※記事内に商品プロモーションを含むことがあります。
はじめに
モデルの性能を検証するとき、データを学習用と検証用に分割します。これは、未知のデータに対してもモデルの精度が良いこと(汎化性能)を評価するためです。より安定して汎化性能を評価するため、データの分割方法を何度も変えて評価します。これを交差検証 (cross validation) と呼びます。
交差検証にはいくつか種類がありますが、ここでは次の手法を説明します。
- k分割交差検証 (k-fold cross validation)
- 層化k分割交差検証 (stratified -)
また、この記事ではPythonとScikit-learnによるサンプルコードも示します。実行環境は以下の通りです。
- Python: 3.9.7
- NumPy: 1.20.3
- sklearn: 0.24.2
k分割交差検証
k分割交差検証では、データをk個のサブセットに等分割します(kの値は5~10程度にすることが多いです)。まず、この内の1個を検証データとして除き、残りのk-1個のデータでモデルを学習します。その後、検証データで精度などを評価します。次に、今度は別のサブセットを検証データとして、他のk-1個で学習・評価します。検証データを次々と変更し、これをk回繰り返します。最終的にk回分の評価結果(精度など)が得られることになります。なお、k分割交差検証の課題は、学習と検証をk回繰り返すため処理時間が掛かることです。
層化k分割交差検証
データに偏りがある場合、単純なk分割交差検証ではうまくモデルを評価できないことがあります。例えば、2クラス分類問題で、データの90%をクラスA, 残りの10%をクラスBが占める場合を考えます。このようなデータを適当に分割すると、あるサブセットにはクラスBが全く含まれていない、という可能性もあります。
層化k分割交差検証では、各クラスのデータをそれぞれk分割することによって、偏ったデータに対処できます。すなわち、各サブセット内のクラスの比率を、全体データにおける比率と等しくします。
scikit-learnの交差検証
KFoldクラスによるk分割交差検証
scikit-learnではsklearn.model_selection.KFold
というクラスにk分割交差検証が実装されています。
|
|
主なパラメータの意味は以下の通りです。
n_splits
(int
): 分割するサブセットの数。デフォルト値は5
(バージョン0.22より前は3
)。shuffle
(bool
):True
の場合、データをシャッフルする。デフォルト値はFalse
.random_state
(int
):shuffle=True
の場合、シャッフルするランダムシードを指定する。デフォルト値はNone
(実行の度に結果が変わる)。
また、主なメソッドは以下の通りです。
split(X)
: 特徴量データX
(行がサンプル、列が特徴量)に対し、学習データと検証データの各インデックスを返す。
KFoldクラスの使用例
KFold
クラスの使用例を示します。X
は行がサンプル、列が特徴量の説明変数です(PandasのDataFrameなどでも可)。Y
は目的変数です。
まず、データをシャッフルしない場合の例を示します。
|
|
実行結果
以下のように、学習データ (TRAIN
) と検証データ (TEST
) の各インデックスが得られます。分割数を3にしたため、ループ回数は3になっています。また、test_index
のデータはシャッフルされていない(順に得られている)ことが分かります。
|
|
次に、先ほどと同じデータに対し、シャッフルして分割します。
|
|
実行結果
以下のように、学習データと検証データの順序がシャッフルされました。
|
|
StratifiedKFoldクラスによる層化k分割交差検証
scikit-learnではsklearn.model_selection.StratifiedKFold
というクラスに層化k分割交差検証が実装されています。基本的な使用方法はKFold
クラスと同じです。
|
|
主なパラメータの意味は以下の通りです。
n_splits
(int
): 分割するサブセットの数。デフォルト値は5
(バージョン0.22より前は3
)。shuffle
(bool
):True
の場合、データをシャッフルする。デフォルト値はFalse
.random_state
(int
):shuffle=True
の場合、シャッフルするランダムシードを指定する。デフォルト値はNone
(実行の度に結果が変わる)。
また、主なメソッドは以下の通りです。
split(X, Y)
: 説明変数X
(行がサンプル、列が特徴量)、目的変数Y
に対し、Y
の比率が均等になるような学習データと検証データの各インデックスを返す。
StratifiedKFoldクラスの使用例
StratifiedKFold
クラスの使用例を示します。X
は行がサンプル、列が特徴量の説明変数です(PandasのDataFrameなどでも可)。Y
は目的変数であり、0
または1
の値を取ります(2クラス分類問題を想像してもらえればよいと思います)。Y
の3分の2が0
, 残りが1
であり、不均衡なデータです。
まず、データをシャッフルしない場合の例を示します。
|
|
実行結果
以下のように、学習データ (TRAIN
) と検証データ (TEST
) の各インデックスが得られます。分割数を2にしたため、ループ回数は2になっています。各ループのtest_index
には、Y
の値が0
となるインデックスが2個、1
となるインデックスが1個含まれており、均等に分割されています。また、TEST
はシャッフルされていない(順に得られている)ことが分かります。
|
|
次に、先ほどと同じデータに対し、シャッフルして分割します。
|
|
実行結果
以下のようにデータは均等に分割されたまま、学習データと検証データの順序がシャッフルされました。
|
|