はじめに

データサイエンティスト養成講座の第二回を受けてきました。

扱った内容は、

  • 決定木
  • クロスバリデーション
  • グリッドサーチ

講座では、Rを使うのだけれども、Pythonにもなれておきたいので、

講座の内容をPythonで復習しました。

ついでに、kaggleのタイタニック問題を決定木で解きました。

今回のコードは、githubにあげています。以下は、コードの抜粋です。

Pythonで決定木

Pythonで決定木を使うには、scikit-learnライブラリを使う。

from sklearn import tree
clf = tree.DecisionTreeClassifier(random_state=17)
clf.fit(X, y)

簡単!

クロスバリデーション with KFold

決定木は、max_depthパラメータを大きくすればするほど精度が上がっていくが、汎化性能が下がっていく。なので、クロスバリデーションという方法を使って、過学習が起こっていないかチェックすることが重要になる。

from sklearn.model_selection import KFold
from sklearn import metrics
from sklearn.metrics import accuracy_score
K = 5
kf = KFold(n_splits=K, shuffle=True, random_state=17)

score_train_tmp = 0
score_test_tmp = 0

for train_index, test_index in kf.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

    # 構築データでモデル構築
    clf.fit(X_train, y_train)

    # 構築データの予測値
    pred_train = clf.predict(X_train)

    # 構築データのaccuracy
    auccuracy = accuracy_score(pred_train, y_train)

    #構築データのaccuracyを足していく
    score_train_tmp+=auccuracy

    #検証データの予測値
    pred_test = clf.predict(X_test)

    #検証データのaccuracy
    auccuracy = accuracy_score(pred_test, y_test)

    #検証データのaccuracyを足していく
    score_test_tmp+=auccuracy
score_train_tmp/K
0.82463676190176005

score_test_tmp/K
0.80247944259619608

構築データと検証データのスコアが近ければ、過学習が起こっていないと判断できる。これが乖離していると過学習が起こっているので、パラメータチューニングが必要。

グリッドサーチ

最適なパラメータをしらみつぶしにパラメータを組み合わせて探索していく方法をグリッドサーチという。普通はfor文を回してパラメータを変えてスコアを見ることで調整していく。しかし、scikit-learnには、GridSearchCVというグリッドサーチをするための専用のクラスが用意されている。

これをつかえば、煩わしいfor文のネストを書かずとも、複数パラメータに対して探索をすくことができる。

調べたいパラメータをまずは辞書で定義する。

from sklearn.model_selection import GridSearchCV

# use a full grid over all parameters
param_grid = {"max_depth": [2,4,6,8,10],
              "max_features": [log2, sqrt,auto],
              "min_samples_split": [2, 3, 5],
              "min_samples_leaf": [1,5,8],
              "criterion": ["gini", "entropy"]}

次に、GridSearchCVを読んで、グリッドサーチを実行する。

tree_grid = GridSearchCV(estimator=clf,
                 param_grid = param_grid,   
                 scoring="accuracy",  #metrics
                 cv = K,              #cross-validation
                 n_jobs =-1)          #number of core

tree_grid.fit(X,y) #fit

tree_grid_best = tree_grid.best_estimator_ #best estimator
print("Best Model Parameter: ",tree_grid.best_params_)
print("Best Model Score    : ",tree_grid.best_score_)
Best Model Parameter:  {criterion: gini, max_depth: 6, max_features: log2, min_samples_leaf: 8, min_samples_split: 2}
Best Model Score    :  0.812570145903

便利だ。素晴らしい。

しかし、このパラメータチューニングした結果をサイトにて提出しても、大したスコアは出ない。これは、特徴量エンジニアリングがそもそもしょぼいという問題がある。