synthcity 完整教學

Repository: https://github.com/vanderschaarlab/synthcity Stars: 664 | Fork: 94 | License: Apache-2.0 Tags: synthetic-data, privacy, fairness, pytorch, tabular-data, generative-model 最新版本: v0.2.12 (2025-05-08) 論文: arXiv:2301.07573

2. 核心架構

2.1 系統架構圖


graph TB
    subgraph Input["輸入層 Input Layer"]
        RAW["原始資料
Raw Data"] RAW --> GDL["GenericDataLoader"] RAW --> SDL["SurvivalAnalysisDataLoader"] RAW --> TDL["TimeSeriesDataLoader"] RAW --> IDL["ImageDataLoader"] end subgraph PluginRegistry["Plugin 註冊中心"] PR["Plugins()"] PR -->|"categories=generic"| GEN["Generic Plugins
CTGAN, TVAE, NFlow, ARF,
DDPM, GReaT, BN, RTVAE..."] PR -->|"categories=privacy"| PRIV["Privacy Plugins
AdsGAN, DP-GAN, PATEGAN,
PrivBayes, DECAF, AIM"] PR -->|"categories=survival"| SURV["Survival Plugins
SurvivalGAN, SurVAE,
Survival-CTGAN"] PR -->|"categories=time_series"| TS["Time Series Plugins
TimeGAN, FourierFlows,
TimeVAE"] end subgraph Training["訓練與生成"] FIT["model.fit(dataloader)"] GEN2["model.generate(count=N)"] FIT --> GEN2 end subgraph Evaluation["評估引擎 Metrics Engine"] BENCH["Benchmarks.evaluate()"] BENCH --> M1["eval_sanity
基本健全性"] BENCH --> M2["eval_statistical
統計一致性"] BENCH --> M3["eval_privacy
隱私風險"] BENCH --> M4["eval_detection
合成偵測"] BENCH --> M5["eval_performance
下游效能"] BENCH --> M6["eval_attacks
攻擊模擬"] end GDL --> FIT SDL --> FIT TDL --> FIT IDL --> FIT GEN2 --> BENCH style Input fill:#e1f5fe,stroke:#0288d1 style PluginRegistry fill:#f3e5f5,stroke:#7b1fa2 style Training fill:#e8f5e9,stroke:#388e3c style Evaluation fill:#fff3e0,stroke:#f57c00

2.2 Plugin 機制

synthcity 的核心設計是 Plugin Pattern (插件模式):每個生成器都是一個繼承自 Plugin 基底類別的獨立模組。所有生成器共享相同的介面:

1Plugin (基底類別)
2  ├── name()         插件名稱
3  ├── type()         插件類型 (generic / privacy / ...)
4  ├── hyperparameter_space()  超參數搜尋空間
5  ├── fit(dataloader)         訓練
6  ├── generate(count, constraints)  生成
7  └── save() / load()         序列化

2.3 DataLoader 體系


classDiagram
    class DataLoader {
        <>
        +dataframe() DataFrame
        +info() dict
        +sample(count) DataLoader
        +train() DataLoader
        +test() DataLoader
        +hash() str
    }
    class GenericDataLoader {
        +target_column: str
        +sensitive_columns: list
        +fairness_column: str
    }
    class SurvivalAnalysisDataLoader {
        +target_column: str
        +time_to_event_column: str
    }
    class TimeSeriesDataLoader {
        +temporal_data: list
        +observation_times: list
        +static_data: DataFrame
        +outcome: DataFrame
    }
    class ImageDataLoader {
        +dataset: TorchDataset
        +height: int
        +width: int
    }

    DataLoader <|-- GenericDataLoader
    DataLoader <|-- SurvivalAnalysisDataLoader
    DataLoader <|-- TimeSeriesDataLoader
    DataLoader <|-- ImageDataLoader

2.4 評估指標體系

指標模組說明代表指標
eval_sanity基本健全性檢查資料型別一致性、值域範圍、NaN 比率
eval_statistical統計分佈一致性Jensen-Shannon Divergence (JSD)、Wasserstein Distance、相關矩陣差異
eval_privacy隱私風險量化Nearest Neighbor Distance Ratio (NNDR)、Identifiability Score
eval_detection真假資料可區分度偵測 AUC(用分類器判別真假)
eval_performance下游任務效能Train-on-Synthetic-Test-on-Real (TSTR) 的 ML 模型表現
eval_attacks隱私攻擊模擬Membership Inference Attack (MIA; 成員推斷攻擊)、Attribute Inference

3. 安裝與設定

3.1 基本安裝

 1# 建議使用 uv 建立隔離環境
 2uv venv synthcity-env --python 3.10
 3source synthcity-env/bin/activate
 4
 5# 基本安裝
 6uv pip install synthcity
 7
 8# 完整安裝(含所有可選依賴)
 9uv pip install "synthcity[all]"
10
11# 含測試工具
12uv pip install "synthcity[testing]"

3.2 系統需求

項目最低需求建議
Python3.8+3.10
RAM8 GB16 GB(大型資料集)
GPU非必要CUDA 11.x+(GAN 類加速明顯)
磁碟~2 GB(含 PyTorch)

3.3 驗證安裝

 1from synthcity.plugins import Plugins
 2
 3# 列出所有可用的生成器
 4all_plugins = Plugins().list()
 5print(f"可用生成器數量: {len(all_plugins)}")
 6print(all_plugins)
 7
 8# 列出隱私類生成器
 9privacy_plugins = Plugins(categories=["privacy"]).list()
10print(f"隱私類生成器: {privacy_plugins}")

3.4 已知問題與注意事項

  • synthcity 不處理缺失值 (Missing Values):需先使用 HyperImpute 或其他方法填補
  • 部分生成器(如 GOGGLE)需額外安裝 pip install synthcity[goggle]
  • GReaT(LLM-based)需較大記憶體和 GPU

4. 使用方式與程式碼範例

範例 1:EHR 結構化資料合成與隱私評估

此範例模擬一個完整的 EHR 合成 → 品質評估 → 隱私評估 工作流,適用於需要將真實臨床資料轉為可共享合成版本的情境。

 1"""
 2範例 1:EHR 結構化資料合成與隱私評估
 3場景:合成糖尿病患者臨床資料,評估統計品質與隱私風險
 4"""
 5import pandas as pd
 6from sklearn.datasets import load_diabetes
 7from synthcity.plugins import Plugins
 8from synthcity.plugins.core.dataloader import GenericDataLoader
 9from synthcity.benchmark import Benchmarks
10
11# ── 步驟 1:準備資料 ──────────────────────────────
12X, y = load_diabetes(return_X_y=True, as_frame=True)
13X["target"] = y
14
15# 建立 DataLoader,標記敏感欄位
16# 在真實 EHR 中,sensitive_columns 應包含 age, sex, race 等
17loader = GenericDataLoader(
18    X,
19    target_column="target",
20    sensitive_columns=["sex"],  # 用於公平性評估
21)
22
23print(f"原始資料筆數: {len(X)}")
24print(f"欄位數: {X.shape[1]}")
25print(f"欄位名稱: {list(X.columns)}")
26
27# ── 步驟 2:訓練隱私保護生成器 ─────────────────────
28# 使用 PATEGAN:結合 PATE 框架的差分隱私 GAN
29syn_model = Plugins().get(
30    "pategan",
31    # 差分隱私參數
32    epsilon=1.0,           # 隱私預算 (越小越隱私、效用越低)
33    n_teachers=10,         # PATE 教師模型數量
34    moments_order=100,     # 隱私會計矩次數
35)
36
37syn_model.fit(loader)
38
39# ── 步驟 3:生成合成資料 ──────────────────────────
40synthetic_data = syn_model.generate(count=500)
41syn_df = synthetic_data.dataframe()
42
43print(f"\n合成資料筆數: {len(syn_df)}")
44print(f"\n合成資料統計摘要:")
45print(syn_df.describe().round(3))
46
47# ── 步驟 4:全面評估 ──────────────────────────────
48# 使用 Benchmarks 同時比較多個生成器
49score = Benchmarks.evaluate(
50    [
51        ("pategan_eps1", "pategan", {"epsilon": 1.0}),
52        ("pategan_eps5", "pategan", {"epsilon": 5.0}),
53        ("dpgan_eps1",   "dpgan",   {"epsilon": 1.0}),
54        ("adsgan",       "adsgan",  {}),
55    ],
56    loader,
57    synthetic_size=500,
58    metrics={
59        "sanity":      ["data_mismatch", "common_rows_proportion"],
60        "stats":       ["jensenshannon_dist", "inv_kl_divergence"],
61        "privacy":     ["delta-presence", "k-anonymization"],
62        "performance": ["linear_model"],
63    },
64    repeats=2,
65)
66
67# 印出比較結果
68Benchmarks.print(score)

要點解讀

  • epsilon 是差分隱私的核心參數:epsilon = 1.0 提供較強隱私保護,epsilon = 5.0 隱私較弱但效用較高
  • sensitive_columns 標記後,評估指標會額外計算這些欄位的公平性表現
  • Benchmarks 內建並行化,可同時訓練 + 評估多個生成器

範例 2:存活分析資料合成(臨床試驗端點模擬)

此範例展示如何合成含 Time-to-Event (事件發生時間)Censoring (右設限) 的臨床試驗資料,適用於試驗設計階段的 Protocol Simulation (方案模擬)。

 1"""
 2範例 2:臨床試驗存活端點合成
 3場景:模擬 PFS/OS 存活曲線,用於 protocol 設計的 power analysis
 4"""
 5import pandas as pd
 6import numpy as np
 7from synthcity.plugins import Plugins
 8from synthcity.plugins.core.dataloader import SurvivalAnalysisDataLoader
 9
10# ── 步驟 1:準備存活分析資料 ──────────────────────
11# 模擬臨床試驗資料(真實場景:從 EDC 匯出的 SDTM/ADaM 格式)
12np.random.seed(42)
13n_patients = 200
14
15clinical_data = pd.DataFrame({
16    "age":       np.random.normal(62, 12, n_patients).astype(int),
17    "sex":       np.random.choice([0, 1], n_patients),
18    "stage":     np.random.choice([1, 2, 3, 4], n_patients, p=[0.1, 0.3, 0.4, 0.2]),
19    "treatment": np.random.choice([0, 1], n_patients),      # 0=對照組, 1=實驗組
20    "biomarker": np.random.lognormal(2, 0.8, n_patients),
21    # 存活端點
22    "pfs_weeks": np.random.exponential(24, n_patients),      # PFS (週)
23    "event":     np.random.choice([0, 1], n_patients, p=[0.3, 0.7]),  # 1=事件發生
24})
25
26# 建立存活分析 DataLoader
27surv_loader = SurvivalAnalysisDataLoader(
28    clinical_data,
29    target_column="event",              # 事件指標欄位
30    time_to_event_column="pfs_weeks",   # 事件時間欄位
31)
32
33print(f"原始資料: {len(clinical_data)} 名患者")
34print(f"事件發生率: {clinical_data['event'].mean():.1%}")
35print(f"中位 PFS: {clinical_data['pfs_weeks'].median():.1f} 週")
36
37# ── 步驟 2:訓練存活分析生成器 ─────────────────────
38# SurvivalGAN 專門針對存活資料的分佈特性設計
39surv_model = Plugins().get("survival_gan")
40surv_model.fit(surv_loader)
41
42# ── 步驟 3:生成合成臨床試驗資料 ──────────────────
43syn_surv = surv_model.generate(count=500)
44syn_surv_df = syn_surv.dataframe()
45
46print(f"\n合成資料: {len(syn_surv_df)} 名虛擬患者")
47print(f"合成事件發生率: {syn_surv_df['event'].mean():.1%}")
48print(f"合成中位 PFS: {syn_surv_df['pfs_weeks'].median():.1f} 週")
49
50# ── 步驟 4:比較原始 vs 合成的 Kaplan-Meier 曲線 ──
51# 可搭配 lifelines 繪製 KM 曲線比較
52try:
53    from lifelines import KaplanMeierFitter
54    import matplotlib.pyplot as plt
55
56    fig, ax = plt.subplots(1, 1, figsize=(8, 5))
57
58    kmf_real = KaplanMeierFitter()
59    kmf_real.fit(
60        clinical_data["pfs_weeks"],
61        event_observed=clinical_data["event"],
62        label="Real Data (真實資料)"
63    )
64    kmf_real.plot(ax=ax)
65
66    kmf_syn = KaplanMeierFitter()
67    kmf_syn.fit(
68        syn_surv_df["pfs_weeks"],
69        event_observed=syn_surv_df["event"],
70        label="Synthetic Data (合成資料)"
71    )
72    kmf_syn.plot(ax=ax)
73
74    ax.set_xlabel("Weeks (週)")
75    ax.set_ylabel("Survival Probability (存活機率)")
76    ax.set_title("Real vs Synthetic Kaplan-Meier Curve")
77    plt.tight_layout()
78    plt.savefig("km_comparison.png", dpi=150)
79    print("\nKM 曲線比較圖已儲存: km_comparison.png")
80except ImportError:
81    print("提示:安裝 lifelines 與 matplotlib 可繪製 KM 曲線比較圖")

要點解讀

  • SurvivalAnalysisDataLoader 會自動識別設限資料的特殊分佈結構
  • SurvivalGAN 在訓練時會學習存活函數的形狀,而非僅學習數值分佈
  • 這類合成資料可用於試驗設計階段的 Power Analysis (統計檢力分析) 和 Sample Size Estimation (樣本數估算)

範例 3:差分隱私 epsilon 權衡分析

此範例系統性地比較不同 epsilon 值對資料效用 (Utility) 和隱私保護 (Privacy) 的影響,產出可視覺化的權衡曲線。

 1"""
 2範例 3:差分隱私 epsilon 權衡分析
 3場景:為合規團隊提供 epsilon 選擇的量化依據
 4"""
 5import pandas as pd
 6from sklearn.datasets import load_diabetes
 7from synthcity.plugins import Plugins
 8from synthcity.plugins.core.dataloader import GenericDataLoader
 9from synthcity.metrics.eval_statistical import AlphaPrecision
10from synthcity.metrics.eval_privacy import DeltaPresence
11
12# ── 準備資料 ──────────────────────────────────────
13X, y = load_diabetes(return_X_y=True, as_frame=True)
14X["target"] = y
15loader = GenericDataLoader(X, target_column="target")
16
17# ── 不同 epsilon 值的比較實驗 ─────────────────────
18epsilons = [0.1, 0.5, 1.0, 3.0, 5.0, 10.0]
19results = []
20
21for eps in epsilons:
22    print(f"\n{'='*50}")
23    print(f"訓練 DP-GAN, epsilon = {eps}")
24    print(f"{'='*50}")
25
26    # 訓練 DP-GAN
27    model = Plugins().get("dpgan", epsilon=eps)
28    model.fit(loader)
29
30    # 生成合成資料
31    syn = model.generate(count=len(X))
32
33    # 評估統計品質(Alpha Precision)
34    stat_score = AlphaPrecision().evaluate(
35        loader, syn
36    )
37
38    # 評估隱私風險(Delta Presence)
39    priv_score = DeltaPresence().evaluate(
40        loader, syn
41    )
42
43    result = {
44        "epsilon": eps,
45        "alpha_precision": float(stat_score.get("delta_precision_alpha_OC", 0)),
46        "delta_presence": float(priv_score.get("score", 0)),
47    }
48    results.append(result)
49    print(f"  統計品質 (Alpha Precision): {result['alpha_precision']:.4f}")
50    print(f"  隱私風險 (Delta Presence):  {result['delta_presence']:.4f}")
51
52# ── 結果彙整 ─────────────────────────────────────
53df_results = pd.DataFrame(results)
54print("\n" + "="*60)
55print("Epsilon 權衡分析結果")
56print("="*60)
57print(df_results.to_string(index=False))
58print("\n解讀指引:")
59print("  - Alpha Precision 越高 → 統計品質越好")
60print("  - Delta Presence 越低 → 隱私保護越強")
61print("  - 一般建議: 醫療資料 epsilon = 1.0~3.0 為合理區間")
62print("  - HIPAA Safe Harbor: 無明確 epsilon 標準,但建議 epsilon <= 1.0")
63print("  - GDPR: 歐盟尚無具體 epsilon 門檻,但 Article 89 要求 'appropriate safeguards'")

要點解讀

  • epsilon 越小 → 噪音越大 → 隱私越強但效用越低(經典 Privacy-Utility Trade-off)
  • 醫療資料常見的 epsilon 選擇:0.11.0(高度敏感)、1.05.0(一般敏感)、5.0~10.0(低敏感或已去識別化)
  • 目前 HIPAA、GDPR、台灣 PDPA 均無明確 epsilon 門檻標準,需依資料敏感度和使用情境判斷

5. 在醫療結構化資料合成生態系中的定位

5.1 生態系總覽

synthcity 位於 Domain 1(醫療結構化資料合成)的 Sub-domain C:Medical Tabular SDG (醫療表格合成) 核心位置,同時因其內建的隱私模組而橫跨 Sub-domain B:Privacy-Preserving SDG (隱私保護合成)


graph LR
    subgraph DomainA["A. Patient Simulation
患者模擬"] SYNTHEA["Synthea"] FHIR["Synthea-FHIR"] end subgraph DomainB["B. Privacy-Preserving
隱私保護"] TFP["TF Privacy"] DIFFP["Diffprivlib"] ODP["OpenDP"] SN["SmartNoise"] DPCG["dp_cgans"] end subgraph DomainC["C. Medical Tabular SDG
醫療表格合成"] SC["synthcity ★"] DS["DataSynthesizer"] CG["COR-GAN"] SE["synthEHRella"] end subgraph DomainD["D. Clinical Trial
臨床試驗"] VIC["VICTRE"] TS["tsynth"] TRS["TrialSynth"] end subgraph DomainE["E. Time Series
時間序列"] TA["TemporAI"] end SC -.->|"內建 DP 模組"| DomainB SC -.->|"Survival 生成"| DomainD SC -.->|"TimeGAN 等"| DomainE TA -.->|"同 Lab 開發"| SC style SC fill:#ff9800,stroke:#e65100,color:#fff,font-weight:bold style DomainC fill:#fff3e0,stroke:#f57c00

5.2 與同類工具的比較

維度synthcityDataSynthesizerCOR-GANsynthEHRella
生成器數量20+31數個
隱私機制內建 6 種 DP 生成器DP 模式部分支援
資料型態表格 + 時序 + 存活 + 影像僅表格僅二元表格EHR 專用
評估體系六大類完整指標基本統計無內建部分
可擴充性Plugin 架構較封閉固定中等
醫療專用通用框架,含醫療範例通用醫療導向醫療專用
維護狀態活躍 (2025 更新)較慢低活躍新專案

5.3 定位總結

synthcity 是這個生態系中 最完整的統一框架 (Unified Framework):它不是專門為醫療設計的,但它的 Plugin 架構讓它能整合最多種方法,並且其內建的隱私評估指標對醫療應用至關重要。對於需要 系統性比較多種合成方法 的研究團隊,synthcity 是首選。


6. 與其他工具的整合

6.1 與 Synthea 的互補

1Synthea (患者模擬)              synthcity (表格合成)
2───────────────────        ───────────────────
3產出完整患者生命歷程            接收任何表格資料
4FHIR/CSV 格式輸出    ─────→    GenericDataLoader 匯入
5基於規則的生成                  基於學習的生成
6無隱私保證                      內建差分隱私
7無品質評估                      完整評估體系

整合模式:用 Synthea 產生基礎 EHR 結構,匯出 CSV 後餵入 synthcity 的隱私生成器(如 PATEGAN),為合成資料加上正式的 DP 保證。

6.2 與 DP 工具鏈的整合

工具角色與 synthcity 的關係
OpenDP / SmartNoiseDP 查詢機制 (Query Mechanism)可驗證 synthcity 生成資料的 DP 保證
IBM DiffprivlibDP ML Pipeline可用其 DP 演算法訓練 synthcity 生成的合成資料上的模型
dp_cgans獨立 DP-CGAN 實作synthcity 內建 DP-GAN,功能重疊但 synthcity 提供更完整評估
TF PrivacyDP-SGD 訓練synthcity 的 DP-GAN 內部即使用 DP-SGD 概念

6.3 與下游分析工具整合

 1# synthcity 生成的合成資料可直接匯入標準 ML/統計工具
 2syn_df = syn_model.generate(count=1000).dataframe()
 3
 4# → pandas 分析
 5syn_df.describe()
 6
 7# → scikit-learn 建模
 8from sklearn.model_selection import train_test_split
 9X_train, X_test = train_test_split(syn_df, test_size=0.2)
10
11# → lifelines 存活分析
12from lifelines import CoxPHFitter
13cph = CoxPHFitter()
14cph.fit(syn_df, duration_col="pfs_weeks", event_col="event")
15
16# → 匯出為 CSV(可轉換為 CDISC SDTM/ADaM 格式)
17syn_df.to_csv("synthetic_clinical_data.csv", index=False)

6.4 與 TemporAI 的關係

TemporAI 是同一實驗室(van der Schaar Lab)開發的時間序列醫療資料工具。兩者共享部分底層模型(如 TimeGAN),但 TemporAI 更專注於臨床時間序列的完整管線(預測 + 治療效果估計 + 合成),而 synthcity 的時間序列模組較為通用。


7. 優缺點分析

7.1 優勢

優勢說明
統一 API 設計20+ 生成器一行切換,大幅降低實驗成本;Benchmark 功能可同時比較多種方法
隱私評估完整從 DP 生成到隱私攻擊模擬一條龍,六大類指標不需額外工具
學術根基紮實來自劍橋 van der Schaar Lab,每個生成器都有對應論文,arXiv:2301.07573 詳述框架設計
可擴充性佳Plugin 架構可自行註冊新生成器、新指標,適合研究團隊持續擴充
多資料型態同一框架覆蓋表格 / 時序 / 存活 / 影像,減少工具切換成本
活躍維護截至 2025 年仍有版本更新,社群有 Slack 頻道

7.2 劣勢

劣勢說明
不處理缺失值真實 EHR 普遍存在 Missing Data (缺失資料),需先用 HyperImpute 等外部工具填補
非醫療專用通用框架未內建醫療領域知識(如 ICD 碼階層、LOINC 對應、CDISC 格式)
無 FHIR/OMOP 原生支援需自行處理醫療標準格式的轉換
GPU 依賴GAN 類生成器在大資料集上需 GPU,CPU-only 環境訓練時間長
部分生成器品質參差20+ 生成器中,部分較老舊的方法品質不如新方法,需依賴 Benchmark 篩選
文件散落官方文件與 Tutorial Notebook 分散在多處,初學者需花時間整理

7.3 醫療 / 藥物開發應用的具體建議

適合使用 synthcity 的情境

  1. 需要 系統性比較 多種合成方法的研究團隊
  2. 需要 差分隱私保證 的資料共享場景(跨機構合作、外部資料提供)
  3. 臨床試驗 存活端點模擬 用於 protocol 設計
  4. 資料增強 解決稀有疾病小樣本問題

不適合直接使用的情境

  1. 需要 FHIR/OMOP/CDISC 格式輸出 → 需搭配格式轉換層
  2. 需要 縱向患者生命歷程模擬 → 改用 Synthea
  3. 需要 法規提交等級的驗證文件 → synthcity 無 GxP Validation (GxP 驗證) 支援
  4. 需要 影像合成的最新方法 → synthcity 影像模組非 SOTA,建議用專門工具

7.4 Blue Ocean (藍海) 機會

synthcity 目前缺乏但市場需要的能力:

缺口機會
CDISC SDTM/ADaM 原生支援寫 Plugin 直接產出 submission-ready 格式
IND Submission (IND 申報) 合規報告結合 DP 指標產出 FDA 可接受的隱私報告
台灣 PDPA 合規評估本地化隱私指標(台灣個資法第 19 條要件)
Real-World Data (RWD) Pipeline從 NHIRD / 健保資料庫 → synthcity → 合成 RWD
Multi-site Federated Synthetic Data跨院區聯邦式合成(結合 FATE / Flower)

一行總結:synthcity 是目前最完整的合成表格資料統一框架,20+ 生成器 + 六大類評估指標 + 內建差分隱私,適合需要系統性比較合成方法並量化隱私風險的醫療資料團隊。