機械学習

交差検証(Cross Validation)で過学習を抑える

本日は過学習を防ぐ上で欠かせない交差検証についてまとめていきます。

交差検証(Cross Validation)は何故行うのか?

機械学習でモデルの性能評価を行う場合、一般的にやられているのは、全体のデータを訓練データテストデータに分割を行い、訓練データを用いてモデルを作成後、テストデータでモデルの性能評価を行います。

何を予測するにしても重要なのは、手元にあるデータの性能のみではなく、未知のデータに対する予測精度のため、このように訓練データとテストデータに分けることで、疑似的に未知データを作るのが理由となります。

pythonの場合train_test_split関数がsklearnにあり、これを用いると訓練データとテストデータをそれぞれ75%と25%にランダムに分割することができます(任意の値に設定できます)

しかし、この方法だと訓練データとテストデータで異なる性質のものが偏って分割された場合(例えば極端に予測が難しいデータがテストデータに分割された場合)など、本来の目的である「未知のデータに対する予測精度」を適切に見積もれなくなってしまいます。

yaaku

分布が異なるデータで機械学習は難しい…

 

データの性質にもよりますが、kaggleなどのコンペでは交差検証(Cross Validation)と呼ばれる、4~5分割(任意の分割数)を行うことによるモデルの評価方法が使用されています。

今回はメジャーな下記3点について紹介していきます。

・k-分割交差検証(k-fold cross-validation)

・層化k分割交差検証(stratified k-fold cross-validation)

・グループ付き交差検証(GroupKFold)

k分割交差検証(k-fold cross-validation)

k分割交差検証はよく用いられる分割方法で、データセットを任意の数k個に分割します。ここでは、k=5とした場合、全体のデータの1/5をテストデータ、残りの4/5を訓練データとしてモデルを構築して評価を行います。

分割数が5なので、それぞれのデータ(全体の4/5のデータ×4)に対するモデルを作成することができるため、ここでは5個のモデルが作成できます。

分割されたデータをFold 1~5と呼びます。特徴としては分割の仕方がランダムであることが挙げられます。したがってクラスの偏りなどは、考慮した分割ではないので冒頭に上げた問題は残ったままになるので注意が必要です。

ここでは、5個モデルを作成しており、全てのデータは必ず一度はテストデータとなるため、全てのデータでの評価が可能となります。評価の仕方は2つの考え方があり、各Fold毎で評価指標を計算して平均を取る場合と、全体のデータ評価指標を計算して評価する場合に分かれます。

層化k分割検証(stratified k-fold cross-validation)

次に層化k分割検証(k-stratified)ですが、先ほど紹介したKFoldでは下記のようにターゲットのクラスに偏りがある場合、

シャッフルをせずに順番にkfoldで分割して学習を行うと、適切なモデルができないのは直感的に理解できます。

そこで層化k分割交差検証では各分割内でクラスの比率が同じようになるように分割を行います。

こうすることで訓練データとテストデータのラベルの分布が同等になるため、先ほどのirisのようにデータを分けた際にあるクラスが異常に偏っているという状況を避けることができます。

クラスに偏りが大きい場合などは、こちらを検討することが推奨されます。

グループ付き交差検証(GroupKFold)

最後にグループ付き交差検証です。これはデータの中に密接に関係するグループがある場合に用いられます。

yaaku

必要性がイメージしにくい…

例えば顔の画像から感情を予測しようとするときに、同じ人の笑ってる顔と泣いている顔がテストデータと訓練データに入っていたとすると、別々の人の感情認識より楽になってしまいます。

そのほかにも医療データなどを扱いモデルを作成する際、同じ被験者から得られたデータが学習データとテストデータ両方に入るとそうでない場合と比較してテストデータの予測精度が高くなることが想像できます。

この場合、未知データに学習時に用いられた人と同一人物が含まれる可能性が大きい場合はテストデータと訓練データに同一の人が含まれていても問題ないケースもあります。

ただ、レントゲンから診断を行うモデルなどを考えた場合、未知データとして入手するのは非同一人物になるのが一般的かと思われるので、そのような場合にgroupkfoldを使用するべきとなります。

groupkfoldの必要性は(痛い目を見ないと)中々伝わりにくいところでもあるので、groupkfoldを使うべき問題でkfoldで予測精度を評価してしまうケースというのは意外に多いのではないかと思われます。

まとめ

kaggleでは最初から訓練データとテストデータが分けて与えられており、交差検証を行うのは訓練データに対してとなります。(なので訓練データ、検証データ、テストデータの3種類のデータセットに分けられます)

ここでの肝は、訓練データと検証データの分割の仕方を、いかに訓練データとテストデータの分割の仕方に似せられるかというところで勝負が決まります。

そのほかにもgroupkfoldとkstratifiedを合わせた、groupkfoldstratifiedなどgroup関係を維持したまま、ターゲットのクラスの比率を同一にする方法などが使われていたりします。

機械学習のモデルを構築する上でかなり大事な要素だと思うので、そのほかに関してはまたの機会にまとめていきます。