MACHINE LEARNING / CROSS VALIDATION
交差検証(クロスバリデーション)とは? K-foldと汎化性能を図解で理解する
公開日:2026-10-13
教師あり学習でモデルの性能を評価するとき、1回の分割だけで判断してよいのでしょうか。交差検証の仕組みを、学習・検証データの分け方から順を追って解説します。
教師あり学習 → 汎化性能 → K-fold → 数値例 → 分割法の選択 → データリーク対策 → 実装例 → 操作ラボ
01|交差検証とは何か
機械学習は、過去の正解付きデータから規則性を学び、まだ見たことのないデータを予測します。学習に使ったデータだけで成績を測ると、暗記したモデルが高得点を取ることがあります。ここで重要なのが汎化性能、すなわち未知データでの性能です。
交差検証(Cross-validation)は、用意したデータのうち学習に使う部分と検証に使う部分を何度か入れ替え、各回の評価結果を集める方法です。1回の偶然の分割に依存しにくい見積もりを得られます。ただし交差検証を行うだけで過学習が自動的に消えるわけではありません。
02|教師あり学習と3種類のデータ
訓練データ
モデルの重みやパラメータを学習する
検証データ
モデル・ハイパーパラメータを比較する
テストデータ
最終的な汎化性能を独立に評価する
最終評価用のテストセットを最初に分けておき、残りのデータで交差検証を使ってモデル選択を行う構成が典型的です。交差検証の各回で検証用になったデータを使い、繰り返しモデルを選び続けると評価に選択バイアスが生じ得ます。最後のテストデータは開発途中の意思決定に使いません。
03|K-fold交差検証の流れ
K-foldはデータをK個の区画(fold)へ分け、1つを検証用、残るK−1個を学習用としてK回の評価を行います。各回で新たにモデルを学習し直します。図ではK=5、各回の検証データは異なります。
概念図:5回の学習では、それぞれ別のモデルを訓練します。元データの各区画は通常1回ずつ検証に使われます。
- データを5つのfoldへ分けます。
- 1つのfoldを検証用として、残る4つで学習します。
- 検証用foldで精度などを計測します。
- 検証用foldを変え、5回繰り返します。
- 5回のスコアの平均やばらつきを確認します。
例えば各回の正解率が80%、85%、75%、90%、70%なら単純平均は80%です。ただしfoldサイズが異なる場合や評価指標によっては集計方法を検討する必要があります。
04|「K」を大きくするとどうなる?
Kが大きいほど1回あたりの学習データは増え、検証データは小さくなります。一方、学習をやり直す回数が増えて計算負荷も上がります。K=5や10は実務でよく使われる出発点ですが、最適な値はサンプル数、クラス比率、計算予算など次第です。
| 方式 | 学習データ比率(均等分割) | 特徴 |
|---|---|---|
| 2-fold | 50% | 計算負荷は比較的小さい |
| 5-fold | 80% | バランスを取りやすい |
| 10-fold | 90% | 学習割合が大きいが再学習が増える |
| LOOCV | (N−1)/N | N回学習し、計算負荷が重くなりやすい |
05|データに応じて分割方法を選ぶ
通常のK-foldは、データが独立に同じ分布から得られたとみなせる場合の基本形です。しかし、実データには偏りや依存関係があります。
StratifiedKFold(層化)
不正取引が1%など少数クラスのある分類では、各foldのクラス比率を近づけます。
GroupKFold
同一患者・利用者・端末の観測データが学習側と検証側に混ざらないようグループ単位で分割します。
TimeSeriesSplit
未来予測では時間の順序を守り、過去で学習し未来側の期間で検証します。
RepeatedKFold
分割の乱数を変えて複数回繰り返し、分割に由来する変動を観察します。
06|混同しやすい4つの学習手法
| 手法 | 何をするか | 主な目的 |
|---|---|---|
| 交差検証 | 分割を入れ替え複数回学習・評価 | 未知データへの性能推定・モデル選択 |
| 正則化(L1/L2) | 損失に複雑さのペナルティを加える | 過学習を抑える |
| アンサンブル学習 | 複数モデルの予測を結合 | 予測性能・頑健性の向上 |
| マルチタスク学習 | 関連する複数課題を共同学習 | 共有表現の獲得 |
| ホールドアウト | 一度だけ学習・評価へ分割 | 手軽な性能確認 |
正則化はモデルの複雑さを制御し、交差検証はそのモデルが未知データでどの程度働くかを推定します。両者は競合するのではなく、例えば「L2正則化の強さ」を交差検証で選ぶように組み合わせて使えます。アンサンブル学習では複数モデルを組み合わせ、マルチタスク学習では関連タスクを同時に学びます。
07|数字で追うモデル選択
2つの候補モデルAとBを5分割で比較する例です。Aの正解率が81%、84%、80%、83%、82%なら平均82%です。Bが84%、88%、74%、91%、73%なら平均82%です。平均値が同じでも、Bは分割により大きく変動しています。平均だけで判断せず、誤差のばらつきや少数クラスへの性能も確認します。
分類ではAccuracyだけでなくPrecision・Recall・F1・PR-AUCなど目的に適した評価指標を選択し、回帰ではMAEやRMSEなどを使います。とくに不正検知のように正常データが圧倒的に多い場合、正解率だけでは見落としを隠してしまうことがあります。
08|データリークに注意
最も典型的な失敗は、分割前の全データに対して標準化・欠損値補完・特徴量選択を学習(fit)してしまうことです。検証用データの統計が学習プロセスに入り、性能が過大評価されます。各foldでは学習用データで前処理をfitし、検証用データにはその結果をtransformします。scikit-learnのPipelineは、この手順を一貫して適用しやすくします。
# よくない例:分割前の全データにfit
X_scaled = scaler.fit_transform(X)
scores = cross_val_score(model, X_scaled, y, cv=5)
# 推奨:前処理もfold内でfit
pipeline = make_pipeline(StandardScaler(), LogisticRegression())
scores = cross_val_score(pipeline, X, y, cv=5)もう一つは時間リークです。未来にしか確定しない情報を特徴量に含めると、いくらK-foldの評価が高くても実運用では使えません。前処理だけでなく特徴量作成、ラベル付け、分割順序まで点検しましょう。
09|Pythonで実装する
from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
X, y = load_iris(return_X_y=True)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
model = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
scores = cross_val_score(model, X, y, scoring="accuracy", cv=cv)
print(scores)
print("平均:", scores.mean(), "標準偏差:", scores.std())このコードでは前処理と分類器が1つのパイプラインになり、各分割の学習データだけで標準化が学習されます。乱数シードを指定するのは同じ分割を再現するためで、分割方法の妥当性そのものを保証するわけではありません。
10|ハイパーパラメータ調整と入れ子の交差検証
正則化の強さや木の深さなどを多数試し、最もスコアの高いモデルを選ぶと、その検証スコアには選択による楽観バイアスが入り得ます。厳密にモデル選択手順全体を評価したい場合は、外側で性能評価、内側でハイパーパラメータ選択を行うNested CVを使います。
外側の分割:性能評価用(outer CV)
内側の分割:モデル選択用(inner CV)
内側で最良のハイパーパラメータを選択 → 外側の未使用データで評価
11|操作ラボ:foldを入れ替える
分割方法、Kの値、検証回を操作して、どのデータが学習と検証に回るか確かめましょう。時系列はK-foldと異なり、後のデータを未来として残す設計です。ラボのスコアは例示値であり、実際のAIモデルの予測ではありません。
INTERACTIVE LAB
交差検証の分割を操作する
24件の教材用データを色分けします。これは分割の可視化であり、モデルの実学習は行いません。スコアも編集可能な例示値です。
各データを一度ずつ検証側へ。通常のK-foldはクラス比率や時間順序を自動で守るわけではありません。
検証スコアの平均を計算
手動の例示スコアです。データ分割を変えてもモデルを再学習していないため、値は自動更新しません。
平均スコア:81.8%
12|実務チェックリストとまとめ
- 検証したい将来の利用条件に合う分割を選びましたか。
- 評価指標は業務上の失敗コストを反映していますか。
- 同一ユーザーや類似サンプルが学習・検証で漏れ込んでいませんか。
- 欠損値補完・標準化・特徴量選択のfitは学習側だけで実施しましたか。
- 最終テストセットをモデル選択から切り離していますか。
- 平均スコアと分割間の変動、再現条件を記録しましたか。
参考資料
- Cross-validation: evaluating estimator performance — scikit-learn developers
- Common pitfalls and recommended practices — scikit-learn developers
- Nested versus non-nested cross-validation — scikit-learn developers