交差検証のcross_val_scoreって、stratifyなのかな??
train_test_splitのときは、答えデータが訓練とテストで同じ割合になるようにデータ分割をしたよね?
cross_val_scoreは、なにもしないとstratifyなデータになるみたいだね。
前回の交差検証でデータ分割を行ったとき、cross_val_scoreを使えばなにも考えずに交差検証という分割方法で機械学習の汎化性能が計測できることがわかりました。でも、よく考えたら、scikit-learnのアヤメのデータは、「setosa」「verginica」「versicolor」という順番に並んでいるので、普通に三分割したら、訓練データが「setosa」だけになったりしているのではないか・・・と心配になりました。
stratifyなデータの意味については、こちらの記事をご参照ください。
こんな人の役にたつかも
・cross_val_scoreがstratifyになっているか気になる方
・機械学習プログラミングでデータ分割を行いたい方
・機械学習プログラミングを勉強したい方
scikit-learnの公式ドキュメントで確認
なにはともあれ、公式の仕様書を確認してみればOKということで、リンクを貼り付けます。
ライブラリの仕様書などは、英語が多いので、読むことができると非常に役に立ちますね。ちなみに私は高校までしか真面目に勉強してません^^;
雰囲気とGoogle翻訳先生の力をかりてなんとなく読みます 笑
URLのcvパラメータには、↓のようなコメントがあります。
「For integer/None inputs, if the estimator is a classifier and y
is either binary or multiclass, StratifiedKFold
is used. In all other cases, KFold
is used.」
これは、「cv=整数」となっているか、cvというパラメータを書かない場合は、デフォルトで「StratifiedKFold」が選択されるということですね。KFoldは、k分割する、という意味なので、基本的にはデータをStratifyにしながらK分割します、とのことですね。
英語は難しいけど、読めたほうがいいのか~でも、AIが進化してるから大丈夫だね!
なんも言えないです
train_test_splitを導入してワークフローを見直す
英語に苦戦しつつ、公式ドキュメントを眺めていたら、交差検証の使いどころが詳細に記載されていました。すごい勉強になります・・・
交差検証ですべてのデータを利用してしまうのではなく、あらかじめtrain_test_splitで訓練データとテストデータに分割しておいて、訓練データに対して交差検証を行うという流れを行うことで、より汎化性能をしっかりと計測することができるんですね。
イメージとしてはこんな感じかと思います。参考にしたURLも記載します。
交差検証をパラメータ調整のために使用して、最終的に分けておいたテストデータを入れるのがミソです。
プログラムでやってみよう
importからアヤメデータの入力まではいつも通りやります。今回は、train_test_splitも使うので、importしておきます。
from sklearn.datasets import load_iris
#ホールドアウトのimport
from sklearn.model_selection import train_test_split
#交差検証のimport
from sklearn.model_selection import cross_val_score
#k-最近傍法のimport
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
panda_box = load_iris()
X = panda_box.data
y = panda_box.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.5, stratify=y)
JupyterNotebookまたは、Colaboratoryでやっている場合は、ブロック単位でプログラムを実行できるのがとてもメリットですね。パラメータの調整をするときは、次のブロックを何回も実行させればよいだけですので。
次に、訓練データのみで交差検証を行います。cross_val_scoreに与えるデータが「X_train」と「y_train」となりました。ここでよいスコアが出るように、kの値を調整したり、交差検証の分割数を変更したりしてみました。
knc = KNeighborsClassifier(n_neighbors = 9)
#交差検証を行う。
score = cross_val_score(knc, X_train, y_train, cv=3)
#結果の表示
print("交差検証の結果")
print(score)
print("交差検証の平均")
print("{:.4f}".format(np.mean(score)))
今回は、だいたい94%の正解率となりました。
交差検証の結果
[0.88 0.96 1. ]
交差検証の平均
0.9467
最後に、k最近傍法で訓練を行います。cross_val_scoreは、評価のためにありますので、k最近傍法には「fit」で訓練させる必要があります。
最後に、テストデータの評価を行います。
#訓練をする
knc.fit(X_train, y_train)
#モデルの評価(75個すべての予測結果の正解率)
print("{:.4f}".format(knc.score(X_test, y_test)))
そして、交差検証で決定したパラメータのk最近傍法をつかってテストデータを評価したところ、同じ94%が得られました。
0.9467
train_test_splitはもう出てこないと思ったよ、よかったね。
すべてのものに意味があり、役割があるんだね