scikit-learnによるモデル選択(2)

scikit-learnによるモデル選択(2)

<<前の記事に戻る

前回はモデルの正解率をscikit-learnで計算する方法について書きました。
150個体全てのアヤメデータをモデルの訓練に使用し、テストにも同じデータを使ったところ、
K=1のK近傍法では100%の正解率となりました。しかしこれで良いでしょうか?

K=1のK近傍法は、説明変数Xの値が最も近い訓練データにおけるyの値を予測値とするため、
訓練データをそのままテストデータに使えば必ず正解率は100%になってしまいます。
また、一般的にK近傍法でKを少なくするとノイズの影響を受けやすく、複雑なモデルになってしまいます。
これを過学習(overfitting)といいます。

過学習してしまうモデルが選ばれないようにするには、
全データセットを訓練データとテストデータに分割します。

scikit-learnには分割用のtrain_test_split関数があるのでこれを使うことにします。
このとき、test_size=0.4と指定することで、全データ150個のうち40%の
60個がテストデータ、残りの90個が訓練データになります。
random_stateオプションでは標本サンプリングの乱数シードを指定しています。
指定しなければ毎回異なった訓練/テストデータに分割されますが、
指定しておくことで再現性のある分割ができます。

<code>************************************************************
#Xとyを訓練データとテストデータに分割する
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=4)

#訓練データに対してロジスティック回帰
logreg = LogisticRegression()
logreg.fit(X_train, y_train)

#テストデータに対して予測値を計算
y_pred = logreg.predict(X_test)

#予測値の正解率を計算
print metrics.accuracy_score(y_test, y_pred)

#K近傍法(K=5)
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train,y_train)
y_pred = knn.predict(X_test)
print metrics.accuracy_score(y_test, y_pred)

#K近傍法(K=1)
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train,y_train)
y_pred = knn.predict(X_test)
print metrics.accuracy_score(y_test, y_pred)
*************************************************************************

モデルの評価に訓練データとは別のテストデータを使ったことで正解率は
ロジスティック回帰 : 0.95
K近傍法(K=5) : 0.966666
K近傍法(K=1) : 0.95
となりました。

以上が訓練/テスト分割によるモデル選択の仕方です。

訓練データと同じデータをそのままテストに使った場合には
モデルが複雑になればなるほど正解率が上がりますが、
訓練データとテストデータを分割することで
複雑すぎるモデルに対してはペナルティを与えることになります。

訓練/テスト分割の短所はテストデータの違いによって正解率の分散が大きくなってしまうことですが、
手軽に評価が実行できるので、実用上はとても有用です。
なお、分散が大きくなる問題に関してはK-fold交差検定という方法で解決することができます。

【参考記事】
no free hunch「scikit-learn video #5: Choosing a machine learning model」
http://blog.kaggle.com/2015/05/14/scikit-learn-video-5-choosing-a-machine-learning-model/