交差検証とは?分割手法の選び方とデータリーク対策を実装目線で解説【2026年版】
手元のデータを8対2で分けて成績を測ったのに、分け方を変えたら精度が5ポイント下がった。交差検証は、この「分け方の運」を平均で潰し、まだ見ていないデータでどれくらい当たるかを推定する手続きです。この記事では、k分割の仕組みと成績の読み方、データの性質から決まる分割クラスの選び分け、分割数kと総実行時間の逆算、前処理をfold内に閉じてリークを断つ実装、探索と最終評価を切り離すネストした交差検証、そして交差検証を見送ってよい条件までを扱います。仕様は scikit-learn 1.9系(2026年8月時点の最新リリース)に沿って確認しました。
まとめ:交差検証を使う場面と分割設計で先に決める4つの事項
交差検証は、データを k 個に分けて順にテスト役を交代させ、k回分の成績を平均する評価手続きです。1回分割のホールドアウト法と比べて、たまたま難しいデータがテスト側に寄ったときの振れを抑えられます。数千件を下回る規模で、モデルの候補を比べたいときに効きます。
設計で先に決めるのは4点。データの性質に合う分割クラス(クラス比を保つか、グループを割らないか、時間順を守るか)、分割数k、前処理をfoldの内側に閉じる仕組み、そして探索と最終評価を分けるかどうかです。この4点を外すと、交差検証の数値は実力より必ず高く出ます。
逆に、数十万件を超える規模で1試行に数時間かかるなら、交差検証は割に合いません。単純な3分割(学習・検証・テスト)で足ります。
交差検証の仕組みと、ホールドアウト法だけでは成績が振れる理由
まず前提を揃えます。モデルの良し悪しは、学習に使っていないデータでどれだけ当たるかで測ります。この「まだ見ていないデータへの当たり具合」が汎化性能です。
ホールドアウト法の1回分割で成績が数ポイント動いてしまう仕組み
ホールドアウト法は、データを学習用8割・テスト用2割のように1回だけ分けて測る方法です。1,000件のデータなら、テスト側はわずか200件。この200件にたまたま判定の難しいサンプルが多く入れば成績は下がり、素直なサンプルが集まれば上がります。乱数種を変えて5回試すと、正解率が0.78から0.84の範囲で動くことは珍しくありません。
この振れ幅は、モデルAとモデルBの実力差より大きくなりがちです。0.81のモデルAと0.83のモデルBを1回分割で比べても、その2ポイントが実力差なのか分割の運なのか判別できません。交差検証は、テスト役を全データに一巡させることでこの区別をつけます。
k個の分割を順にテストへ回すk分割交差検証の5工程と平均の取り方
k分割交差検証の手順は次の通りです。
- データ全体をk個の塊(fold)に分ける
- 1番目のfoldをテスト、残りk-1個を学習に使ってモデルを作る
- テスト用foldで成績を測り、記録する
- テスト役を2番目、3番目と交代させ、k回繰り返す
- k個の成績の平均と標準偏差を出す
k=5なら学習は5回走り、全データがちょうど1回ずつテスト側を経験する仕組みです。scikit-learn では cross_validate にこの一連の処理がまとまっており、cv に整数を渡すと KFold が選ばれます。ただし推定器が ClassifierMixin を継承する分類器の場合は、公式ドキュメントの通り StratifiedKFold が自動で選ばれます。
平均値だけでなくfold間のばらつきまで見る成績の読み方と判断
交差検証の出力は1つの数字ではなく、k個の数字の集まりです。平均だけ見て終わらせると、交差検証を回した意味の半分を捨てることになります。
見るべきは標準偏差です。5分割で正解率が0.82±0.01なら、分割によらず安定しています。同じ平均0.82でも±0.07なら、特定のfoldで大きく崩れているということ。崩れたfoldに何が入っていたかを調べることは、少数クラスの偏りや外れ値の集中といった原因を突き止める手掛かりです。cross_validate の既定の戻り値には test_score のほか fit_time と score_time が含まれ、学習時間の偏りからもデータの偏りを推測できます。なお学習側の成績(train_score)は既定では返らず、return_train_score を True にして初めて取得できます。
データの性質から決まる分割クラスの選び分けとscikit-learnの対応
分割クラスの選定は好みではなく、データの構造で決まります。
データの性質別に見た分割クラスの対応表と、選定を外したときの症状
scikit-learn 1.9系が用意している主な分割クラスと、データの性質との対応は次の通りです。
| データの性質 | 使う分割クラス | 外したときの症状 |
|---|---|---|
| 独立同分布・回帰 | KFold | 目立った偏りは出にくい |
| クラス比が偏る分類 | StratifiedKFold | foldごとに成績が振れる |
| 同一顧客の複数行 | GroupKFold | 成績が実力より高く出る |
| クラス偏り+グループ | StratifiedGroupKFold | 少数クラスが片寄る |
| 時系列・順序あり | TimeSeriesSplit | 未来の情報で過大評価 |
| 件数が極端に少ない | LeaveOneOut | 分散が大きく判断しにくい |
実務でまず点検するのは上から3行目までです。分類タスクなら層化、同じ人や同じ機器から複数行が出ているならグループ分割。この2つを外している案件が最も多く、しかも成績が良い方向へずれるため気付きにくくなっています。
分類でクラス比を保つStratifiedKFoldが既定になる条件
不良品検知のように、陽性が全体の3%しかないデータを考えます。単純な KFold で5分割すると、あるfoldには陽性が1割、別のfoldにはほとんど入らないという偏りが生じる状態です。陽性がほぼ入らないfoldでは再現率が0になり、平均値が意味を失います。
StratifiedKFold は各foldのクラス比を元データの比率に合わせて分割します。陽性3%なら、どのfoldも陽性がおよそ3%。前述の通り、分類器を cross_validate に渡して cv に整数を指定した場合はこのクラスが自動で選ばれるため、意識せず使っていることも多いはずです。明示的に shuffle や random_state を指定したいときだけ、クラスを直接組み立てます。
顧客IDや患者ID単位の重複を断つGroupKFoldの使いどころ
1人の顧客が12か月分の行を持つ解約予測データを想像してください。行単位で無作為に分割すると、同じ顧客の1月分が学習側、2月分がテスト側に入ります。モデルは顧客の特徴を覚えるだけでテスト側を当てられてしまい、成績は実力を大きく超えます。本番では未知の顧客が来るのに、評価は既知の顧客で行っているためです。
GroupKFold は groups 引数で渡したID単位でデータをまとめ、同じIDが学習側とテスト側に分かれないよう分割します。クラス比の偏りも同時に抱えている場合の選択肢は StratifiedGroupKFold です。公式ドキュメントによれば、このクラスは各クラスの比率を保ちつつ、各グループが全foldを通じてテスト集合にちょうど1回だけ現れるよう分割を試みます。センサーの機器ID、店舗ID、被験者IDなど、行が独立していない列に心当たりがあれば、まずここを疑ってください。
時系列データで未来を学習に入れないTimeSeriesSplitの分割形
需要予測や株価のように時間順が意味を持つデータでは、無作為分割そのものが誤りになります。5月のデータで学習して4月を予測する構図が生まれ、本番では手に入らない未来の情報を使って過去を当てることになるからです。
TimeSeriesSplit は時間順を保ったまま、先頭からk個のfoldを学習、その次のfoldをテストとする形で分割します。公式ドキュメントが述べている通り、後続の学習集合は直前の学習集合を包含する形で増えていきます。1回目は1〜2月で学習して3月を予測、2回目は1〜3月で学習して4月を予測、という進み方です。学習データ量がfoldごとに変わるため、初期のfoldの成績が低く出る点は割り引いて読みます。
LeaveOneOutを避ける理由と公式が5分割か10分割を推す根拠
LeaveOneOut は1件だけをテストに残し、残り全件で学習する分割をデータ件数ぶん繰り返します。1,000件なら学習が1,000回。scikit-learn の公式ドキュメントは、計算コストが高いことに加えて「テスト誤差の推定量として分散が大きくなりやすい」と明記し、一般則として5分割か10分割を推しています。
分散が大きくなる理由は、各回の学習データがほぼ同一(1件しか違わない)のため、作られるモデルが互いにほとんど同じになるからです。独立した推定を集めているつもりが、実質1つのモデルを1件ずつで測っているだけになります。使いどころは数十件規模の実験データに限られます。
分割数kと繰り返し回数の決め方、学習コストから逆算する実行時間
kは大きいほど推定が細かくなる代わりに、学習回数がそのまま増えます。この釣り合いを件数と時間の両面から決めます。
k=5とk=10のどちらを選ぶかを決めるデータ件数と分散の目安
目安はデータ件数です。数千件以上あるならk=5で足ります。各foldのテスト側に数百件以上が確保でき、成績の標準偏差も落ち着いた範囲に収まる見込みです。数百件しかない場合はk=10にして、1回の学習に使えるデータを全体の9割まで増やします。
k=10はk=5に対して学習回数がちょうど2倍。1試行3分のモデルなら15分が30分になります。まず k=5 で回し、標準偏差が平均の1割を超えるようならkを増やす、という順序が実務では手戻りが少ない進め方です。
1試行の学習時間から交差検証の総実行時間を逆算する計算の進め方
総実行時間は「1試行の学習時間 × k × 比較したいモデル数」で求まります。学習1回が3分、k=5、候補モデルが4種類なら 3×5×4 で60分。ここまでは現実的な範囲です。
問題はハイパーパラメータ探索と組み合わせたときで、30通りの試行を交差検証で評価すると 3×5×30 で450分、7時間半かかります。さらに後述するネストした交差検証で外側5分割を加えれば、単純計算で5倍の37時間半。着手前にこの掛け算をしておかないと、翌朝まで結果が出ない事態になります。探索側の試行数を絞る判断はハイパーパラメータ探索の打ち切り設計で扱っています。
RepeatedKFoldで分割の当たり外れを均す条件と繰り返し回数
k分割は1度実行しても、分割の切り方そのものに乱数が入ります。RepeatedKFold は乱数種を変えてk分割を複数回繰り返し、得られる成績の数をk×繰り返し回数まで増やす手法です。5分割を3回繰り返せば15個の成績が集まり、平均の信頼度が上がります。
使うのは、モデル間の差が1ポイント以下で判断がつかないときに限ります。学習回数が繰り返し回数ぶん増えるため、差が明らかな段階で回しても時間の浪費です。繰り返しは3回まで。それでも差が出ないなら、モデルの違いではなく特徴量やデータ量の側に原因があります。
交差検証の成績が実力より甘くなるデータリークの発生箇所と対策
分割クラスを正しく選んでも、前処理の順序を誤ると成績は上振れします。交差検証の数値が本番と合わない案件は、ほぼここで説明がつきます。
標準化や特徴量選択を分割の前に済ませると成績が上振れする理由
データ全体で平均と標準偏差を計算して標準化してから交差検証を回す。この順序は広く見かけますが、誤りです。全体の平均にはテスト側のデータが含まれており、その情報が学習側に流れ込んでいます。
影響がとくに大きいのは特徴量選択です。全データで目的変数との相関が高い上位50列を選んでから分割すると、テスト側の答えを見て特徴量を決めたことになる設計です。scikit-learn の公式ドキュメントも「前処理は学習集合から学び、保留したデータへ適用する」と明記しています。特徴量側の工程については特徴量エンジニアリングの変換・選択の進め方で整理しています。
Pipelineで前処理をfold内に閉じ込める実装と確認の観点
対策は仕組みで担保します。前処理と推定器を1つのオブジェクトにまとめ、それを交差検証へ渡す形です。
make_pipeline(StandardScaler(), SVC(C=1)) のように組み立てたものを cross_validate へ渡すと、標準化の統計量が各foldの学習分割だけから計算され、テスト分割へ適用されます。公式ドキュメントが推奨している形もこれです。欠損補完、エンコーディング、次元削減、特徴量選択はすべてこの内側に入れます。
確認の観点は1つ。「この処理は、テスト分割のデータを1行でも見ているか」と自問することです。見ているならPipelineの内側へ移します。
重複レコードや期間の混入など、見つけにくいリークの兆候と点検
Pipelineを組んでも残るリークがあります。データそのものに埋め込まれている型です。
- 完全重複行が存在し、学習側とテスト側に同じ行が入っている
- 目的変数から作られた列(申込日と契約日の差など)が特徴量に混ざっている
- 集計特徴量を全期間で作っており、未来の集計値が過去の行に付いている
- IDや連番が特徴量に残り、収集順とラベルが相関している
兆候は成績に出ます。交差検証の正解率が0.99を超える、あるいは標準偏差が0.001未満といった不自然に整った数字が出たら、まず重複行の件数を数えてください。上から順に点検すると、多くはこの並びのどこかで見つかります。
ハイパーパラメータ探索と最終評価を切り離すネストした交差検証
ここからは競合上位の解説がほとんど触れていない領域です。探索と評価を同じ分割で行うと、交差検証の数値そのものが甘くなります。
探索に使った分割で最終成績まで報告すると数値が甘くなる仕組み
5分割交差検証で30通りのパラメータを試し、最も成績の良かった組み合わせの数値を「このモデルの精度」として報告する。よくある流れですが、この数値は過大です。
30回のうち最も高い値を選んでいる以上、選択そのものが分割の当たりを拾っています。30通り試せば、実力は同じでも分割との相性だけで1〜2ポイント高く出る組み合わせが混ざります。試行数が増えるほどこのずれは広がり、100通り試したときの最高値は、実力の推定として使えません。
外側ループと内側ループの役割分担と、学習回数が何倍に増えるか
ネストした交差検証は、この選択と評価を別の分割で行います。外側のループがデータをk分割し、そのうちの学習側だけを使って内側でもう一度分割してパラメータを探索。内側で決まった設定を、外側のテスト分割で1回だけ測ります。
外側のテスト分割は探索に一切使われていないため、得られる数値は選択の甘さを含みません。代償は計算量で、外側5分割・内側5分割・30試行なら学習回数は 5×5×30 で750回。1試行3分なら37時間を超えます。着手前に総実行時間を必ず見積もってください。
ネストを省いてよい条件と代わりに確保する評価用ホールドアウト
実務ではネストを省く場面のほうが多いのが実情です。省いてよい条件は2つあり、どちらかを満たせば足ります。1つは試行数が10通り以下で、選択による上振れが小さいと見込める場合。もう1つは、データ件数に余裕があり、最初に評価用ホールドアウトを2割切り出しておける場合です。
後者を選ぶなら、切り出したホールドアウトは探索中に一度も触らず、最終候補が決まってから1回だけ使う設計です。この1回で測った数値が報告値になります。ネストより計算量が少なく、説明も簡単で、受託開発の現場ではこちらが推奨です。逆に、データが数百件しかなく2割を切り出す余裕もないなら、ネストを組む価値があります。
受託開発で交差検証を見送る条件と、顧客へ提示する成績の書き方
交差検証は常に正解ではありません。回さない判断も含めて設計です。
交差検証より単純な分割を選んでよい判断条件とデータ件数の境目
次の条件に当てはまるなら、交差検証を回さず学習・検証・テストの3分割で進めて差し支えありません。データが10万件を超えており、テスト側に1万件以上を割いても学習量が足りる場合。1試行の学習に1時間以上かかり、k倍すると開発期間を圧迫する場合。そして本番が時系列で、最新期間での成績だけが意思決定に使われる場合です。
判断を言い切ります。数十万件のデータで深層学習モデルを1本作る案件に、5分割交差検証は過剰です。学習時間が5倍になる見返りとして得られるのは標準偏差の情報だけで、その情報で変わる判断がありません。逆に、データが5,000件を下回り、モデル候補を3つ以上比べるなら交差検証は必須。1回分割の振れ幅が候補間の差を上回るためです。
顧客へ提示する成績へ平均・ばらつき・分割条件を必ず添える書き方
報告書に「正解率0.87」とだけ書くのは避けてください。分割条件が抜けていると、後日データが増えて数値が変わったときに説明できません。
添えるのは3項目です。平均と標準偏差(0.87±0.02)、分割方法(顧客ID単位の5分割・層化あり)、評価指標の定義(陽性を不良品としたF1値)。加えて、fold間で最も低かった値も併記の対象です。0.87±0.02でも最低foldが0.81なら、条件次第でその水準まで落ちる可能性を先に共有できます。機械学習モデル開発の案件では、この提示の仕方を最初の中間報告で合意しておくと、後の精度に関する議論が数値の解釈ではなく改善策に集中します。
納品物に含める分割の再現情報と、引き渡し範囲を決めるときの線引き
半年後に同じ数値を再現できるかどうかが、納品物の質を分けます。必要なのは、分割クラスと引数(k、shuffle、random_state、groupsに使った列名)、評価指標の定義、学習データのスナップショット、ライブラリの版の4点です。この4点が揃っていれば、担当者が替わっても同じ成績を再現できます。
データ側の版をどう固定するかはデータバージョニングの仕組みで、試行ごとの条件と成績をどう残すかは実験管理の記録項目とrun設計で扱っています。引き渡し範囲を分ける基準は、評価スクリプトそのものを納品対象に含めるかどうかです。数値だけを納めると再検証の依頼が発生するため、分割条件を含む評価スクリプト一式まで含める契約にしておくほうが、双方の手戻りが減ります。
よくある質問
交差検証の設計で実際に判断が分かれる論点を5つ挙げ、実務での結論を示します。
交差検証とホールドアウト検証はどう使い分ければよいですか?
データ件数で分けます。数千件を下回り、複数のモデル候補を比べるなら交差検証。1回分割では成績の振れ幅が候補間の差を上回り、比較になりません。10万件を超えていて学習に時間がかかるなら、ホールドアウト検証で足ります。テスト側に1万件確保できれば、分割の運による振れは1ポイント未満に収まります。中間の規模では、まず5分割で回して標準偏差を見てから決めるのが確実です。
分割数kは5と10のどちらを選べばよいですか?
scikit-learn の公式ドキュメントは一般則として5分割か10分割を推しています。その範囲で選ぶなら、数千件以上はk=5、数百件規模はk=10が目安です。k=10は学習回数がk=5の2倍になるため、1試行の学習時間が長い場合は5から始めます。標準偏差が平均の1割を超えるようなら、kを増やして推定を安定させます。
交差検証の平均スコアをそのまま本番の精度として報告してよいですか?
パラメータ探索に同じ分割を使っていた場合、その数値は過大です。30通り試して最高値を選ぶ行為自体が分割との相性を拾うため、1〜2ポイント高く出ます。報告値として使うなら、探索に一度も使っていない評価用ホールドアウトで測り直すか、ネストした交差検証の外側で得た数値を使ってください。試行数が10通り以下なら、ずれは小さいため平均をそのまま使っても実害は出にくくなります。
時系列データにKFoldを使うと何が起きますか?
未来のデータで学習して過去を予測する分割が生まれ、成績が実力を大きく超えます。需要予測で正解率が異様に高く出る案件は、まずここを疑ってください。TimeSeriesSplit を使えば時間順が保たれ、後続の学習集合が直前の集合を包含する形で進みます。初期のfoldは学習データが少ないぶん成績が低く出るため、平均だけでなく後半foldの数値も併記します。
交差検証で選んだモデルは最後にどのデータで学習し直しますか?
交差検証はk個のモデルを作りますが、そのどれかを納品するわけではありません。分割条件とパラメータを決めるための手続きです。設定が決まったら、学習に使えるデータ全件で最終モデルを1本学習し直し、それを本番へ載せます。交差検証で得た平均成績は、その最終モデルの性能の推定値という位置づけになります。
関連記事
- ハイパーパラメータ探索とは?手法の選び方と打ち切り設計を実装目線で解説:交差検証を内側に組み込む探索工程の設計
- 実験管理とは?記録項目とrun設計・導入判断を実装目線で解説:分割条件と成績を再現可能な形で残す枠組み
- データバージョニングとは:分割を再現するための学習データの版管理
- モデルモニタリングとは?ドリフト検知の指標としきい値設計を実装目線で解説:本番投入後に成績の劣化を追う仕組み
- モデルデプロイとは?本番へ出す6工程と段階公開・切り戻しの判断基準を解説:評価を終えたモデルを本番へ載せる工程