データリーケージは、医療AI研究の性能を静かに押し上げます。一見よく当たるモデルでも、実際の予測時には使えない情報を見ていることがあります。本稿では、リハビリテーション研究で起きやすいリーケージを類型化し、分割と Pipeline で防ぐ考え方を整理します[1]。
本稿は、第9部「医療AI研究の落とし穴と対策」の第2記事です。リーケージとは、予測時には得られない情報が、訓練時に紛れ込む現象です。過学習より見つけにくいことがあります。交差検証の成績が高くても、設計が漏れていると安全ではありません。前記事「過学習と正則化」と合わせて読むことで、予測モデルが過大評価される代表的な原因を整理できます。
// 01 · LEARN OUTCOMESこの記事でわかること
読了後、次の4つを説明できるようになります。
- データリーケージを、予測時点の情報可用性として説明できる
- 医療データで起きる 10 種類のリーケージを区別できる
- Pipeline、GroupKFold、時間順分割の役割を理解できる
- 論文 Methods に、リーケージ対策を書く観点を整理できる
// 02 · CONCLUSIONまず結論
本稿では、両者を次のように区別します。
- validation データ(検証データ):交差検証の各 fold 内で、ハイパーパラメータや特徴量を選ぶために使う。開発中に何度も触る。
- test データ:開発が終わった後、未知データでの性能を見るために最後に 1 回だけ触る。開発中は触らない。
リーケージには、この 2 つに対応する別系統があります。validation leakage は、前処理や統計量計算が分割前に行われ、検証データの情報が訓練側に流れ込む型です。test leakage は、test データの成績を見ながらモデルや特徴量を選び直し、その同じ test データで最終性能を報告する型です。
// 03 · FIGUREリーケージが起きる位置を地図にする
まず、リーケージがどこで起きるかを全体像で見ます。重要なのは、漏れはモデル学習の場面だけでなく、その手前でも起きることです。特に、分割前の前処理、目的変数に近い特徴量、評価データを見た調整は頻出です。
次に、同一患者の複数評価をどう分けるかを見ます。リハビリテーション研究では、入院時、1 か月後、退院時のように、同じ患者の評価が複数あることが珍しくありません。このとき通常の分割を使うと、患者固有の情報が train と validation にまたがります。
「この情報は、予測したい時点で本当に取れるか」。この問いを、すべての特徴量に当てます。さらに、前処理にも同じ問いを当てます。全データの平均値で標準化していれば、検証データの情報を見ています。
図にすると、リーケージはモデルの中だけではないと分かります。むしろ、モデルに入る前に起きることが多いです。特に pandas で全データをまとめて加工すると、気づかないうちに漏れます。その後に交差検証をしても、漏れた特徴量は残ったままです。
Kaufman らは、リーケージをデータマイニングにおける重要な失敗として定式化しました[1]。そこでは、学習時にだけ使える情報と、予測時にも正当に使える情報を分ける発想が重要です。医療AIでも、この分離が研究の信頼性を左右します。
// 04 · CLINICALリハビリ研究で起きるリーケージ
入院時情報から退院時 FIM を予測したい場面を考えます。ここに在院日数を入れると、未来の情報が入ります。在院日数は、退院後に確定する変数です。予測時点ではまだ分かりません。これはターゲットリーケージの典型例です。
同一の脳卒中患者で、入院時、1 か月後、退院時の FIM を記録したとします。これらを別症例として扱うと、同じ患者が train と validation に分かれます。患者固有の重症度や社会背景が漏れます。患者 ID を group として分割する設計が必要です。
SIAS や握力に欠測があるため、多重代入を行う場面があります。全データで補完モデルを作ってから分割すると、検証データの分布を見ています。目的変数も補完に含める設定では、漏れがさらに強くなります。補完は fold の訓練側だけで学習します。
CT 画像で歩行自立を予測する研究を考えます。撮影日時や撮影機種がメタデータに残っていると、病院や時期を当てる手がかりになります。2018 年以降の画像が新しい CT 機種に偏ると、病変ではなく施設差を覚えることがあります。画像の内容とメタデータを分けて点検します。
これらの例は、どれも「当たりすぎる」方向に働きます。そのため、研究者にとっては一見うれしい結果に見えます。訓練 AUC も CV AUC も高いかもしれません。しかし、実際の予測場面では同じ情報が使えません。
リハビリ領域では、アウトカムが時間の後半で決まります。退院先、退院時 FIM、歩行自立、在院日数は、互いに強く関係します。その分、目的変数に近すぎる説明変数が紛れ込みやすいです。02·01 説明変数と目的変数の段階で、時点をそろえる視点が重要になります。
また、同一患者の繰り返し測定も多くあります。歩行速度の複数試行、上肢機能評価の左右データ、入退院時評価などです。これらは独立したサンプルではありません。group を持つデータとして扱う発想が必要です。
// 05 · THEORY10 種類のリーケージを整理する
リーケージは、1 つの名前で語られます。しかし実際には、いくつかの型があります。ここでは、リハビリ研究で見落としやすい 10 種類に分けます。型で覚えると、研究計画の時点で点検しやすくなります。
全データで StandardScaler.fit() してから分割する例です。検証データの平均と分散が、訓練側の変換に使われます。対策:Pipeline の中に scaler を入れると、fold ごとに fit されます。
目的変数を導く特徴量が入る型です。自宅退院予測に退院前カンファレンス内容を入れる場合などです。退院日、在院日数、退院時 FIM も注意します。予測時点で未確定なら除外します。
未来のデータで過去を予測する型です。2025 年の診療体制で集めたデータを、2020 年の予測に混ぜると起こります。急性期から回復期への流れでも注意が必要です。時間順分割で確認します。
同一患者、同一施設、同一療法士が train と validation に分かれる型です。患者固有の情報や施設運用が漏れます。患者 ID、施設 ID、評価者 ID を group として扱います。GroupKFold や外部施設検証が候補になります。
同じ「評価データを見て調整する」でも、漏れる対象が validation データか test データかで意味合いが変わります。両者は別系統です。
validation leakage:交差検証の各 fold で、検証 fold の成績を見ながら特徴量やハイパラを調整する場合は問題ありません。ただし、前処理や統計量計算が分割前に行われ、検証 fold の情報が訓練側に流れ込むと、validation の成績そのものが過大評価されます(1・2・3・4・7・10 と重なります)。
test leakage:test データの成績を見ながら、特徴量やハイパラを選び直す型です。その同じ test データで最終性能を報告すると、「最終評価」が実際にはチューニング後の性能になり、未知患者での性能を過大評価します。test データは、開発が終わった後に 1 回だけ触るようにします。
研究では、validation データと test データを分け、調整に使ったデータと最終評価に使ったデータを Methods に明記します。
後ろ向き研究でよく起きます。カルテから抽出できる変数でも、予測時点で入力できるとは限りません。退院サマリの記載、最終診断名、転帰決定後の情報が該当します。収集可能性と予測時の利用可能性を分けます。
平均値、順位、クラスタ、主成分などを全データで作る型です。たとえば、全患者の歩行速度平均との差を特徴量にすると、検証データの情報も使います。統計量の計算も、訓練 fold の中だけで行います。
問診記録や診療録に、診断名や転帰が直接書かれている型です。「自宅退院予定」「施設調整中」などの語が入ると、モデルは文章の中の答えを拾います。テキストを使う場合は、記録時点と記載内容を確認します。
撮影機種、画素間隔、撮影日時、施設名がラベルの代理になる型です。画像 AI では、病変ではなく撮影条件を学ぶことがあります。DICOM tag、ファイル名、フォルダ名も確認します。施設別分割で性能を見る視点も有用です。
欠測補完を全データで行い、その後に分割する型です。補完モデルが検証データの分布を学びます。目的変数を含む補完では、アウトカム情報も影響します。CV では fold ごとに補完を fitします。
重要なのは、各型が重なり得る点です。たとえば、退院サマリのテキストを全データでベクトル化し、自宅退院を予測するとします。この場合、テキストリーケージ、時点の問題、前処理リーケージが同時に起こり得ます。1 つずつ分解して確認します。
各特徴量に当てるリーケージ点検:
1. 予測時点で取得できるか?
2. アウトカム発生より前に測定されているか?
3. 訓練データだけで作られているか?
4. 目的変数を直接エンコードしていないか?
5. 患者・施設・機器・評価者の identity をエンコードしていないか?
// 06 · IMPLEMENTATION · PYTHONPipeline と GroupKFold で防ぐ
scikit-learn では、前処理とモデルを Pipeline にまとめます。これにより、交差検証の各 fold 内で前処理が fit されます。同一患者の複数評価がある場合は、GroupKFold を使います[4]。以下は教育用の仮想データを想定したサンプルです。
# ============================================
# 教育用サンプル
# 実臨床データを使う場合は、個人情報保護、
# 倫理審査、施設ルール、利用規約を必ず確認してください。
# ============================================
# 自宅退院(home_discharge: 1=自宅, 0=その他)の予測を題材に、
# 同一患者の複数評価がある状況でリーケージを防ぐ書き方を示す。
import pandas as pd
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GroupKFold, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
# 教育用の仮想データを想定
# df = pd.read_csv("example_rehab_dataset.csv")
# 1 行 = 1 評価。同じ patient_id が複数回出現することがある。
# target: home_discharge (1 = 自宅, 0 = その他)
features = [
"age",
"days_from_onset_to_admission",
"fim_motor_admission",
"fim_cognition_admission",
"sias_leg_admission",
"stroke_type",
]
# 除外する未来情報の例:
# length_of_stay, discharge_fim_total,
# discharge_conference_note, discharge_destination_text
X = df[features]
y = df["home_discharge"]
groups = df["patient_id"]
num_cols = [
"age",
"days_from_onset_to_admission",
"fim_motor_admission",
"fim_cognition_admission",
"sias_leg_admission",
]
cat_cols = ["stroke_type"]
# Pipeline 内で前処理を fit する
num_pipe = Pipeline(steps=[
("imputer", SimpleImputer(strategy="median")),
("scaler", StandardScaler()),
])
cat_pipe = Pipeline(steps=[
("imputer", SimpleImputer(strategy="most_frequent")),
("onehot", OneHotEncoder(handle_unknown="ignore")),
])
preprocess = ColumnTransformer(transformers=[
("num", num_pipe, num_cols),
("cat", cat_pipe, cat_cols),
])
clf = LogisticRegression(
penalty="l2",
C=1.0,
max_iter=1000,
class_weight="balanced",
)
pipe = Pipeline(steps=[
("preprocess", preprocess),
("model", clf),
])
# 患者 ID で fold を切る
cv = GroupKFold(n_splits=5)
scores = cross_val_score(
estimator=pipe,
X=X,
y=y,
groups=groups,
cv=cv,
scoring="roc_auc",
)
print("AUC by fold:", np.round(scores, 3))
print("Mean AUC:", np.round(scores.mean(), 3))
print("SD AUC:", np.round(scores.std(ddof=1), 3))
# ============================================
# 悪い書き方の例(リーケージが起きる)
# ============================================
# 全データで scaler を fit してから CV すると、
# 検証データの平均・分散が訓練側に漏れる。
#
# scaler = StandardScaler().fit(X[num_cols])
# X_scaled = scaler.transform(X[num_cols])
# cross_val_score(clf, X_scaled, y, cv=5, scoring="roc_auc")
このコードの要点は、fit の位置です。imputer や scaler は、Pipeline の中にあります。そのため、各 fold の訓練側だけで学習されます。検証側は transform されるだけです。
GroupKFold では、同じ patient_id が train と validation に分かれません。これにより、繰り返し評価の情報漏れを抑えます。ただし、施設差を評価したい場合は facility_id を group にします。何を group とするかは、研究の問いで決まります。
ターゲットエンコーディングや特徴量選択も同じです。それらを分割前に実行すると、検証データの情報が入ります。特徴量選択や前処理を扱う後続記事でも、同じ考え方を使います。
欠測補完で KNNImputer を使う場合も同様です。近傍探索の基準が全データで作られると、検証データが混ざります。kNN の距離の考え方は、03·04 k 近傍法とつながります。補完器も Pipeline に入れて扱います。
// 07 · MYTHSよくある誤解
- 交差検証さえやればリークしない
- 交差検証は分割後の評価方法です。分割前に全データで標準化、補完、特徴量選択を行うと、CV の中にも漏れが残ります。前処理は Pipeline 内で行います。
- 同一患者でも別評価日なら独立サンプルとして扱える
- 同じ患者の背景、病変、生活環境は共有されています。別評価日でも独立とは限りません。患者 ID で group 分割する設計が必要になります。
- ターゲットエンコーディングは前処理だから問題ない
- 目的変数を使ってカテゴリを数値化するため、扱いを誤ると強いリーケージになります。fold 内で学習し、検証 fold には訓練 fold で得た変換だけを適用します。
- MICE で欠測補完してから分割でよい
- 全データで補完モデルを作ると、検証データの分布が訓練側に入ります。CV の各 fold 内で補完を学習する設計が必要です。補完に目的変数を含める場合は、報告で明記します。
誤解の背景には、前処理を「モデルの外」と考える習慣があります。しかし、機械学習では前処理も学習の一部です。平均、分散、欠測補完のルール、特徴量選択の基準は、データから学ばれます。そのため、評価データから学んではいけません。
線形回帰やロジスティック回帰のような古典的モデルでも、リーケージは起きます。ただし、どの変数を入れるかが漏れていると、モデルの種類に関係なく評価は歪みます。正則化を入れても、未来の情報そのものは消えません。
// 08 · WRITING論文 Methods で書くこと
リーケージ対策は、論文の Methods に明記します。「モデルを作った」だけでは足りません。どの時点の情報を使い、どの単位で分割し、前処理をどこで fit したかを書きます。TRIPOD+AI では、予測モデル研究の透明な報告が重視されています[2]。
- 予測時点:入院時、発症後何日、評価後何時間などを明記する
- 候補特徴量:予測時点で取得可能な変数に限定した理由を書く
- 除外特徴量:在院日数、退院時 FIM、退院先メモなどを除いた理由を書く
- 分割単位:患者 ID、施設 ID、撮影機器 ID など group の扱いを書く
- 前処理:補完、標準化、特徴量選択を fold 内で fit したかを書く
- 評価設計:検証データと最終テストデータを分けたかを書く
査読では、次の点が見られます。まず、アウトカム発生後の情報が説明変数に入っていないかです。次に、同一患者や同一施設の情報が train / validation にまたがっていないかです。さらに、欠測補完や標準化が分割前に行われていないかです。
Methods に書く文章例
「すべての前処理は、交差検証の各訓練 fold 内で fit した」と明記します。「同一患者の複数評価が複数 fold に分散しないよう、患者 ID を group とした」と書きます。「予測時点で取得できない変数は、候補特徴量から除外した」と説明します。
Clinical prediction model の文脈では、開発、検証、更新の各段階を分けることが重要です。Steyerberg は、臨床予測モデルで妥当な開発と検証を行うための実務的な考え方を整理しています[3]。リーケージ対策も、この妥当性の一部です。
// 09 · CHECKLISTリーケージ点検リスト
研究計画と論文読解のセルフチェックに使う 8 項目。
- 01予測時点を、入院時・初回評価時・退院前など具体的に決めている
- 02各特徴量が、その予測時点で本当に取得できるかを確認している
- 03退院日、退院時 FIM、在院日数など、未来の情報を除外している
- 04標準化、補完、特徴量選択を、分割後の訓練 fold 内で fit している
- 05同一患者、同一施設、同一撮影機器が train / validation にまたがるリスクを確認している
- 06test データを見ながら特徴量やハイパラを調整していないか確認している(test leakage の防止)
- 07テキスト・画像メタデータに、目的変数や施設情報が入り込んでいないかを点検している
- 08分割単位・前処理 fit 位置・除外変数を Methods に記述している
このチェックリストは、解析前に使うほど効果があります。解析後に気づくと、データセット作成から戻ることがあります。特に後ろ向き研究では、収集した変数が多いほど危険が増えます。変数表に「予測時点で利用可」という列を作ると、点検しやすくなります。
// 10 · QUIZミニクイズ
-
Q1入院時の自宅退院予測で、在院日数を説明変数に入れた。何が問題か?
- 在院日数は連続変数なので使えない
- 在院日数は退院後に確定する未来情報である
- ロジスティック回帰では日数を扱えない
- FIM と同時に使えない
SHOW ANSWER
B. 在院日数は予測時点では未確定です。ターゲットリーケージになります。 -
Q2同一患者の複数評価がある場合、まず検討する分割はどれか?
- 評価日ごとのランダム分割
- 患者 ID を group とした GroupKFold
- 全データで標準化してから KFold
- AUC が最大になる分割
SHOW ANSWER
B. 同じ患者が train と validation に分かれると、患者固有情報が漏れる可能性があります。患者 ID で group 分割します。 -
Q3
StandardScalerを全データで fit してから CV した。何が問題か?- 標準化は常に不要である
- 検証データの平均や分散が前処理に入る
- ロジスティック回帰では標準化できない
- AUC が計算できなくなる
SHOW ANSWER
B. 前処理は Pipeline に入れ、訓練 fold 内で fitします。これにより、検証データの情報が訓練側へ漏れない構造になります。 -
Q4後ろ向き研究で「カルテにある退院サマリのテキスト」を入院時予測の説明変数として使った。最も適切な対応は?
- そのまま使う(カルテに記載があるので問題ない)
- 記載時点を確認し、入院時に存在しないテキストは除外する
- テキストは常に使えないので削除する
- テキストを全データでベクトル化してから分割する
SHOW ANSWER
B. テキストの記録時点が予測時点より後であれば、ターゲットリーケージになります。記載時点を確認し、入院時に存在しないテキストは除外します。D の「全データでベクトル化してから分割」は前処理リーケージにあたります。
// REF参考文献
- Kaufman S, Rosset S, Perlich C. Leakage in data mining: Formulation, detection, and avoidance. ACM Transactions on Knowledge Discovery from Data 2012;6(4):1-21.
- 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.
- Steyerberg EW. Clinical Prediction Models: A Practical Approach to Development, Validation, and Updating. 2nd ed. Springer, 2019.
- Pedregosa F, Varoquaux G, Gramfort A, Michel V, Thirion B, Grisel O, et al. Scikit-learn: Machine learning in Python. Journal of Machine Learning Research 2011;12:2825-2830.