訓練データと検証・テストデータの分布が異なるときの機械学習

### 1. 訓練データ、検証データ、テストデータ
　どうもNegimaruです。今回は、訓練データと検証・テストデータが従う分布が異なるときの機械学習における注意点についてまとめます。まずは、訓練データ、検証データ、テストデータとは何かを簡単に書いておきます。

- 訓練データ：モデルの訓練に使うデータ
- 検証データ：複数のモデルを試したり、ハイパーパラメータをチューニングしたりする際に、訓練したモデルを評価するためのデータ
- テストデータ：検証データを用いて最終的に選んだモデルの性能を測るためのデータ

　機械学習においてまず重要なのは、**検証データとテストデータが同一の分布に従っている**ことです。仮に検証データとテストデータが異なる分布に従うものであった場合、検証データを用いて選んだモデルが、テストデータに対して上手く予想できるモデルとは異なるモデルになってしまう可能性があるからです。例えば、食べ物の写真からカロリーを予測するモデルを作るために、和食の写真の検証データと洋食の写真のテストデータを用意したとします。すると、検証データを用いて和食のカロリー判定に優れたモデルが選ばれますが、このモデルは洋食のカロリーを上手く判定できるとは限りません。このような状況を避けるために、検証データとテストデータが同一の分布に従うことが必要なのです。
　しかし、**訓練データの分布は検証・テストデータの分布と必ずしも一致する必要はありません**。特に、検証・テストデータの分布に従うデータの数が少ないときは異なる分布のデータを訓練集合に入れることはモデルの精度をあげるために有効な手段です。例えば、キノコの写真からそのキノコが毒キノコであるかを判定するアプリを作りたいとします。このとき検証・テストデータとしては、スマホで撮影したキノコの画像を用いるべきです。アプリの最終的な用途が、スマホで撮影されたキノコの判定であるからです。ここで、スマホで撮影されたキノコの画像はモデルの訓練に十分なほどはないとしましょう。このとき、インターネット上にある無数のキノコの画像を訓練集合に加えることで、十分な数の訓練データが用意でき、モデルの精度を上げることができます。ここで注意点は**訓練データにはデータを追加して良いが、検証・テストデータは変更してはならない**ということです。なぜならば、検証・テストデータ（スマホで撮影した画像）と追加したデータ（インターネット上の画像）は分布が異なるからです。例えば、インターネット上の画像は高画質であるが、スマホで撮影した画像は手ブレで見にくいことが多いかもしれませんね。もしインターネット上のデータを検証・テストデータに追加してしまうと、検証・テストデータの分布は最終的な用途（スマホの画像から毒キノコか判定する）を反映していない分布になってしまうのです。そのような検証データとテストデータを通して得られるモデルは、最終的な用途に適したモデルでないかもしれません。

### 2. 訓練データと検証・テストデータの分布が異なるときの機械学習フロー
　訓練データと検証・テストデータが異なるとき、機械学習はどのように進めていけばよいのでしょうか。訓練データと検証・テストデータの分布が同じであり、かつベイズエラー[^1] が0と近似できるときの機械学習の進め方は[以前の記事](https://qiita.com/Negimaru1/items/d8e381c7e4ba71539d1e)で紹介しました。一言でまとめると、**バイアス**（モデルの予測と学習データのずれの大きさ）と**バリアンス**（モデルの予測の分散、つまりモデルの複雑さの度合い）の大きさから次のステップを考えるのでした。今回は、ベイズエラーが0とは限らない場合で、訓練データと検証・テストデータの分布が異なる場合のバイアスとバリアンスについて説明します。以下では、あるクラス分類問題を考えます。ただし、ベイズエラーは人間の誤り率で近似します。

###### 2.1.　バリアンスとデータミスマッチ

　訓練データと検証・テストデータの分布が同じであり、かつベイズエラーが0と近似できるときは訓練データに対する誤り率(Training error)と検証データに対する誤り率(Development error)からバイアスとバリアンスを推定し、学習の次のステップを決定しました。訓練データと検証・テストデータの分布が異なるときもその方法で上手くいくでしょうか。例えば以下のような場合を考えます。

- Human error (proxy for Bayes error): 0%
- Training error: 1%
- Development error: 10%

訓練データと検証・テストデータの分布が同じである場合、以上の結果からバリアンスが大きいと分かります。モデルが訓練データにフィットしすぎている過学習の状態です。しかし、訓練データと検証・テストデータの分布が異なる場合は、Training errorとDevelopment errorの差が大きい原因として以下の2つが考えられます。

- バリアンスが大きい。つまり、過学習している。
- 訓練データと検証データの分布が異なりすぎている（データミスマッチ）。

Training errorとDevelopment errorの情報だけではどちらが原因でTraining errorとDevelopment errorの差が生じているのかがわからず、精度向上のためにとるべき方策が定まりません。そこで、新たに訓練検証データ[^2]を作ります。これは、訓練データと同じ分布に従うが、訓練には用いないデータです。下の図はイメージです。
![training-development.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605268/a28fbedc-64ef-0eff-133b-9915d3bb74d6.jpeg)



###### 2.2. 4つの誤り率
新たに導入した訓練検証データを用いることで、4つ目の誤り率を定義します。そして、これらの誤り率の値から機械学習の次のステップを決める方法を説明します。

- Human error (proxy for Bayes error): 人間の誤り率
- Training error: モデルの訓練データに対する誤り率
- Training-development error: モデルの訓練検証データに対する誤り率
- Development error: モデルの検証データに対する誤り率

2.2.1. シナリオA（学習不足）

- Human error (proxy for Bayes error): 1%
- Training error: 10%
- Training-development error: 11%
- Development error: 12%

このとき、Human errorとTraining errorの差が大きいことからバイアスが大きいことがわかります。モデルが十分に訓練データを表現できていないので、モデルをより複雑にしたり訓練時間を伸ばしたりするのが次に行うべきことです。

2.2.2. シナリオB（過学習）

- Human error (proxy for Bayes error): 1%
- Training error: 2%
- Training-development error: 11%
- Development error: 12%

このとき、Training errorとTraining-development errorの差が大きいことから、モデルが訓練データに過剰にフィットしていて汎化性能が損なわれていることがわかります。次に行うべきことは、正則化を強化したり、訓練データを増やしたりすることになります。

2.2.3. シナリオC（データミスマッチ）

- Human error (proxy for Bayes error): 1%
- Training error: 2%
- Training-development error: 3%
- Development error: 12%

このときTraining-development errorとDevelopment-errorの差が大きいことから、訓練・訓練検証データが従う分布と検証・テストデータが従う分布の差が大きいと考えられます。このデータミスマッチを解消するためには、検証・テストデータに似たデータを収集または生成して訓練・訓練検証データに加えることなどが考えられます。

注）2.2.2と2.2.3においてTraining errorとDevelopment errorの値は同じであるので、Training-development errorを確認しないと過学習とデータミスマッチどちらが生じているのかがわかりません。

###### 2.3. まとめ
　以上を図にまとめると次のようになります。どのerrorとどのerrorの差が大きいかによって次に何をするべきかが決まります。
![training-flow.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605268/65f84bd5-1492-144a-bd82-be8bf3bec3bd.jpeg)


[^1]: 理想的なモデルが達成する誤り率のことです。どのようなモデルを持ってきても誤り率をこの値より小さくすることはできません。ベイズエラーは、データそのものが確率的であるとき0になりません。

[^2]: 正式な日本語名はわかりませんでした。すみません。参考にした英語の講座ではTraining-development setと表記していました。

### 3. 参考文献

- [Courseraの講座](https://www.coursera.org/learn/machine-learning-projects?specialization=deep-learning)