医療AI研究では、アウトカム定義・組入れ基準・特徴量・前処理・モデル種類・ハイパーパラメータ・閾値といった選択肢を、いくらでも組み替えて試すことができます。最終的に最も成績の良かった組み合わせだけを「本研究のモデル」として報告すると、偶然高く出た性能が、あたかも代表値のように読者に伝わってしまいます。
この問題は、伝統的な仮説検定の p 値だけでなく、機械学習の AUC・F1・R² にも同じ構造で現れます。むしろ機械学習では、ハイパーパラメータ探索や AutoML によって 「何回試したか」自体が見えにくくなる ため、検定の多重比較よりも厄介な側面があります。
本稿は、第9部「医療AI研究の落とし穴と対策」の第5記事です。09·01 過学習 が訓練データへの過剰適合、09·02 データリーケージ が情報の漏れ、09·03 小規模データ問題 がイベント数の不足、09·04 不均衡データ がクラス比の歪みを扱ったのに対し、本稿では 「たくさん試したことで得られた最良値」 という、データ自体ではなく 解析プロセス の落とし穴を扱います。評価設計の前段は 14·02 交差検証デモ、リーケージとの関係は 14·03 リーケージデモ も併せて読むと立体的に理解できます。
// 01 · LEARN OUTCOMESこの記事で学ぶこと
- Garden of forking paths(分岐する小道)を、医療AIのモデル探索プロセスに対応づけて説明できる。
- p-hacking と、機械学習における選択バイアス(最良モデルだけを報告することの楽観バイアス)の関係を整理できる。
- FWER(family-wise error rate)と FDR(false discovery rate)の違い、および Bonferroni・Holm・Benjamini-Hochberg の使い分けを理解する。
- nested CV・hold-out test・事前登録の役割と限界を区別できる。
- CV で複数モデルを比較するときの分散の取り扱い(Nadeau-Bengio 補正、Bootstrap CI、DeLong 検定)を選べる。
- Methods と Supplementary に探索範囲を書く意義と書き方を整理できる。
// 02 · CONCLUSIONまず結論
// 03 · FIGURE多重比較とモデル探索を図で理解する
この落とし穴は、数式よりも「どこで性能が歪むか」を図で見たほうが直観的に理解できます。まず全体像として、解析の各段階で選択肢が分岐していく構造を確認します。
次に、探索と評価をどう分離すれば楽観バイアスを抑えられるか、nested CV の構造で確認します。鍵は、ハイパーパラメータ・モデル選択を行う fold と、最終性能を測る fold を分ける ことです。
最後に、研究全体の設計レベルで「何を事前に固定し、何を探索的とするか」を分ける枠組みを示します。hold-out test を一発封筒のように扱う ことが、外部検証に近い独立評価を内部データで実現するための鍵です。
// 04 · CLINICALリハ・神経・整形領域での使いどころ
FIM 総点・運動項目・認知項目・利得・効率といった複数のアウトカムを並行に解析し、最も AUC が高かったものだけを主結果として報告する例です。実質的に多重比較を行っているのに、補正も開示もないと「ある特定の FIM アウトカム予測が良かった」のではなく「6 つ試して最良の 1 つを示した」結果になります。主要アウトカムを事前に 1 つ決め、残りは副次・探索的と明記します。
LogReg・SVM・RF・XGBoost・LightGBM・CatBoost・MLP・TabNet・Transformer・スタッキングを比較し、最高 AUC を採用する研究設計です。モデル選択そのものの楽観バイアスが残るため、最終評価は別の hold-out test か nested CV の外側 fold で測ります。さらに、モデル間 AUC 差の有意性は Nadeau-Bengio 補正分散や DeLong 検定・bootstrap CI を併用すると、誤差バーが意味のある幅で見えるようになります。
訓練データで Youden index 最大の閾値・感度 90% 維持の閾値・PPV 重視の閾値を一通り検討し、最も都合のよい指標が出る閾値を「採用閾値」と書く例です。臨床応用では、閾値の選び方で介入対象が大きく変わるため、選択ルールそのもの を事前に決めることが結論の頑健性を支えます。後から選んだ場合は、感度分析として複数閾値の結果を併記します。
AutoML フレームワーク(auto-sklearn、AutoGluon、H2O AutoML 等)で多数のモデル・前処理・スタッキングを自動探索し、最終 AUC だけを報告する例です。AutoML は便利な反面、探索範囲がブラックボックス化しがちです。Methods には、AutoML が探索したモデル空間・特徴量変換・チューニング戦略・CV 設計を明示し、最終評価は AutoML パイプラインに渡していない hold-out test で行います。TRIPOD+AI[3] と PROBAST+AI[4] の該当項目を満たすよう書きます。
// 05 · THEORY多重比較とモデル選択の理論
Garden of forking paths
Gelman & Loken[1] は、研究者が 事前に決めた一意の解析 ではなく、データを見ながら解析経路を選択する ことそのものが、p 値の解釈を歪めると指摘しました。たとえ研究者が「自分は 1 回しか検定をしていない」と感じていても、「もし違うデータが来たら違う解析をしていただろう」という潜在的な分岐があれば、報告された p 値は理論的な意味を失います。機械学習でも、データを見て前処理や閾値を決め直す行為は、同じ意味で潜在的な分岐を生みます。
FWER と FDR
多重比較の補正は、何を制御したいかで二系統あります。
FWER (Family-Wise Error Rate)
= P(少なくとも 1 つの偽陽性 | すべて帰無)
→ Bonferroni, Holm, Šidák で制御
→ 1 つの偽陽性も許したくない厳格な場面
FDR (False Discovery Rate)
= E[ 偽陽性 / 棄却された仮説 ]
→ Benjamini-Hochberg (BH) で制御
→ 多数の仮説から探索的に拾うバイオインフォ等
例: m = 10 検定 / α = 0.05
Bonferroni 補正: α/m = 0.005 を各検定に適用
Holm : ソートして段階的に 0.005, 0.0056, ...
BH (FDR=0.05): k 番目を α·k/m と比較
機械学習のモデル選択は、形式上は仮説検定ではないものの、本質的には「多数の候補から最良値を選ぶ」点で多重比較と同じ問題を抱えます。AUC の最良値は、試行回数が増えるほど真の汎化性能から正の方向に偏ります。
モデル比較の分散補正
k-fold CV で得られた 2 モデルの平均 AUC を直接比較すると、fold 間が独立でないために検定の分散が過小評価されます。Nadeau & Bengio[5] は、CV のスコア分散に、訓練・検証データの重複に応じた補正項を加える方法を示しました。AUC 同士の比較では DeLong 検定[6] が用いられます。実務では、bootstrap CI(モデル別の AUC 信頼区間)や、ペア bootstrap(同一 fold 内での AUC 差の分布)を併用すると、誤差が見える形になります。
楽観バイアスの目安
n 個の独立モデルから最良 AUC を選ぶと、その期待値は真の AUC からおよそ σ√(2·ln n) 程度上に偏ります(極値統計)。n=10, σ=0.03 でおよそ +0.06 のずれです。実際にはモデル間で相関があるためこの値は上限に近いですが、「数十個試した中の最良値は単独で意味を持ちにくい」感覚を持つには十分です。09·03 EPV・サンプルサイズ で扱った optimism と同じ理屈です。
// 06 · IMPLEMENTATION実装:nested CV とモデル比較の信頼区間
実装では、解析の便利さよりも 評価データを守ること を優先します。前処理・補完・特徴量選択・リサンプリング・ハイパーパラメータ探索は、すべて検証設計の 中 に入れて考えます。
# ============================================================
# Nested CV for model selection — scikit-learn skeleton
# ハイパラ探索を inner CV、最終性能を outer CV で評価する
# ============================================================
import numpy as np
from sklearn.model_selection import (
GridSearchCV, cross_val_score, StratifiedKFold, RepeatedStratifiedKFold,
)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
# 1) Pipeline は前処理を含めて 1 つの "model" にする
# (前処理を CV の外でやると leakage の温床になる)
pipe_lr = Pipeline([
("scaler", StandardScaler()),
("clf", LogisticRegression(max_iter=2000, class_weight="balanced")),
])
pipe_svm = Pipeline([
("scaler", StandardScaler()),
("clf", SVC(probability=True, class_weight="balanced")),
])
grid_lr = {"clf__C": [0.01, 0.1, 1, 10]}
grid_svm = {"clf__C": [0.1, 1, 10], "clf__gamma": ["scale", 0.01, 0.001]}
# 2) Inner CV: ハイパラ選択
inner = StratifiedKFold(n_splits=5, shuffle=True, random_state=1)
search_lr = GridSearchCV(pipe_lr, grid_lr, scoring="roc_auc",
cv=inner, n_jobs=-1, refit=True)
search_svm = GridSearchCV(pipe_svm, grid_svm, scoring="roc_auc",
cv=inner, n_jobs=-1, refit=True)
# 3) Outer CV: 最終性能の評価(モデル選択に使わない)
outer = RepeatedStratifiedKFold(n_splits=5, n_repeats=5, random_state=2)
auc_lr = cross_val_score(search_lr, X, y, scoring="roc_auc", cv=outer, n_jobs=-1)
auc_svm = cross_val_score(search_svm, X, y, scoring="roc_auc", cv=outer, n_jobs=-1)
print(f"LR AUC: {auc_lr.mean():.3f} ± {auc_lr.std():.3f}")
print(f"SVM AUC: {auc_svm.mean():.3f} ± {auc_svm.std():.3f}")
# ============================================================
# Paired bootstrap CI for AUC difference
# 同一サンプルに対するモデル間 AUC 差を bootstrap で評価する
# ============================================================
from sklearn.metrics import roc_auc_score
from sklearn.utils import resample
def paired_bootstrap_auc_diff(y_true, p_a, p_b, n_boot=2000, seed=0):
rng = np.random.default_rng(seed)
diffs = []
for _ in range(n_boot):
idx = rng.integers(0, len(y_true), len(y_true))
if len(np.unique(y_true[idx])) < 2:
continue # 単一クラスは AUC が定義不能なのでスキップ
auc_a = roc_auc_score(y_true[idx], p_a[idx])
auc_b = roc_auc_score(y_true[idx], p_b[idx])
diffs.append(auc_a - auc_b)
diffs = np.array(diffs)
ci = np.percentile(diffs, [2.5, 97.5])
return diffs.mean(), ci
mean_diff, ci = paired_bootstrap_auc_diff(y_test, p_lr, p_svm)
print(f"ΔAUC(LR - SVM) = {mean_diff:.3f} 95% CI [{ci[0]:.3f}, {ci[1]:.3f}]")
# CI が 0 をまたぐかどうかが「優劣を主張できるか」の目安
GridSearchCV の best_score_ をそのまま「最終性能」と書くのは、内側 CV の最良値を最終結果に流用することと同じで、楽観バイアスが残ります。必ず外側 fold か hold-out test で測り直す こと。Pipeline に前処理・SMOTE 等を含めるのも、リーケージ防止のための同じ規律です。
// 07 · MYTHS誤解と訂正
「モデルをたくさん比較するほど良い研究になる」
比較自体は悪くありませんが、最良値だけを最終性能として書くと、選択バイアスが入った数字を「実力」と称することになります。比較した事実と探索範囲を開示したうえで、最終評価を外側 fold か hold-out test で測り直す枠組みが必要です。
「nested CV を回しさえすれば多重比較問題は消える」
nested CV はモデル選択の楽観を抑えますが、コホート定義の選び直し・アウトカム差し替え・特徴量セット入れ替えといった「外側 CV の外」での分岐には効きません。コホート選択や主要アウトカムは事前に固定するか、感度分析として明示します。
「AutoML は人手の探索より客観的だから多重比較に強い」
AutoML は再現性が高いものの、探索した候補数は通常人手よりはるかに多くなります。最良値の選択バイアスはむしろ大きくなる可能性があります。AutoML の探索空間・評価方式・最終評価用データの分離を Methods に明記することで初めて、客観性が機能します。
「p < 0.05 を Bonferroni で割れば多重比較は片付く」
Bonferroni は FWER の保守的な制御方法で、探索的研究では検出力を大きく落とします。仮説の数や独立性、目的に応じて Holm・Šidák・Benjamini-Hochberg を選び分けます。さらに、機械学習のモデル選択は p 値補正の枠組みでは捕捉しきれないため、nested CV や hold-out で別に対処します。
// 08 · WRITING医療AI・リハビリ研究論文での書き方
Methods と Discussion では、読者が「どこで性能が歪む可能性があるか」を追跡できるようにします。次の要素を明記すると、査読で同じ指摘を繰り返し受けにくくなります。
- 主要 vs 副次: 主要アウトカム・主要評価指標・主要モデルを明示し、その他を探索的と書く。
- 試した範囲: 試したモデル数・前処理・特徴量セット・ハイパーパラメータ範囲を Methods か Supplementary に列挙する。
- 評価分離: ハイパーパラメータ探索が inner CV、最終評価が outer CV または hold-out test であることを構造図か文章で示す。
- 多重比較の補正: 検定を多数行った場合は補正方法(Bonferroni/Holm/BH 等)と補正後の閾値を書く。
- 事前登録: 事前登録の有無、登録先(OSF/AsPredicted/ClinicalTrials.gov)、登録 ID を記載する。事前登録から逸脱した解析は逸脱として明記する。
- モデル比較の不確実性: AUC 差の bootstrap CI または DeLong 検定の結果を併記する。
- Limitations: 探索的解析の影響、外部検証の不在、選択バイアスの可能性を率直に述べる。
// 09 · CHECKLIST投稿前チェックリスト
解析開始時・投稿前の双方で確認したい項目です。
- 01主要アウトカムと副次アウトカムを事前に区別した
- 02試したモデル・前処理・特徴量セットを Methods/Supplementary に記録した
- 03ハイパーパラメータ探索を inner CV の内側で行った
- 04最終 test データをモデル選択・ハイパラ選択に使っていない
- 05探索的解析と検証的解析を本文・図表で明示的に分けた
- 06複数検定を行った場合は補正方法(FWER/FDR)と補正後閾値を記載した
- 07モデル間 AUC 差の信頼区間(bootstrap/DeLong)を併記した
- 08閾値選択ルールを事前に決め、後付けで変えた場合は逸脱として明記した
- 09AutoML を使った場合、探索空間と評価分離を Methods に書いた
- 10事前登録の有無・登録 ID・逸脱の有無を記載した
- 11Supplementary にすべての候補モデルの結果を示した
- 12Limitations に探索的解析の影響と外部検証の必要性を記載した
// 10 · QUIZミニクイズ
-
Q110 種類のモデルを試して最高 AUC だけを報告するときに最も問題となるのは?
- 性能が過小評価になりやすい
- モデル選択による楽観的バイアスが入る
- 欠測バイアスだけが問題
- Calibration が必ず良くなる
SHOW ANSWER
B. 多数の候補から最高値を選ぶと、偶然高く出た結果が選ばれやすくなります。極値統計の理屈から、試行数 n の最良値の期待値は σ√(2 ln n) 程度上に偏ります。 -
Q2ハイパーパラメータ探索後のモデル性能を報告するのに最も適した方法は?
- 探索に使った validation スコアをそのまま報告
- nested CV の外側 fold または独立 hold-out test
- 訓練 AUC だけを報告
- 最良 fold の値だけ報告
SHOW ANSWER
B. 探索と評価を分離することで、性能の過大評価を抑えられます。探索に使った validation スコアを最終性能として書くと、内側選択の楽観が残ります。 -
Q3FWER と FDR の使い分けで最も適切な記述は?
- どちらも常に Bonferroni で十分
- FWER は厳格な「1 件の偽陽性も避けたい」場面、FDR は「探索的に多数から拾う」場面
- FDR は p 値を 0.05 未満にする補正
- FWER は機械学習にしか使えない
SHOW ANSWER
B. FWER は少なくとも 1 つの偽陽性が出る確率、FDR は棄却された仮説の中に占める偽陽性の期待割合を制御します。確証的検定では FWER、探索的なスクリーニングでは FDR が選ばれることが多いです。 -
Q42 モデルの AUC 差を CV で評価するときの注意点として正しいものは?
- fold 間が独立でないため、単純な t 検定では分散が過小評価される
- fold は完全に独立なので普通の t 検定で十分
- AUC 差の検定は閉じた解がないので諦める
- 差の符号さえ正なら有意
SHOW ANSWER
A. CV では訓練データが fold 間で重複するため、スコア差の分散が過小評価されます。Nadeau-Bengio 補正分散・DeLong 検定・bootstrap CI などを使います。
// 11 · FAQよくある質問
- モデルを複数試してはいけないのですか?
- 試すこと自体は問題ありません。問題は、試した事実を隠して、最も良かった結果だけを最終モデルの実力として報告することです。試したモデル・前処理・特徴量セット・ハイパーパラメータ範囲を Methods か Supplementary に明記し、最終性能は探索に使わなかったデータ(nested CV の外側 fold か独立 hold-out test)で評価します。
- AutoML は使ってよいですか?
- 使って構いませんが、探索範囲がブラックボックス化しやすい点に注意します。AutoML が探索したモデル空間・前処理・特徴量変換・ハイパーパラメータの全候補と、その評価で使った CV 設計を Methods と Supplementary に開示します。最終性能は AutoML に渡していない hold-out test で報告し、TRIPOD+AI と PROBAST+AI の項目に沿って書きます。
- 統計検定の多重比較と機械学習の多重比較は同じ問題ですか?
- 原理は同じで、たくさんの比較から良いものを選ぶと選択バイアスが入ります。違いは現れ方で、統計検定では p 値の偽陽性として、機械学習では AUC や F1 の楽観バイアスとして表れます。検定では Bonferroni・Holm・Benjamini-Hochberg などで補正し、機械学習では nested CV・hold-out test・事前登録・探索範囲の開示で対応します。
- 事前登録は機械学習の論文でも必要ですか?
- 義務ではありませんが、推奨です。少なくとも主要アウトカム・主要モデル・主要評価指標・閾値ルールを解析開始前に文書化しておくと、Reviewer から「都合のよい結果だけ選んだのでは」と疑われたときに反証材料になります。OSF や AsPredicted は無料で利用でき、社内の Git リポジトリでハッシュ付きで残すだけでも十分機能します。
// REF参考文献
- Gelman A, Loken E. The garden of forking paths: why multiple comparisons can be a problem, even when there is no "fishing expedition" or "p-hacking" and the research hypothesis was posited ahead of time. Department of Statistics, Columbia University. 2013. — PDF
- Simmons JP, Nelson LD, Simonsohn U. False-Positive Psychology: Undisclosed Flexibility in Data Collection and Analysis Allows Presenting Anything as Significant. Psychological Science 2011;22(11):1359-1366.
- Collins GS, Moons KGM, Dhiman P, Riley RD, Beam AL, Van Calster B, et al. TRIPOD+AI statement: updated guidance for reporting clinical prediction models that use regression or machine learning methods. BMJ 2024;385:e078378. — doi
- Moons KGM, Wolff RF, Riley RD, et al. PROBAST+AI: an updated quality, risk of bias, and applicability assessment tool for prediction models using regression or artificial intelligence methods. BMJ 2025;388:e082505. — doi
- Nadeau C, Bengio Y. Inference for the Generalization Error. Machine Learning 2003;52(3):239-281.
- DeLong ER, DeLong DM, Clarke-Pearson DL. Comparing the areas under two or more correlated receiver operating characteristic curves: a nonparametric approach. Biometrics 1988;44(3):837-845.
- Cawley GC, Talbot NLC. On Over-fitting in Model Selection and Subsequent Selection Bias in Performance Evaluation. Journal of Machine Learning Research 2010;11:2079-2107. — link
- Benjamini Y, Hochberg Y. Controlling the false discovery rate: a practical and powerful approach to multiple testing. JRSS-B 1995;57(1):289-300.