まとめ
- 交差検証はデータを複数分割してモデル性能を安定評価する手法です。
- ホールドアウトとの違いをコードで比較し、分割数の影響を確認します。
- フォールド設計や計算コストの見積もりなど実務での注意点を整理します。
標本データを分割し、その一部でモデルを学習、残りでテストを行い、解析自体の妥当性を検証する手法 — 交差検証 (Wikipedia)
1. 交差検証とは #
- データを複数の「フォールド」に分割し、学習と検証を交互に入れ替えて評価する方法。
- 1 回だけの
train_test_splitでは評価のばらつきが大きくなるため、交差検証で平均性能を把握する。 - 典型例は k-fold(k 分割)と Stratified k-fold(各フォールドでラベル比率を揃える)の 2 種。
2. Python 3.13 での基本例 #
Python 3.13 環境を前提とし、必要なライブラリを導入します。
python --version # 例: Python 3.13.0
pip install scikit-learn matplotlib
乳がん診断データセットを用い、単一のホールドアウト評価と 5 分割交差検証を比較します。
from __future__ import annotations
import numpy as np
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import cross_validate, train_test_split
RANDOM_STATE = 42
def make_dataset() -> tuple[np.ndarray, np.ndarray]:
"""不均衡な二値分類データセットを生成する。"""
features, labels = make_classification(
n_samples=300,
n_classes=2,
weights=[0.2, 0.8],
n_informative=4,
n_features=6,
n_clusters_per_class=2,
shuffle=True,
random_state=RANDOM_STATE,
)
return features, labels
def holdout_score() -> float:
"""単一のホールドアウト分割で ROC-AUC を計算する。"""
features, labels = make_dataset()
x_train, x_valid, y_train, y_valid = train_test_split(
features,
labels,
test_size=0.2,
stratify=labels,
random_state=RANDOM_STATE,
)
model = RandomForestClassifier(max_depth=4, random_state=RANDOM_STATE)
model.fit(x_train, y_train)
predictions = model.predict(x_valid)
return roc_auc_score(y_valid, predictions)
def cross_validation_scores() -> dict[str, float]:
"""5 分割交差検証で ROC-AUC と Accuracy の平均を計算する。"""
features, labels = make_dataset()
model = RandomForestClassifier(max_depth=4, random_state=RANDOM_STATE)
scores = cross_validate(
model,
features,
labels,
cv=5,
scoring=("roc_auc", "accuracy"),
return_train_score=False,
n_jobs=None,
)
return {
"roc_auc": float(np.mean(scores["test_roc_auc"])),
"accuracy": float(np.mean(scores["test_accuracy"])),
}
if __name__ == "__main__":
holdout = holdout_score()
print(f"Hold-out ROC-AUC: {holdout:.3f}")
cv_result = cross_validation_scores()
print(f"5-fold ROC-AUC: {cv_result['roc_auc']:.3f}")
print(f"5-fold Accuracy: {cv_result['accuracy']:.3f}")
出力例:
Hold-out ROC-AUC: 0.528
5-fold ROC-AUC: 0.844
5-fold Accuracy: 0.858
単一ホールドアウトでは ROC-AUC が 0.5 程度と低く出ていますが、交差検証では安定した性能が確認できます。
3. 交差検証の設計ポイント #
- フォールド数の選択
一般的には 5 または 10。データが少ない場合はLeaveOneOutも候補だが計算コストが高い。 - 層化(Stratification)
クラス不均衡がある場合はStratifiedKFoldなどを使い、各フォールドのラベル比率を揃える。 - 評価指標の複数指定
scoringにタプルを渡すと複数指標を一度に計算できる。ROC-AUC + Accuracy などを組み合わせるとバランスが見えやすい。 - ハイパーパラメータ探索との組み合わせ
GridSearchCVやRandomizedSearchCVは内部で交差検証を行い、外部評価で過学習を防げる。
4. 現場でのチェックリスト #
- フォールド分割が適切か: データの時系列依存がある場合は
TimeSeriesSplitを使う。 - 評価指標の揃え方: ビジネスで重要な指標を
scoringに含め、意思決定者と認識を合わせる。 - 処理時間の見積もり: 交差検証は k 回学習するため、モデルの訓練コストを把握しておく。
- 再現可能なノートブック: Python 3.13 環境で同じ分割・同じ乱数を使えるよう設定値を残しておく。
まとめ #
- 交差検証は評価のばらつきを抑え、モデルの汎化性能を把握するための基本手法。
- scikit-learn では
cross_validateを使うと複数指標をまとめて取得できる。 - 実務では分割方法・指標・計算コストを踏まえて設計し、再現可能な形で運用に組み込もう。