1. 序章

このチュートリアルでは、機械学習でテストセットを生成するために使用される手法である層化抽出法を確認します。 次に、それを実装する方法を説明し、アプリケーションの例を示します。

2. サンプリング手法

テストセットを作成することは、機械学習モデルを評価する際の重要なステップです。 テストセットを作成する最も簡単な方法は、大規模なデータセット(通常は元のデータセットの20 % o f)からランダムにいくつかのインスタンスを選択することです。 統計では、インスタンスのサブセット(サンプル)がより大きなセット(母集団)からランダムに選択されるため、この方法は単純ランダムサンプリングと呼ばれます。 インスタンスの各サブセットは、他の要素のサブセットと同じ確率でサンプルとして選択されます。

元のデータセットが十分に大きい場合は、通常、ランダムサンプリングで問題ありません。 そうでない場合は、サンプリングエラーのためにバイアスが発生します。 層化抽出は、母集団をサブグループに分割できる場合のサンプリングエラーを減らすサンプリング方法です。 母集団をstrataと呼ばれる同種のサブグループに分割し、各サブグループ内で単純ランダムサンプリングを適用することにより、層化サンプリングを実行します。

結果として、各層のパーセンテージが保持されるため、テストセットは母集団を表します。 層はばらばらにされるべきです。 したがって、母集団内のすべての要素は1つの層にのみ属している必要があります。

それでは、実際の例を考えてみましょう。 イタリアの人口は男性48.7人と女性51.3人であるため、イタリアでの調査は、この比率を維持しながら個人のサンプルを選択することによって行う必要があります。 調査サンプルに1000人の個人が含まれている場合、層化抽出法は正確に487人の男性と513人の女性を選択します。 単純ランダムサンプリングを実行すると、男性と女性の適切な割合が維持されず、調査結果が大幅にバイアスされます。

3. 層化抽出に関連するステップ

次の手順に従うことで、層化抽出を簡単に実装できます。

  • サンプルサイズを設定します。サンプルのインスタンス数を定義します。 通常、テストセットのサイズは元のデータセットの20 % o fですが、データセットが非常に大きい場合はそれよりも小さくなる可能性があります。
  • データセットを階層に分割する:このステップでは、母集団は同様の機能に基づいて同種のサブグループに分割されます。 母集団の各インスタンスは、1つの階層にのみ属している必要があります。
  • 各層に単純ランダムサンプリングを適用する:ランダムサンプルは、最初のステップで定義された同じ比率で各層から取得されます。

ここでは、手順を概略的に示します。

4. 利点と制限

層化抽出は、母集団内の各グループがサンプル内で適切な表現を受け取ることを保証します。 母集団を同種のサブグループに分割できる場合、この手法はランダムサンプリングよりもモデルパラメーターのより正確な推定を提供します。

ただし、単純ランダムサンプリングは、母集団をサブグループに分割できない場合、母集団内の差異が多すぎるため、より有利です。

5. 例

次に、数字が9であるかどうかを予測する二項分類子の例を考えてみましょう。 分類器のパフォーマンスを評価するために、層化抽出法を使用して K-Fold CrossValidationを実行します。 次に、PythonパッケージScikit-Learnで提供されるStratifiedKFoldクラスを利用します。

MNISTデータセットのトレーニングセットを使用して分析を行い、次の範囲で正規化します。

import numpy as np
from keras.datasets import mnist

(x, y), (_, _) = mnist.load_data()
x = x.reshape(-1, 28*28) / 255.0

次に、この二項分類タスクのターゲットベクトルを作成します。

y = (y == 9) 

ネガティブインスタンス(-9ではない)はポジティブインスタンス(9)よりも頻繁であるため、このデータセットは不均衡であることに注意してください。

次に、Scikit-Learn を使用して、階層化されたK分割交差検定を使用して確率的勾配降下(SGD)分類器をトレーニングおよびテストします。

from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import StratifiedKFold

skfolds = StratifiedKFold(n_splits=3)
splits = skfolds.split(x, y)
for i, (train_index, test_index) in enumerate(splits):  
  x_train = x[train_index]
  y_train = y[train_index]
  x_test  = x[test_index]
  y_test  = y[test_index]
  clf = SGDClassifier()
  clf.fit(x_train, y_train)
  y_pred = clf.predict(x_test)
  accuracy = np.mean(y_pred == y_test)
  print("[SPLIT %d]"%(i+1))
  print("Percentage of digit 9 in the original dataset: %.2f %%"%(np.mean(y==True)*100))
  print("Percentage of digit 9 in the training set: %.2f %%"%(np.mean(y_train==True)*100))
  print("Percentage of digit 9 in the test set: %.2f %%"%(np.mean(y_test==True)*100))
  print("Accuracy: %.4f"%accuracy) 

各反復で、コードは層化サンプリングを使用してデータセットを分割し、トレーニングフォールドで分類器をトレーニングし、テストフォールドで推論を行い、全体的な精度を評価します。 最後に、元のデータセット、トレーニングセット、および各反復でのテストセットのポジティブクラスに属するインスタンスの割合を出力します。

ポジティブクラスのパーセンテージは、期待どおりに分割ごとに保持されます。

次に、層化抽出なしのK分割交差検定について考えてみましょう。 上記のコードでは、StratifiedKFoldKFoldクラスに置き換える必要があります。

from sklearn.model_selection import KFold
skfolds = KFold(n_splits=3)

これで、次の出力が得られます。

層化抽出法を使用していないため、各分割内の元のデータセット、トレーニングセット、およびテストセット間で、陽性クラスの割合の割合が大きく異なることがわかります。

6. 結論

この記事では、テストセットを生成するために機械学習で使用されるサンプリング手法である層化サンプリングについて説明しました。 また、この手法の利点と制限についても説明しました。 最後に、層化抽出法を使用したK分割交差検定を適用して、Python実装を使用して数字分類子を評価する方法を学びました。