k-Fold Cross Validation(交差検証)を解説する【機械学習入門9】

グローバルでAI開発者・データサイエンティストを目指す人向け
おすすめUdemy講座一覧

TOEIC300→海外就職の英語勉強法まとめ

こんにちは,米国データサイエンティストのかめ(@usdatascientist)です.

データサイエンス入門の機械学習編第9回です!(講座全体の説明と目次はこちら)

追記)機械学習超入門動画講座を公開しました!動画で効率よく学習をしたい人はこちら(現在割引クーポン配布中です)

前回の記事では汎化性能を測る手法としてLOOCVについて述べました.

LOOCVは,データの数やモデル構築が簡単な場合はいいんですが,一般に機械学習は学習データが多かったり,モデル構築に時間がかかることが多いです.(高い精度のモデルを構築するには,大量のデータが必要だったり,計算コストが高いアルゴリズムを使う必要がでてきます)

そこで,今回の記事で紹介するk-Fold Cross Validation (k-Fold交差検証)の出番です.K-Fold Cross Validationは,hold-outとLOOCVの中間的な手法で,実際の業務では最も使われる汎化性能の測定手法です.

なので,今回の記事でしっかりk-Fold Cross Validationを学び,自分で学習したモデルの汎化性能を測定できるようにしましょう!

k-Fold Cross Validation

k-Fold Cross Validationは,hold-outLOOCVの中間のような手法です.日本語ではk-Fold交差検証といったりしますが,日本語でもCross Validation(クロスバリデーション)というので本講座では英語表記で書いていきます.また,略してk-Fold CVと略したり,単にCross Validation やCVといったらk-Fold Cross Validationを指します.

k-Fold Cross Validationは,手元のデータをk個のグループに分割して,k個のうちひとつのグループをテストデータとして,残りのデータを学習データとします.それを全てのグループがテストデータになるようk回繰り返します.

図にするとわかりやすいと思います.

上図はk=5の例です.

データを5分割して,それぞれのグループをテストデータ,それ以外のデータを学習データにしてモデルを構築し精度を測ります.(LOOCVでは各データで行われていたことが,k-Fold Cross Validationでは各グループごとに行われるということですね,)

これを5回繰り返すので5つの結果がでますが,それを平均した値を最終的な精度の結果とします.この辺りはLOOCVと同じです.

このように,各データやグループに分けて交差(Cross)させて検証(Validation)するので,Cross Validationというのですね!

k-Fold Cross ValidationをPythonで実装する

それでは今回もPythonでk-Fold Cross Validationを実装してみましょう!

前回同様,今回もtipsデータセットを使って,total_billからtipを予測する予測モデルを構築し,k-Fold Cross Validationで汎化性能を測ってみましょう.

k-Fold Cross ValidationをPythonで実装するには, scikit-learn.model_selectionKFold クラスを使います.前回やった LeaveOneOut クラスと同じ要領で使うことができます.例えば以下のように cv インスタンスを生成し, cv.split() に学習データ X を入れると,それぞれの交差の train_index および test_index を返すジェネレータの役割をします.

インスタンス生成時の引数は, n_splits にk, random_state に乱数の種, shuffle にbooleanをセットしてグループ分けの前にシャッフルするかを決めます.

上記のコードを実行すると, train_indextest_index がそれぞれのイテレーションで異なっているのがわかると思います.

今回はk=5の5-Fold Cross Validationを実装してみましょう.

これも,前回の記事と同じですね.

毎回のイテレーションで sme を計算して,その結果を sme_list に入れて最後に平均を求めています.

もっと簡単にscikit-learnでCross Validationを実行する

先のコードや前回のLOOCVのコードでは, .split() をcallしてイテレーションを回す必要がありました.

実は,scikit-learnにはもっと手軽にCross Validationを実行できる関数があります.

めちゃくちゃ便利でよく使うので,是非使えるようにしましょう!!

scikit-learn.model_selectioncross_val_score 関数を使います.

cross_val_score 関数には,主に以下の引数を入れます.

estimator : scikit-learnの機械学習モデルのインスタンス
X : 学習データのX
y : 学習データのy
scoring : 計算する評価指標(文字列で指定)(後述)
cv : KFoldLeaveOneOut のインスタンスでCross Validationをするジェネレータ
n_jobs : 並列処理の際のプロセッサーの数. -1 を指定すると使える全てのプロセッサーを割り当ててくれる

先ほどの5-Fold Cross Validationを cross_val_score を使って実行すると以下のようになります.

すると,各交差での scoring に指定した評価指標をリストにして返してくれるので,以下のように平均を取ればOKです.

今回はMSE(mean squared error)を指標にしたかったので, scoring 引数には "neg_mean_squared_error" を指定しました.

scoring 引数に指定する文字列は公式ドキュメントに一覧があるので確認してください.

cross_val_score 関数に使われる精度指標は基本的に「大きい方が精度が良い」ようにしています.SMEは”損失”を表す指標なので,そのままでは「小さい方が良い」指標になってしまうので,負の符号をつけて「大きい方が良い」ようにしています.

そのため, scoring に指定している文字列にもnegatedのnegが接頭辞にあり,結果も不の値の-1.08になっているのがわかります.

符号以外は先のコードの結果と一致していますね.このように,イテレーションを回すことなく一行でCross Validationを実行できる素敵関数なのです!!

LeaveOneOut のインスタンスでも同様にしてLOOCVを実行できます.興味がある人は試して,前回の結果と同じになることを確認しましょう

まとめ

今回はk-Fold Cross Validationのやり方とその実装を紹介しました.Cross Validationの結果をみると,それぞれの交差で(当然ですが)結果が多少異なっているのがわかると思います.ひとつひとつの交差ではhold-outが行われていると考えると,どれだけhold-outはランダム性があり分散が高いかがわかると思います.

普通機械学習のモデルを評価する際にはk-Fold Cross Validationでの評価の結果を報告するのがほとんどです.また,よく使われるのはk=5とk=10なので,これも覚えておきましょう!

  • k-Fold Cross Validationは,最も一般的に使われる汎化性能を測る手法
  • k-Fold Cross Validationは,hold-outとLOOCVの中間的な手法であり,k個のグループに分けてCross Validation(交差検証)する
  • scikit-learn.model_selectionKFold クラスを使ってk-Fold Cross Validationを実装する
  • scikit-learn.model_selectioncross_val_score 関数を使うことで簡単にCross Validationを実行できる

次回の記事では,回帰モデルの評価指標について解説します.今まではMSEを使ってましたが,他にも回帰モデルを評価する指標があるので使えるようにしましょう!

それでは!

追記)次回の記事書きました!

回帰モデルの評価指標を一挙に解説(MSE, RMSE, MAE, R-Squared等)【機械学習入門10】