要点: リーク防止の5×5反復層化CV(675 fold評価)のもとで、9種類のデータ拡張戦略 × 3種類の分類器を比較した結果、PR-AUCでは TVAE が1位(0.854)となり、SMOTE(0.831)および強力な無拡張ベースライン(0.845)を上回った。ただし、TVAE の優位は記憶(メモライゼーション)によって交絡しており、慎重に解釈すべきである。
主な知見(すべての数値は outputs/metrics/ に基づく):
1. TVAE は有用性(utility)で勝るが、その一部は実レコードのコピーによるもの。 TVAE は3モデルすべてで PR-AUC において SMOTE を上回る(ペアWilcoxon p = 1.6e-4 LR、0.026 RF、0.019 XGB)。しかし、その合成少数クラス行は最もプライバシー性が低い。最近傍実レコードまでの距離の平均 = 3.84(Gaussian Copula の 6.17、CTGAN の 7.03 と比較)、TVAE 行の39%が DCR 閾値を下回り、55%が実患者のカテゴリ準重複である。したがって、見かけの利得は学習データの準重複によって水増しされている。これはまさに H3 で仮説とした小規模データにおける記憶リスクである。
2. データ拡張は無拡張をかろうじて上回るのみ。 none は2位(0.845)。データはすでにかなり分離可能であり(ROC-AUC ≈ 0.93)、Normal 少数クラスのリサンプリングはほとんど寄与しない。n=303 では、適切に正則化されたベースラインを信頼性高く安全に上回ることは難しい。
3. Gaussian Copula は SMOTE を上回らなかった(0.820 < 0.831)。これは事前の期待(H2)と矛盾する。Gaussian Copula は最も正直な生成器であり(完全重複0/準重複0、DCR 最高値 6.17)、balanced accuracy では競争力がある(最良の単一セル: GC + random_forest = 0.851)。しかし PR-AUC の有用性は低く、ペア検定では RF/XGB に対して SMOTE との有意差はなく、ロジスティック回帰では劣位であった。
4. CTGAN は明確に最下位(0.782)であり、すべてのモデルで SMOTE を有意に下回る。これは n=303 でデータ不足に陥った深層GANの典型例である。
5. SMOTE系の手法はベースライン付近に集まる。smotenc(混合型に対応)はその中で最良(0.843)であり、最も安全な「実質的な」改善シグナルである。
結論(ニュアンスを含むパターンB → C): SMOTE を統計的に上回る唯一の手法(TVAE)は、その一部を記憶によって達成しており、一方で安全な生成器(Gaussian Copula、CTGAN)は SMOTE を上回らない。このデータセットに対する妥当な結論は、n=303 では合成生成が SMOTE や無拡張に対してクリーンかつ安全な優位をもたらさないということであり、有用性(utility)/忠実度(fidelity)/プライバシーのトレードオフ(H4)が支配的である。単純で安全なベースラインとしては smotenc または class_weight を用いるべきであり、TVAE のヘッドライン数値は臨床的シグナルではなく記憶に交絡したものとして扱うべきである。
日本語要約: 9手法×3分類器・リーク防止5×5 CV(計675評価)で PR-AUC 最良は TVAE (0.854)。 ただし TVAE は合成行の DCR が最小(3.84)・39%が閾値内・カテゴリ準重複55% と実データを強く 「記憶」しており、利得は記憶バイアスで水増しされている可能性が高い。Gaussian Copula(0.820) は SMOTE(0.831) を上回らず(H2は不成立)、安全だが utility は劣る。CTGAN(0.782) は全モデルで 最下位。無拡張(0.845)も強く、n=303 では合成生成が SMOTE / 無拡張に対して明確かつ安全な優位を もたらすとは言えない(utility と fidelity/privacy のトレードオフが支配的)。実務的には smotenc / class_weight が安全な選択。
local_snapshot)Cath のクラス数: {'Cad': 216, 'Normal': 87}Normal。正例(y=1)としてモデル化。主要指標: PR-AUC(Average Precision) — 少数クラスを正例とするタスクに適切。
平均 PR-AUC による総合ランキング(モデル平均、ratio=1.0):
| rank | method | mean average_precision |
|---|---|---|
| 1 | tvae | 0.854 |
| 2 | none | 0.845 |
| 3 | smotenc | 0.843 |
| 4 | class_weight_balanced | 0.842 |
| 5 | smote | 0.831 |
| 6 | adasyn | 0.830 |
| 7 | borderline_smote | 0.828 |
| 8 | gaussian_copula | 0.820 |
| 9 | ctgan | 0.782 |
指標別の最良(method, model):
PR-AUC による最良:
| method | model | ratio | average_precision |
|---|---|---|---|
| tvae | random_forest | 1.0 | 0.863 (±0.070) |
| tvae | logistic_regression | 1.0 | 0.860 (±0.068) |
| none | logistic_regression | 1.0 | 0.855 (±0.068) |
| none | random_forest | 1.0 | 0.852 (±0.075) |
| smotenc | logistic_regression | 1.0 | 0.851 (±0.072) |
| class_weight_balanced | logistic_regression | 1.0 | 0.850 (±0.073) |
Balanced Accuracy による最良:
| method | model | ratio | balanced_accuracy |
|---|---|---|---|
| gaussian_copula | random_forest | 1.0 | 0.851 (±0.050) |
| class_weight_balanced | random_forest | 1.0 | 0.851 (±0.061) |
| adasyn | random_forest | 1.0 | 0.849 (±0.053) |
| class_weight_balanced | logistic_regression | 1.0 | 0.844 (±0.048) |
| smotenc | logistic_regression | 1.0 | 0.843 (±0.048) |
| smote | random_forest | 1.0 | 0.841 (±0.048) |
Brier スコアによる最良(低いほど良い):
| method | model | ratio | brier_score |
|---|---|---|---|
| tvae | logistic_regression | 1.0 | 0.098 (±0.030) |
| none | logistic_regression | 1.0 | 0.099 (±0.029) |
| smotenc | logistic_regression | 1.0 | 0.102 (±0.031) |
| tvae | random_forest | 1.0 | 0.103 (±0.019) |
| tvae | xgboost | 1.0 | 0.105 (±0.031) |
| smotenc | random_forest | 1.0 | 0.105 (±0.020) |
Recall@Precision≥0.80 による最良:
| method | model | ratio | recall_at_prec_80 |
|---|---|---|---|
| none | random_forest | 1.0 | 0.747 (±0.201) |
| class_weight_balanced | random_forest | 1.0 | 0.742 (±0.207) |
| smotenc | random_forest | 1.0 | 0.736 (±0.174) |
| tvae | random_forest | 1.0 | 0.729 (±0.198) |
| smote | random_forest | 1.0 | 0.717 (±0.229) |
| none | xgboost | 1.0 | 0.712 (±0.198) |
図: pr_auc_boxplot.png、roc_auc_boxplot.png、brier_score_boxplot.png、balanced_accuracy_boxplot.png、topk_precision.png。
参照となる SMOTE の平均 PR-AUC = 0.831。手法別の平均 PR-AUC:
smote: 0.831(SMOTE比 +0.000)smotenc: 0.843(SMOTE比 +0.012)borderline_smote: 0.828(SMOTE比 -0.003)adasyn: 0.830(SMOTE比 -0.001)gaussian_copula: 0.820(SMOTE比 -0.011)ctgan: 0.782(SMOTE比 -0.048)tvae: 0.854(SMOTE比 +0.023)SMOTE とのペア比較(Wilcoxon 符号順位検定、fold単位、PR-AUC):
| method | model | mean_diff | p_value | n |
|---|---|---|---|---|
| tvae | random_forest | 0.025 | 0.026 | 25 |
| tvae | logistic_regression | 0.023 | 0.000 | 25 |
| tvae | xgboost | 0.022 | 0.019 | 25 |
| none | logistic_regression | 0.018 | 0.003 | 25 |
| none | random_forest | 0.014 | 0.134 | 25 |
| smotenc | logistic_regression | 0.014 | 0.010 | 25 |
| smotenc | xgboost | 0.013 | 0.030 | 25 |
| class_weight_balanced | logistic_regression | 0.013 | 0.012 | 25 |
| class_weight_balanced | xgboost | 0.011 | 0.107 | 25 |
| none | xgboost | 0.011 | 0.182 | 25 |
| class_weight_balanced | random_forest | 0.011 | 0.032 | 25 |
| smotenc | random_forest | 0.009 | 0.230 | 25 |
| adasyn | logistic_regression | 0.004 | 0.442 | 25 |
| gaussian_copula | random_forest | 0.003 | 0.711 | 25 |
| borderline_smote | logistic_regression | 0.003 | 0.791 | 25 |
| gaussian_copula | xgboost | 0.000 | 0.874 | 25 |
| adasyn | random_forest | -0.003 | 0.833 | 25 |
| adasyn | xgboost | -0.004 | 0.979 | 25 |
| borderline_smote | xgboost | -0.004 | 0.578 | 25 |
| borderline_smote | random_forest | -0.008 | 0.442 | 25 |
| ctgan | random_forest | -0.031 | 0.007 | 25 |
| gaussian_copula | logistic_regression | -0.035 | 0.006 | 25 |
| ctgan | xgboost | -0.054 | 0.000 | 25 |
| ctgan | logistic_regression | -0.061 | 0.000 | 25 |
CV の fold は完全には独立ではない。p値は確証的なものではなく、あくまで参考として扱うこと。
fold_metrics.csv(n_synthetic=0 の行)を参照。忠実度(fidelity)(SDMetrics、少数クラス合成 vs 少数クラス実データ、fold 0):
| method | overall_quality | column_shapes | column_pair_trends |
|---|---|---|---|
| gaussian_copula | 0.781 | 0.886 | 0.677 |
| ctgan | 0.718 | 0.832 | 0.604 |
| tvae | 0.736 | 0.847 | 0.625 |
プライバシー / 記憶(メモライゼーション)の代理指標(正式な保証ではない):
| method | exact_duplicate_rate | categorical_quasi_duplicate_rate | dcr_mean | dcr_p05 | dcr_below_threshold_rate |
|---|---|---|---|---|---|
| gaussian_copula | 0.000 | 0.000 | 6.167 | 5.292 | 0.000 |
| ctgan | 0.000 | 0.000 | 7.032 | 5.768 | 0.000 |
| tvae | 0.000 | 0.549 | 3.842 | 3.161 | 0.392 |
図: nn_distance_distribution.png(最近傍実レコードまでの距離の分布)。
Brier スコアと ECE は各 fold の生のモデル確率に対して計算される(主要な結果 / boxplot を参照)。手法別の信頼性曲線は calibration_curves.png にある。確率はさらに、学習fold内でフィットした Platt スケーリング / 等調回帰(isotonic regression)で再校正できる(cad_synth.calibration.compare_calibration)。
本実験で比較する各データ拡張/合成生成手法について、概要・仕組み・長所・注意点・参考URLをまとめる。
実装は src/cad_synth/samplers.py(無拡張・SMOTE 系)と src/cad_synth/synthesizers.py(SDV 合成生成)にある。
いずれも各 training fold 内でのみ fit し、少数クラスを目標比率(sampling_ratio)まで拡張する。
記法: 「少数クラス」= 本データでは
Normal(正例)。SMOTE 系の近傍数kは、少数クラスのサンプル数が少ない fold では自動的に縮小される(k = min(5, n_minority − 1))。
X, y をそのまま返す)。他手法が「無拡張に対して本当に改善するのか」を測る基準線。class_weight='balanced')。n_samples / (n_classes × n_class) で重み付け。本実装では拡張器は恒等で、ランナーが分類器に class_weight='balanced' を設定する。いずれも少数クラスのサンプル空間を補間・複製して増やす手法。混在型データでは、素の SMOTE がカテゴリ/二値列を小数に補間してしまうため、型の扱いが重要(smotenc 参照)。本実装ではカテゴリ列を整数エンコードして処理し、生成後に最近傍カテゴリへ復元する。
RandomOverSampler)。k 近傍の少数クラス点との間を線形補間して合成点を作る(Chawla ら, 2002)。x と近傍 x_nn に対し x_new = x + λ(x_nn − x)(λ∈[0,1])。特徴空間はユークリッド距離を仮定。categorical_features に渡す(カテゴリ列が無い fold では素の SMOTE にフォールバック)。m_neighbors で危険度を判定)。X_train + y_train の同時分布を生成モデルで学習し、少数クラスの行を条件付き/棄却サンプリングで生成する。SMOTE 系の局所補間と異なり、データ全体の分布・相関を学習する点が特徴。本実装では fold ごとに1回学習し、複数モデル間で再利用する。
epochs=150, batch_size=60)。epochs=150, batch_size=60)。非線形な特徴量依存を生成モデルが捉えた可能性がある。ただし、小規模データでの記憶リスクを追加評価する必要がある。
CAD ではなく Normal である。Normal のオーバーサンプリングは CAD 検出の感度を直接改善するものではない。configs/full.yaml を実行する(5×20 CV、LightGBM・SVM を含む全手法/全モデルのグリッド)。cad_positive 方向を評価する。本ドキュメントは、実験パイプラインのエンジニアリングおよび前処理の詳細を、再現性・実装レベルの理解を求める読者に向けて説明するものである。記載内容はすべてリポジトリのソース(src/cad_synth/preprocessing.py, README.md, configs/report.yaml, SPEC.md)に基づく。
エンドツーエンドの処理は以下の流れで進む。
src/cad_synth/data.py が data/raw/ のローカルスナップショット(z_alizadeh_sani.xlsx/.csv)を優先し、なければ ucimlrepo.fetch_ucirepo(id=412) を試行する。detect_feature_types により、各カラムを数値/カテゴリ/削除に分類する(§2)。RepeatedStratifiedKFold(5×5, random_state=42)で層化交差検証の fold を生成する。build_preprocessor が生成する ColumnTransformer を、各 training fold 内でのみ fit する(§3)。重要: fold 分割以降のあらゆる処理(補完・エンコーディング・スケーリング・リサンプリング・合成・閾値調整・校正)は、各 training fold の内側でのみ fit される。CV split より前に全データへ適用することはない(§4)。
detect_feature_types(X, max_categorical_cardinality=12) は各カラムを次のルールで分類する。
Exertional CP)。max_categorical_cardinality(=12)以下で、値がすべて整数)。なぜこの判定が必要か:
結果: 数値 20 / カテゴリ 34 / 削除 1。
build_preprocessor(model_name, schema) は、モデルの系統に応じた未 fit の ColumnTransformer を返す。
random_forest, xgboost):SimpleImputer(strategy="median") による中央値補完。SimpleImputer(strategy="most_frequent")(最頻値補完)+ OneHotEncoder(handle_unknown='ignore')。logistic_regression, svm_rbf):StandardScaler を適用する。ColumnTransformer は remainder='drop' を指定し、変換対象外のカラムは破棄する。補完は中央値/最頻値で行うが、本データセットは実質的に完全(欠損なし)であるため、補完はセーフティネットとして機能する。
RepeatedStratifiedKFold(5分割 × 5反復, random_state=42)。SDV 合成生成器:
gaussian_copula — 古典的な統計モデル。ctgan — epochs=150, batch_size=60。tvae — epochs=150, batch_size=60。max_sample_attempts=20。SMOTE 系:
smote, smotenc(混在型を認識), borderline_smote, adasyn。共通設定:
1.0(少数クラスを多数クラスと同数まで拡張してバランスさせる)。pyproject.toml + uv.lock により完全に固定される。random_state=42 により fold 分割・生成を固定。主なコマンド:
uv sync --extra dev
uv run python experiments/run_experiment.py --config configs/report.yaml # 約20分
uv run python experiments/build_report_html.py
出力レイアウト(outputs/ 配下):
metrics/ — fold_metrics.csv, aggregate_metrics.csv, method_model_summary.csv, statistical_tests.csv, synthetic_quality.csv, fold_predictions.csv。figures/ — 各種箱ひげ図・EDA 図。synthetic_samples/ — fold_0_<method>_r1.0.csv。reports/ — experiment_report.md, data_profile.md, experiment_report.html。Pipeline / ColumnTransformer / SimpleImputer / OneHotEncoder / StandardScaler、および RepeatedStratifiedKFold。smote, smotenc, borderline_smote, adasyn)。gaussian_copula, ctgan, tvae)。ソース: data/raw/z_alizadeh_sani.xlsx · 患者数: 303 · カラム数: 56(55特徴量 + ターゲット Cath)
欠損値: 0(データセットは完全に揃っており、補完は不要)。
object(文字列)、34列が数値(int64/float64)。これらの整数コード化された二値フラグは、dtype としては数値だが意味的にはカテゴリであり、値を {0,1} に保つため、あらゆる SMOTE/合成生成パイプラインではカテゴリとして明示する必要がある。
| クラス | n | 割合 |
|---|---|---|
| Cad(多数派) | 216 | 71.3% |
| Normal(少数派 / 正例) | 87 | 28.7% |
不均衡比 ≈ 2.48 : 1(Cad : Normal)。Normal は少数クラスであり、下流の実験では正例として扱われる。これがオーバーサンプリング/合成によって拡張すべきクラスである。
全体の平均 ± 標準偏差、続いてクラス別、そして Cohen's d(Cad − Normal)。|d| > 0.5 はおよそ中程度の分離を意味する。
| 特徴量 | 平均 | 標準偏差 | Cad 平均 | Normal 平均 | Cohen's d |
|---|---|---|---|---|---|
| Age | 58.90 | 10.39 | 61.25 | 53.06 | +0.84 |
| BMI | 27.25 | 4.10 | 27.05 | 27.75 | -0.17 |
| BP | 129.55 | 18.94 | 132.41 | 122.47 | +0.54 |
| FBS | 119.18 | 52.08 | 125.97 | 102.34 | +0.46 |
| LDL | 104.64 | 35.40 | 104.12 | 105.95 | -0.05 |
| HDL | 40.23 | 10.56 | 39.95 | 40.94 | -0.09 |
| TG | 150.34 | 97.96 | 159.07 | 128.68 | +0.31 |
| EF-TTE | 47.23 | 8.93 | 45.91 | 50.52 | -0.53 |
| ESR | 19.46 | 15.94 | 21.26 | 14.99 | +0.40 |
| HB | 13.15 | 1.61 | 13.11 | 13.26 | -0.09 |
最も分離のよい数値特徴量: Age(Cad 患者は約8歳年上)、低い EF-TTE(Cad では駆出率(EF)の低下)、高い BP、そして高い FBS/ESR。LDL, HDL, HB, BMI はクラス間でほとんど分離しない。
全体および各クラス内での陽性率(% positive)。
| 特徴量 | 全体 % | Cad % | Normal % |
|---|---|---|---|
| Sex = Male | 58.1 | 60.2 | 52.9 |
| DM = 1 | 29.7 | 37.0 | 11.5 |
| HTN = 1 | 59.1 | 68.1 | 36.8 |
| Typical Chest Pain = 1 | 54.1 | 71.3 | 11.5 |
| Current Smoker = 1 | 20.8 | 22.7 | 16.1 |
| FH = 1 | 15.8 | 16.7 | 13.8 |
| Region RWMA > 0 | 28.4 | 38.0 | 4.6 |
最も分離のよいカテゴリ特徴量: Typical Chest Pain(Cad で71%に対し Normal で12%)と Region RWMA > 0(38% 対 5%)は、データセット中で群を抜いて識別力の高い単一特徴量である。DM と HTN も Cad で顕著に多い。Sex, 喫煙, 家族歴は分離が弱い。
大半の数値特徴量は相関が弱い。|r| ≥ 0.4 のペア:
| ペア | r |
|---|---|
| Lymph ↔ Neut | -0.92 |
| Weight ↔ BMI | +0.73 |
| CR ↔ BUN | +0.51 |
| Weight ↔ Length | +0.46 |
Lymph/Neut はほぼ完全な負の相関を示し(両者は合計がおよそ100%になる相補的な白血球分画のパーセンテージである)、Weight/BMI は機構的に連動している(BMI は Weight と Length から導出される)。これらの冗長性は、相関を考慮する合成生成器や特徴量リークの回避において重要である。eda_correlation_heatmap.png を参照。
Exertional CP は100%が 'N' であり、分散がゼロで削除すべきである(情報を持たず、一部の指標を破綻させる)。outputs/figures/eda_target_distribution.png — クラス数と不均衡。outputs/figures/eda_numeric_by_class.png — クラス別に分割した主要な数値特徴量10件の箱ひげ図。outputs/figures/eda_correlation_heatmap.png — 数値相関行列。実験によって生成されたすべての図を、インラインで埋め込んで一覧表示します。