テストエンジニアが機械学習してみた備忘録

広島とジト目が好きなテストエンジニアが機械学習に手を出した備忘録。

KaggleのタイタニックでSVMの練習

前回はKaggleのタイタニックをランダムフォレストでやってみて、下から数えたほうが早いくらいの成果しか出ませんでした。今回はSVMsupport vector machine)を試してみたいと思います。

1.4. Support Vector Machines — scikit-learn 0.19.1 documentation

例に漏れずSVMも分類用のClassificationと回帰用のRegressionがあり、前者はSVC、後者はSVRと略されるようです。で、色々とチューニングする要素はあり、むしろチューニングしないと性能が出ないっぽいですが、何から手をつけていいのかわからない…

というわけで、とりあえず参考サイトを参考にSVMに関する雑多な知識をメモします。 末尾に参考にした記事のURLを貼っているので、詳細はそちらをご参照ください。

SVMと標準化

はじパタ曰く「データを平均0、分散1に変換すること」。測定単位の影響を取り除くための手法であり、SVMにおいても効果を発揮するらしい。scikit-learnにおいてはsklearn.preprocessingのStandardScalerで以下のように実現できます。

from sklearn.preprocessing import StandardScaler

'''
dfに分析対象のデータフレームを読み込んでおく
'''

std = StandardScaler()
df_std = pd.DataFrame(
    std.fit_transform(df.loc[:, ['Age', 'Fare']]),
    columns=['Age', 'Fare']
)
df_std.index = df.index
df['Age'] = df_std['Age']
df['Fare'] = df_std['Fare']

今回は元データのAgeとFareに対して標準化したかったので、 それらの列を抽出したデータフレームにStandardScaler()のfit_transformメソッドを適用し、元データと置き換えています。

カーネルトリック

SVMは本来は線形分離可能なデータしか分類できないが、非線形カーネル関数を用いることで線形分離不可能なデータも分類可能になるそうです。これは、データを線形分離可能な高次元空間に写像することで実現されるとのこと。

カーネル関数

scikit-learnでは以下が指定可能。

  • RBF: Gaussian
  • 線形
  • 多項式
  • シグモイド
  • ユーザ定義

主に非線形のRBFカーネルが使われるとのこと。scikit-learnのデフォルトもRBF。

ハイパーパラメータCとgamma

Cは誤りをどの程度許容するかを表すパラメータで、大きいほど誤りを許容しなくなる。gammaはRBFやシグモイドといったカーネルを用いる場合のパラメータで、大きほど決定境界を複雑にする効果がある。つまり、Cとgammaを共に大きくすると、誤りを許容しない複雑な決定境界を引くので、過学習しやすいと解釈しました。

グリッドサーチ

sklearn.model_selection.GridSearchCV — scikit-learn 0.19.1 documentation

パラメータをあらかじめ定めた範囲で変化させてcross validationを行い、最も良いモデルを返す。下記の例ではCとgammaについて、それぞれ1, 10, 100の3つの値を候補とし、全9個の組み合わせの中からaccuracyのよいパラメータを選んでいます。

from sklearn import svm
from sklearn.model_selection import GridSearchCV

'''
訓練データとしてtrainXとtrainYを用意しておく
'''

# SVM
svc = svm.SVC()
params = {
    "C": [1, 10, 100],
    "gamma": [1, 10, 100]
}
gs = GridSearchCV(svc, params, cv=10, scoring='accuracy', n_jobs=-1)
gs.fit(trainX, trainY)
print(f"Best Score: {gs.score(trainX, trainY)}")
print(f"Best Params: {gs.best_params_}")

なお、grid_search.GridSearchCVは0.20で廃止される模様。

scikit-learnにおけるSVM

SVC、LinerSVC、NuSVCの3種類が用意されている。SVCとNuSVCは誤りの許容の仕方の表現が異なるだけでほぼ同じ、LinerSVCは線形カーネルを用いることに特化しているとのこと。

SVRについても同様。

結果

訓練データを標準化し、グリッドサーチでパラメータを調整してSVMを適用したところ、0.77511にスコアが上昇し、2018年3月6日時点で1万人中5648位まで上昇しました。さらに少しパラメータを調整してみましたが、あまり改善は見られなかったので、さらに上を目指すにはデータの前処理を見直すべきかもしれません。特に欠損値の扱いが雑なので、その辺りを勉強がてら見直してみようと思います。

参考