ホールドアウト法と交差検証法をまとめてみた

# はじめに
今回、機械学習のモデル検証方法である**ホールドアウト法**と**交差検証法**を簡単にまとめた。

前提知識としてモデルやハイパーパラメータの概要があることが望ましい。

ただ、なくても概念は理解できるように努めたため、理解いただければ幸いである。


# 目次
1.モデル検証とは
2.ホールドアウト法
3.交差検証法
    3-1.k分割交差検証
    3-2.leave-one-out(1個抜き)交差検証
    3-3.層化交差検証
    3-4.その他の交差検証
4.まとめ


# 1.モデル検証とは
機械学習のなかでも教師あり学習において、未知のデータに対する予測を高い精度で行うことが求められている。
そのため、既知のデータを用いて未知のデータを予測するような仕組みを作ることとなる。
このような、入力データに対してある結果（出力）を導き出す仕組みを**モデル**と呼ぶ。
また、モデルの仕組みの中で性能を高めるために、自由に調節できる要素のことを**ハイパーパラメータ**と呼ぶ。

そして、モデルを作成した際にそのモデルが未知データに対しての予測性能を測ることを**モデル検証**と呼ぶ。

![無題のスプレッドシート.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746338/508f7045-0454-aba1-54b3-2104ab019897.jpeg)図1

上記のカラオケの例だと概念をつかみやすいのではないだろうか。
さらに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746338/ff9758aa-ce74-93f5-8b75-83b69fd27c4f.png)図2

**ハイパーパラメータ**が音量やエコー調節のつまみとすれば、概念として理解しやすいのではないかと提案する。
カラオケ機器が正確に音程を理解し元の楽曲（正解）の一致具合を点数化することを**モデル検証**という。


ここで、既知のデータをもとにモデルを作成するため既知データに依存してしまい、未知のデータに対する性能（**汎化性能**）が著しく低下する可能性がある。
この問題を解決する手法を次項以降で紹介していく。
# 2.ホールドアウト法
機械学習において未知なるデータを予測するモデルを作成し、そのモデルの汎化性能（予測性能）を測る方法の一つとして、**ホールドアウト法**がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746338/424a9930-1dc4-cde8-a6ab-de90d3a971a0.png)図3

元データをデータセットとして以下の流れでモデル検証を行う。

**1.データセットを学習データとテストデータに分ける**
**2.学習データを学習データと検証データに分ける**
**3.学習データと検証データから予測モデルを作成する**
**4.予測モデルの評価をテストデータを用いて行う**
※データ分割方法は諸説あり。学習データ：テストデータ（検証データ）＝7:3or8:2等

以上のようなモデル検証法では「データの偏りに弱い」という弱点がある。
分割したデータの片方に特徴的なデータが集まることで、汎化性能が著しく下がる可能性が発生する。
その弱点を解消するために次項の**交差検証法**がある。

# 3.交差検証法
学習データを2分割してモデル検証をしたホールドアウト法に対して、**交差検証法**は3分割以上してモデル検証を行う。

![無題のスプレッドシート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746338/c6dad4d9-a73b-d327-d87e-15e0c7d790d6.png)図4

図6の方法によりホールドアウト法の弱点を克服することができ、汎化性能が向上する。
交差検証法には種類があることから、いくつか紹介していく。

## 3-1.ｋ分割交差検証
交差分割検証の中でもk個に学習データを分割し、そのうちの一つを検証データ、残りのk-1個を学習データとして精度を算出し、その平均をとって評価する方法である。

![無題のスプレッドシート (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746338/8bdbacf8-286d-ec2c-330b-1e2350df3b0d.png)図5

流れとしては

**1.学習データをk個に分割する**
**2.1つのデータを検証データ、残りのk-1個を学習データしてモデル精度を算出**
**3.1と2をk回繰り返す**
**4.出てきた精度の平均をとることでモデル評価する**

以上となる。

特徴として学習データのすべてが検証データになることから、データの偏りによる汎化性能の低下が回避される。

コード例

```python

import numpy as np
from sklearn.model_selection import KFold

X = ["a", "b", "c", "d","e","f","g","h","i","j","k","l"]

kf = KFold(n_splits=4,shuffle=True)

for train, test in kf.split(X):
    print("%s %s" % (train, test))

```

出力結果
[ 0  1  2  3  4  7  9 10 11] [5 6 8]
[0 1 2 3 5 6 7 8 9] [ 4 10 11]
[ 0  3  4  5  6  7  8 10 11] [1 2 9]
[ 1  2  4  5  6  8  9 10 11] [0 3 7]
## 3-2.leave-one-out(1個抜き)交差検証
k分割交差検証の派生として**leave-one-out(1個抜き)交差検証**があげられ、これはｋ分割交差検証では学習不足に陥ってしまう場合に使用される方法である。
データの分割をデータの個数（n）分割することによって学習不足を回避し、少ないデータ数であっても計3回数を増やすことを可能にした。

![無題のスプレッドシート (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746338/ffb11775-bae2-dadf-48f7-4956f9e54a3a.png)図6

流れとして

**1.学習データをn個に分割する**
**2.1つのデータを検証データ、残りのn-1個を学習データしてモデル精度を算出**
**3.1と2をn回繰り返す**
**4.出てきた精度の平均をとることでモデル評価する**

以上となる。

特徴として過学習の回避にはつながるものの、逆に過学習（既知のデータに過剰に適合してしまうこと）になる可能性が高くなるとともに、計算コストが増大することがあげられる。

コード例

```python

from sklearn.model_selection import LeaveOneOut

X = [1, 2, 3, 4]
loo = LeaveOneOut()
for train, test in loo.split(X):
    print("%s %s" % (train, test))

```

出力結果
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]

## 3-3.層化k分割交差検証
k分割交差検証の派生として**層化k分割交差検証**があげられ、これは分類課題において目的変数（分類クラス）のデータにおける比率が偏っている場合に使用される方法である。
データの分割方法を分類クラスの比率に合わせて分割する方法をとるため、クラス比率が偏っている場合に有効な検証方法となる。
![無題のスプレッドシート (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2746338/18d58ff6-022a-24be-e764-b82e81410c5b.png)図7

流れはほとんど同じであるため割愛する。

特徴としてすべてのデータ分割においてクラス比率が同じとなり、比率による精度の偏りを回避することがあげられる。データ抽出を**層化抽出法**を用いていることで上記の特徴を得られるため、詳しく調べたい方は上記のキーワードをもとに検索してみるとよい。

コード例
```python

import numpy as np
from sklearn.model_selection import StratifiedKFold

X = np.ones(12)
y = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]

skf = StratifiedKFold(n_splits=4)

for train, test in skf.split(X, y):
    print("%s %s" % (train, test))

```

出力結果
[ 1  2  3  6  7  8  9 10 11] [0 4 5]
[ 0  2  3  4  5  8  9 10 11] [1 6 7]
[ 0  1  3  4  5  6  7 10 11] [2 8 9]
[0 1 2 4 5 6 7 8 9] [ 3 10 11]

## 3-4.その他の交差検証
他にも状況に応じた交差検証があることから紹介だけしておく。

**シャッフル分割交差検証**
データを分割する前にシャッフルしてからk分割交差検証を行う。

**層化シャッフル分割交差検証**
層化抽出法を用いてデータを抽出し、その抽出したクラス内でシャッフルを行いk分割交差検証を行う。

**グループk分割交差検証**
同じグループ（顧客等の特定の人物を表すもの）が同じになるように、データを分割するk分割交差検証のこと。

以上の交差検証は、これだけの紹介にとどめる。

# 4.まとめ
今回の学習を通じてモデル検証という、作成したモデルの検証方法の考え方や方法を学べたと思う。それを共有できればと思い寄稿した。
実際のコード例も小規模データを作成し掲載できたので、活用方法も示すことができたのではないかと思う。
今回は私自身も初学者のため、図を多く用いて抽象的になったかもしれない。
今後の反省として次回以降の記事に生かしていきたい。