Scikit-learn クロスバリデーション

scikit-learnBeginner
オンラインで実践に進む

はじめに

機械学習では、モデルの性能を評価するために、データを訓練セットとテストセットに分割することがよくあります。しかし、この評価は、どのデータポイントが訓練セットに入り、どのデータポイントがテストセットに入るかに大きく依存する可能性があります。より堅牢な方法がクロスバリデーション(CV)です。

クロスバリデーションが必要な理由

  • 過学習のリスクを低減: 複数のデータ分割でモデルをテストします。
  • 汎化性能のより良い推定: 未知のデータに対するより信頼性の高い性能。
  • データの使用を最大化: すべてのサンプルが訓練とテストの両方に使用されます。

クロスバリデーションでは、データセットを複数の「フォールド」に分割し、毎回異なるフォールドをテストに使用して、モデルを複数回訓練および評価します。これにより、未知のデータに対するモデルの性能をより信頼性の高い推定値として得ることができます。

この実験では、scikit-learn の強力で便利な関数を使用して、有名な Iris データセットを用いた分類器のクロスバリデーションを実行する方法を学びます。cross_val_score を使用して性能スコアを取得し、その平均値と標準偏差を計算することで、モデルの安定性と全体的な精度をより深く理解できるようになります。

sklearn.model_selection から cross_val_score をインポートする

このステップでは、クロスバリデーションを実行するために必要な関数をインポートすることから始めます。cross_val_score 関数は、この目的のための scikit-learn における主要なツールです。データの分割、モデルの訓練、および複数のフォールドでのスコアリングのプロセスを簡素化します。

まず、IDE の左側にあるファイルエクスプローラーを使用して、~/project ディレクトリにある main.py ファイルを開きます。

次に、cross_val_score のインポート文を main.py スクリプトに追加します。ファイルの先頭にある他のインポート文と一緒に配置してください。

from sklearn.model_selection import cross_val_score

これで、main.py ファイルは以下のようになります。

import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target

## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)

## --- Your code will go below this line ---

構文エラーがないことを確認するためにスクリプトを実行できます。IDE でターミナルを開き、次のコマンドを実行します。

python3 main.py

まだ出力コードを追加していないため、何も表示されないはずです。これは予期された動作です。

sklearn.model_selection から n_splits=5 で KFold を初期化する

cross_val_score は自動的に分割を処理できますが、その基盤となるメカニズムを理解することは良い習慣です。最も一般的なクロスバリデーション戦略は K-Fold であり、データセットは 'k' 個のフォールドに分割されます。モデルは k-1 個のフォールドで訓練され、残りのフォールドでテストされ、このプロセスを k 回繰り返します。

KFold のパラメータ:

  • n_splits=5: データを 5 つの等しい部分(フォールド)に分割します。
  • shuffle=False (デフォルト): 元のデータの順序を維持します。
  • random_state: shuffle=True の場合、ランダム化を制御します。

scikit-learn の KFold クラスは、データを分割するための訓練/テストインデックスを提供するクロスバリデーションイテレータです。次のステップではより簡単なショートカットを使用しますが、KFold を理解することは基本的です。

KFold をインポートして、どのように初期化するかを見てみましょう。以下の行を main.py ファイルに追加してください。

まず、先頭にインポート文を追加します。

from sklearn.model_selection import KFold

次に、初期化できます。ただし、この実験では、cross_val_scorecv パラメータに依存します。これはより直接的なアプローチです。このステップの目的は、KFold の概念を紹介することです。簡潔にするため、また実験の流れに沿うために、この実験では KFold の初期化コードをスクリプトに追加しません。次のステップで直接 cv=5 を使用します。これは内部的に K-Fold 戦略を使用します。これはクロスバリデーションを実行する最も一般的で簡単な方法です。

実践でこの概念を使用する次のステップに進みましょう。このステップではコードを追加しなかったため、「続行」をクリックして次に進むことができます。

cross_val_score(clf, X, y, cv=5) でクロスバリデーションを実行する

いよいよクロスバリデーションを実行します。先ほどインポートした cross_val_score 関数を使用します。この関数はいくつかの引数を取ります。

cross_val_score のパラメータ:

  • estimator: 評価するモデル(私たちの clf クラス分類器)
  • X: 特徴データ行列
  • y: ターゲットラベル配列
  • cv=5: クロスバリデーション戦略(整数 = k-fold、または CV スプリッターオブジェクト)
  • scoring: 評価メトリック(デフォルトでは推定器のスコアメソッドを使用)
  • n_jobs: 使用する CPU コア数(デフォルト=1、全コアの場合は -1)

cv=5 を設定することで、scikit-learn に 5-fold クロスバリデーションを実行するように指示します。データは自動的に 5 つのフォールドに分割され、モデルは 5 回訓練およびテストされ、各実行のスコアを含む配列が返されます。

以下のコードを main.py ファイルの末尾、コメント行の下に追加してください。

## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)

## Print the array of scores
print("Scores:", scores)

これで、main.py ファイル全体は以下のようになります。

import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target

## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)

## --- Your code will go below this line ---

## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)

## Print the array of scores
print("Scores:", scores)

次に、ターミナルからスクリプトを実行します。

python3 main.py

クロスバリデーションの各フォールドに対応する 5 つのスコアの配列を示す出力が表示されます。

Scores: [0.96666667 1.         0.96666667 0.96666667 1.        ]
Mean score: 0.9800000000000001
Standard deviation: 0.016329931618554516

スコアは、正確な分割方法によって若干異なる場合がありますが、似ているはずです。この配列は、モデルがデータの異なるサブセットでどのようにパフォーマンスを発揮したかを詳細に示しています。

scores.mean() で平均 CV スコアを計算する

スコアの配列は情報量が多いですが、モデルのパフォーマンスの簡単な概要を得るためには、通常これらのスコアの平均を計算します。この単一の値は、モデルの精度に関する一般的なアイデアを与えてくれます。

cross_val_score 関数は NumPy 配列を返します。この配列には .mean() を含む多くの便利なメソッドがあります。このメソッドを scores 変数に直接呼び出すことができます。

平均スコアを計算して表示するために、以下の行を main.py スクリプトの末尾に追加してください。

## Compute and print the mean of the scores
mean_score = scores.mean()
print("Mean score:", mean_score)

これで、main.py ファイルには以下のコードが含まれるはずです。

import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target

## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)

## --- Your code will go below this line ---

## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)

## Print the array of scores
print("Scores:", scores)

## Compute and print the mean of the scores
mean_score = scores.mean()
print("Mean score:", mean_score)

スクリプトを再度実行します。

python3 main.py

出力には、5 つのスコアの平均が含まれ、単一の代表的なパフォーマンスメトリックが得られます。

Scores: [0.96666667 1.         0.96666667 0.96666667 1.        ]
Mean score: 0.9800000000000001

scores.std() で CV スコアの標準偏差を計算する

平均スコアは平均的なパフォーマンスを示しますが、そのパフォーマンスの一貫性については教えてくれません。スコアの標準偏差は、このばらつきの尺度を与えてくれます。

標準偏差の解釈:

  • 低い標準偏差 (< 0.05): モデルはすべてのデータサブセットで一貫したパフォーマンスを発揮します。
  • 中程度の標準偏差 (0.05-0.15): 適度なばらつきがあり、ほとんどの場合で許容範囲内です。
  • 高い標準偏差 (> 0.15): パフォーマンスのばらつきが大きく、データの問題やモデルの不安定性を示唆する可能性があります。

標準偏差が低いということは、モデルのパフォーマンスがデータの異なるサブセット間で安定していることを示しますが、標準偏差が高いということは、パフォーマンスがより変動しやすいことを示唆します。

.mean() と同様に、NumPy 配列には標準偏差を計算するための .std() メソッドもあります。

最後のコード片を main.py スクリプトに追加して、標準偏差を計算し表示します。

## Compute and print the standard deviation of the scores
std_dev = scores.std()
print("Standard deviation:", std_dev)

これで、最終的な main.py スクリプトが完成し、以下のようになります。

import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target

## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)

## --- Your code will go below this line ---

## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)

## Print the array of scores
print("Scores:", scores)

## Compute and print the mean of the scores
mean_score = scores.mean()
print("Mean score:", mean_score)

## Compute and print the standard deviation of the scores
std_dev = scores.std()
print("Standard deviation:", std_dev)

スクリプトを最後に実行します。

python3 main.py

最終的な出力には、スコアの配列、その平均、および標準偏差が表示され、モデルのパフォーマンスに関する包括的な評価が得られます。

Scores: [0.96666667 1.         0.96666667 0.96666667 1.        ]
Mean score: 0.9800000000000001
Standard deviation: 0.016329931618554516

まとめ

この実験を完了された皆さん、おめでとうございます!scikit-learn を使用して k-fold クロスバリデーションを実行し、解釈する方法を習得しました。

この実験では、以下のことを行いました。

  • 堅牢なモデル評価におけるクロスバリデーションの重要性を理解しました。
  • cross_val_score 関数を使用して、サポートベクター分類器で 5-fold クロスバリデーションを簡単に実行しました。
  • クロスバリデーションスコアの平均と標準偏差を計算して表示することで、結果を分析しました。

クロスバリデーションの実践的なヒント:

  • ほとんどのシナリオでは 5-fold または 10-fold CV を使用します。
  • 不均衡なデータセットの場合は、層化クロスバリデーション (stratified CV) を検討します。
  • 複数のメトリックを使用する場合は、cross_val_score の代わりに cross_validate を使用します。
  • 再現性のある結果を得るために、常に random_state を設定します。

このテクニックは、機械学習ワークフローの基本的な部分であり、モデルのパフォーマンスが、単に幸運な訓練 - テスト分割の結果ではなく、信頼できるものであることを保証します。この知識を応用して、自身の機械学習モデルをより自信を持って評価できるようになりました。