同一の実験設計(リーク防止 5×5 反復層化CV・9手法・3モデル・主要指標 PR-AUC)を、性質の異なる4つの不均衡二値分類データセットに適用し、SMOTE 系オーバーサンプリングと合成データ生成(Gaussian Copula / CTGAN / TVAE)の優劣がデータセットによってどう変わるかを比較する。
| データセット | n | 特徴量 | 少数クラス(率) | 数値/カテゴリ |
|---|---|---|---|---|
| Z-Alizadeh Sani 冠動脈疾患 | 303 | 55 | Normal(28.7%) | 20 / 34 |
| Pima Indians 糖尿病 | 768 | 8 | 1(34.9%) | 8 / 0 |
| German Credit 信用リスク | 1000 | 20 | 0(30.0%) | 3 / 17 |
| Heart Disease (Cleveland) | 303 | 13 | 0(45.5%) | 5 / 8 |
Z-Alizadeh Sani の完全な単体レポート(全項目・エグゼクティブサマリー・全図)は 詳細レポート を参照。
下図は主要手法の平均 PR-AUC をデータセット横断で並べたもの(cross_pr_auc.png)。
| 手法 | Z-Alizadeh Sani 冠動脈疾患 | Pima Indians 糖尿病 | German Credit 信用リスク | Heart Disease (Cleveland) |
|---|---|---|---|---|
tvae | 0.854 | 0.700 | 0.611 | 0.899 |
ctgan | 0.782 | 0.704 | 0.563 | 0.899 |
gaussian_copula | 0.820 | 0.691 | 0.596 | 0.902 |
smote | 0.831 | 0.704 | 0.588 | 0.901 |
smotenc | 0.843 | 0.704 | 0.614 | 0.901 |
borderline_smote | 0.828 | 0.691 | 0.591 | 0.903 |
adasyn | 0.830 | 0.694 | 0.587 | 0.902 |
class_weight_balanced | 0.842 | 0.709 | 0.626 | 0.902 |
none | 0.845 | 0.708 | 0.628 | 0.902 |
各列の最良手法を太字で示す。
tvae(0.854)/合成生成の最良 tvae(0.854)が SMOTE(0.831)を上回る。 判定パターン B(CTGAN / TVAE が SMOTE を上回る)。class_weight_balanced(0.709)/合成生成の最良 ctgan(0.704)が SMOTE(0.704)を上回る。 判定パターン D(class_weight / threshold tuning が最良)。none(0.628)/合成生成の最良 tvae(0.611)が SMOTE(0.588)を上回る。 判定パターン C(SMOTE 系が最良)。borderline_smote(0.903)/合成生成の最良 gaussian_copula(0.902)が SMOTE(0.901)を上回る。 判定パターン C(SMOTE 系が最良)。記憶(メモライゼーション)リスク: 深層生成モデル(特に TVAE)が SMOTE を上回る場合でも、小規模データでは実レコードの準重複によって利得が水増しされることがある。各データセットタブの「合成品質(DCR)」を併せて参照。
Cath、正例(少数クラス)= Normal(28.7%)/クラス数 {'Cad': 216, 'Normal': 87}| 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 |
基準 SMOTE の平均 PR-AUC = 0.831。手法別の SMOTE 比:
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 値は示唆的に扱う。
忠実度(fidelity)(SDMetrics, 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 |
プライバシー / 記憶(メモライゼーション)代理指標(DCR ほか、正式な保証ではない):
| 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 |
図: pr_auc_boxplot.png, roc_auc_boxplot.png, brier_score_boxplot.png, nn_distance_distribution.png。
Outcome、正例(少数クラス)= 1(34.9%)/クラス数 {'0': 500, '1': 268}| rank | method | mean average_precision |
|---|---|---|
| 1 | class_weight_balanced | 0.709 |
| 2 | none | 0.708 |
| 3 | ctgan | 0.704 |
| 4 | smotenc | 0.704 |
| 5 | smote | 0.704 |
| 6 | tvae | 0.700 |
| 7 | adasyn | 0.694 |
| 8 | borderline_smote | 0.691 |
| 9 | gaussian_copula | 0.691 |
基準 SMOTE の平均 PR-AUC = 0.704。手法別の SMOTE 比:
smotenc: 0.704(SMOTE比 +0.000)borderline_smote: 0.691(SMOTE比 -0.013)adasyn: 0.694(SMOTE比 -0.009)gaussian_copula: 0.691(SMOTE比 -0.013)ctgan: 0.704(SMOTE比 +0.001)tvae: 0.700(SMOTE比 -0.003)SMOTE とのペア比較(Wilcoxon 符号順位検定、fold 単位、PR-AUC):
| method | model | mean_diff | p_value | n |
|---|---|---|---|---|
| ctgan | random_forest | 0.014 | 0.052 | 25 |
| class_weight_balanced | random_forest | 0.010 | 0.001 | 25 |
| none | random_forest | 0.010 | 0.022 | 25 |
| class_weight_balanced | xgboost | 0.003 | 0.411 | 25 |
| none | logistic_regression | 0.002 | 0.127 | 25 |
| class_weight_balanced | logistic_regression | 0.001 | 0.156 | 25 |
| none | xgboost | 0.001 | 0.508 | 25 |
| tvae | xgboost | 0.000 | 0.916 | 25 |
| ctgan | xgboost | 0.000 | 0.731 | 25 |
| smotenc | logistic_regression | 0.000 | 1.000 | 25 |
| smotenc | xgboost | 0.000 | 1.000 | 25 |
| smotenc | random_forest | 0.000 | 1.000 | 25 |
| gaussian_copula | random_forest | -0.002 | 0.874 | 25 |
| tvae | random_forest | -0.003 | 0.672 | 25 |
| adasyn | logistic_regression | -0.004 | 0.007 | 25 |
| gaussian_copula | xgboost | -0.006 | 0.542 | 25 |
| borderline_smote | logistic_regression | -0.006 | 0.042 | 25 |
| tvae | logistic_regression | -0.007 | 0.220 | 25 |
| adasyn | xgboost | -0.011 | 0.022 | 25 |
| ctgan | logistic_regression | -0.011 | 0.141 | 25 |
| borderline_smote | xgboost | -0.013 | 0.015 | 25 |
| adasyn | random_forest | -0.013 | 0.008 | 25 |
| borderline_smote | random_forest | -0.020 | 0.003 | 25 |
| gaussian_copula | logistic_regression | -0.031 | 0.001 | 25 |
CV fold は完全独立ではないため、p 値は示唆的に扱う。
忠実度(fidelity)(SDMetrics, fold 0):
| method | overall_quality | column_shapes | column_pair_trends |
|---|---|---|---|
| gaussian_copula | 0.826 | 0.744 | 0.909 |
| ctgan | 0.681 | 0.661 | 0.700 |
| tvae | 0.882 | 0.802 | 0.961 |
プライバシー / 記憶(メモライゼーション)代理指標(DCR ほか、正式な保証ではない):
| method | exact_duplicate_rate | dcr_mean | dcr_p05 | dcr_below_threshold_rate |
|---|---|---|---|---|
| gaussian_copula | 0.000 | 1.853 | 0.978 | 0.011 |
| ctgan | 0.000 | 2.020 | 1.180 | 0.005 |
| tvae | 0.000 | 1.175 | 0.715 | 0.048 |
図: pr_auc_boxplot.png, roc_auc_boxplot.png, brier_score_boxplot.png, nn_distance_distribution.png。
credit_risk、正例(少数クラス)= 0(30.0%)/クラス数 {'1': 700, '0': 300}| rank | method | mean average_precision |
|---|---|---|
| 1 | none | 0.628 |
| 2 | class_weight_balanced | 0.626 |
| 3 | smotenc | 0.614 |
| 4 | tvae | 0.611 |
| 5 | gaussian_copula | 0.596 |
| 6 | borderline_smote | 0.591 |
| 7 | smote | 0.588 |
| 8 | adasyn | 0.587 |
| 9 | ctgan | 0.563 |
基準 SMOTE の平均 PR-AUC = 0.588。手法別の SMOTE 比:
smotenc: 0.614(SMOTE比 +0.025)borderline_smote: 0.591(SMOTE比 +0.002)adasyn: 0.587(SMOTE比 -0.001)gaussian_copula: 0.596(SMOTE比 +0.008)ctgan: 0.563(SMOTE比 -0.025)tvae: 0.611(SMOTE比 +0.022)SMOTE とのペア比較(Wilcoxon 符号順位検定、fold 単位、PR-AUC):
| method | model | mean_diff | p_value | n |
|---|---|---|---|---|
| tvae | logistic_regression | 0.052 | 0.000 | 25 |
| none | logistic_regression | 0.050 | 0.000 | 25 |
| smotenc | logistic_regression | 0.048 | 0.000 | 25 |
| class_weight_balanced | logistic_regression | 0.046 | 0.000 | 25 |
| none | xgboost | 0.036 | 0.000 | 25 |
| class_weight_balanced | xgboost | 0.035 | 0.002 | 25 |
| none | random_forest | 0.034 | 0.000 | 25 |
| class_weight_balanced | random_forest | 0.031 | 0.001 | 25 |
| smotenc | xgboost | 0.024 | 0.063 | 25 |
| tvae | xgboost | 0.023 | 0.090 | 25 |
| gaussian_copula | logistic_regression | 0.022 | 0.008 | 25 |
| gaussian_copula | random_forest | 0.008 | 0.252 | 25 |
| borderline_smote | logistic_regression | 0.007 | 0.173 | 25 |
| borderline_smote | xgboost | 0.006 | 0.067 | 25 |
| smotenc | random_forest | 0.004 | 0.711 | 25 |
| adasyn | logistic_regression | 0.002 | 0.791 | 25 |
| adasyn | xgboost | 0.001 | 0.596 | 25 |
| borderline_smote | random_forest | -0.006 | 0.353 | 25 |
| gaussian_copula | xgboost | -0.006 | 0.442 | 25 |
| adasyn | random_forest | -0.007 | 0.263 | 25 |
| ctgan | xgboost | -0.008 | 0.458 | 25 |
| tvae | random_forest | -0.009 | 0.381 | 25 |
| ctgan | random_forest | -0.028 | 0.012 | 25 |
| ctgan | logistic_regression | -0.039 | 0.004 | 25 |
CV fold は完全独立ではないため、p 値は示唆的に扱う。
忠実度(fidelity)(SDMetrics, fold 0):
| method | overall_quality | column_shapes | column_pair_trends |
|---|---|---|---|
| gaussian_copula | 0.878 | 0.930 | 0.826 |
| ctgan | 0.802 | 0.850 | 0.753 |
| tvae | 0.841 | 0.868 | 0.813 |
プライバシー / 記憶(メモライゼーション)代理指標(DCR ほか、正式な保証ではない):
| method | exact_duplicate_rate | categorical_quasi_duplicate_rate | dcr_mean | dcr_p05 | dcr_below_threshold_rate |
|---|---|---|---|---|---|
| gaussian_copula | 0.000 | 0.000 | 3.216 | 2.521 | 0.009 |
| ctgan | 0.000 | 0.000 | 3.415 | 2.726 | 0.006 |
| tvae | 0.000 | 0.016 | 2.458 | 1.561 | 0.338 |
図: pr_auc_boxplot.png, roc_auc_boxplot.png, brier_score_boxplot.png, nn_distance_distribution.png。
target、正例(少数クラス)= 0(45.5%)/クラス数 {'1': 165, '0': 138}| rank | method | mean average_precision |
|---|---|---|
| 1 | borderline_smote | 0.903 |
| 2 | class_weight_balanced | 0.902 |
| 3 | adasyn | 0.902 |
| 4 | none | 0.902 |
| 5 | gaussian_copula | 0.902 |
| 6 | smotenc | 0.901 |
| 7 | smote | 0.901 |
| 8 | ctgan | 0.899 |
| 9 | tvae | 0.899 |
基準 SMOTE の平均 PR-AUC = 0.901。手法別の SMOTE 比:
smotenc: 0.901(SMOTE比 +0.001)borderline_smote: 0.903(SMOTE比 +0.002)adasyn: 0.902(SMOTE比 +0.001)gaussian_copula: 0.902(SMOTE比 +0.001)ctgan: 0.899(SMOTE比 -0.002)tvae: 0.899(SMOTE比 -0.002)SMOTE とのペア比較(Wilcoxon 符号順位検定、fold 単位、PR-AUC):
| method | model | mean_diff | p_value | n |
|---|---|---|---|---|
| gaussian_copula | xgboost | 0.004 | 0.090 | 25 |
| borderline_smote | logistic_regression | 0.003 | 0.011 | 25 |
| class_weight_balanced | random_forest | 0.003 | 0.230 | 25 |
| borderline_smote | xgboost | 0.002 | 0.263 | 25 |
| ctgan | logistic_regression | 0.002 | 0.491 | 25 |
| borderline_smote | random_forest | 0.002 | 0.071 | 25 |
| smotenc | logistic_regression | 0.002 | 0.107 | 25 |
| adasyn | logistic_regression | 0.002 | 0.063 | 25 |
| none | logistic_regression | 0.002 | 0.063 | 25 |
| adasyn | random_forest | 0.001 | 0.381 | 25 |
| none | random_forest | 0.001 | 0.381 | 25 |
| smotenc | xgboost | 0.001 | 0.312 | 25 |
| class_weight_balanced | logistic_regression | 0.001 | 0.085 | 25 |
| adasyn | xgboost | 0.001 | 0.560 | 25 |
| none | xgboost | 0.001 | 0.560 | 25 |
| class_weight_balanced | xgboost | 0.001 | 0.339 | 25 |
| tvae | logistic_regression | 0.001 | 0.937 | 25 |
| gaussian_copula | random_forest | -0.000 | 0.853 | 25 |
| gaussian_copula | logistic_regression | -0.000 | 0.874 | 25 |
| smotenc | random_forest | -0.001 | 0.381 | 25 |
| ctgan | xgboost | -0.002 | 0.560 | 25 |
| tvae | xgboost | -0.002 | 0.426 | 25 |
| tvae | random_forest | -0.004 | 0.148 | 25 |
| ctgan | random_forest | -0.005 | 0.045 | 25 |
CV fold は完全独立ではないため、p 値は示唆的に扱う。
忠実度(fidelity)(SDMetrics, fold 0):
| method | overall_quality | column_shapes | column_pair_trends |
|---|---|---|---|
| gaussian_copula | 0.661 | 0.806 | 0.515 |
| ctgan | 0.597 | 0.731 | 0.463 |
| tvae | 0.600 | 0.732 | 0.467 |
プライバシー / 記憶(メモライゼーション)代理指標(DCR ほか、正式な保証ではない):
| method | exact_duplicate_rate | categorical_quasi_duplicate_rate | dcr_mean | dcr_p05 | dcr_below_threshold_rate |
|---|---|---|---|---|---|
| gaussian_copula | 0.000 | 0.045 | 2.442 | 1.999 | 0.000 |
| ctgan | 0.000 | 0.182 | 2.826 | 2.001 | 0.000 |
| tvae | 0.000 | 0.909 | 2.128 | 1.693 | 0.000 |
図: pr_auc_boxplot.png, roc_auc_boxplot.png, brier_score_boxplot.png, nn_distance_distribution.png。
本実験で比較する各データ拡張/合成生成手法について、概要・仕組み・長所・注意点・参考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)。本ドキュメントは、実験パイプラインのエンジニアリングおよび前処理の詳細を、再現性・実装レベルの理解を求める読者に向けて説明するものである。記載内容はすべてリポジトリのソース(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)。