SmartNoise SDK 完整教學
Repository: https://github.com/opendp/smartnoise-sdk Stars: 296 | Language: Python | License: MIT Tags:
differential-privacy,privacy,opendp,smartnoisePython: 3.10 - 3.14 | 最後更新: 2026-05
2. 核心架構
2.1 整體架構圖
graph TB
subgraph "SmartNoise SDK"
direction TB
subgraph SQL["smartnoise-sql
差分隱私 SQL 查詢"]
SQL_PARSER["SQL Parser
(ANTLR4 語法剖析)"]
SQL_REWRITER["Private Rewriter
(查詢改寫引擎)"]
SQL_MECH["DP Mechanisms
(Laplace / Gaussian)"]
SQL_ODO["Odometer
(隱私預算追蹤)"]
SQL_PARSER --> SQL_REWRITER
SQL_REWRITER --> SQL_MECH
SQL_MECH --> SQL_ODO
end
subgraph SYNTH["smartnoise-synth
差分隱私合成器"]
SYNTH_BASE["Base Synthesizer
(統一介面)"]
SYNTH_STAT["統計方法"]
SYNTH_DL["深度學習方法"]
SYNTH_BASE --> SYNTH_STAT
SYNTH_BASE --> SYNTH_DL
SYNTH_STAT --> MWEM["MWEM"]
SYNTH_STAT --> MST["MST"]
SYNTH_STAT --> AIM["AIM"]
SYNTH_DL --> DPCTGAN["DP-CTGAN"]
SYNTH_DL --> PATECTGAN["PATE-CTGAN"]
SYNTH_DL --> PATEGAN["PATE-GAN"]
SYNTH_STAT --> QUAIL["QUAIL"]
end
subgraph EVAL["sneval
品質評估"]
EVAL_SINGLE["Single-Table Metrics
(平均值/中位數偏差)"]
EVAL_COMPARE["Comparison Metrics
(MAE / MPE in Count)"]
end
subgraph TRANSFORM["Transform Pipeline
資料前處理"]
T_BIN["Bin (離散化)"]
T_LABEL["Label Encode"]
T_ONEHOT["One-Hot Encode"]
T_CLAMP["Clamp (截斷)"]
T_ANON["Anonymization"]
end
end
subgraph BACKENDS["後端資料來源"]
PD["Pandas DataFrame"]
PG["PostgreSQL"]
SPARK["Apache Spark"]
BQ["BigQuery"]
MYSQL["MySQL"]
SQLITE["SQLite"]
end
subgraph OPENDP["OpenDP Library
(底層 DP 演算法)"]
DP_CORE["核心 DP 機制"]
end
BACKENDS --> SQL
SQL --> OPENDP
SYNTH --> OPENDP
TRANSFORM --> SYNTH
SYNTH --> EVAL
style SQL fill:#e1f5fe,stroke:#0288d1
style SYNTH fill:#f3e5f5,stroke:#7b1fa2
style EVAL fill:#e8f5e9,stroke:#388e3c
style TRANSFORM fill:#fff3e0,stroke:#f57c00
style OPENDP fill:#fce4ec,stroke:#c62828
2.2 合成器演算法比較
SmartNoise 提供 7 種差分隱私合成器,依底層技術分為三大類:
| 演算法 | 類型 | 輸入要求 | 適用場景 | DP 機制 |
|---|---|---|---|---|
| MWEM | 統計 | 離散/類別欄位 | 低維度表格、直方圖查詢 | Exponential + Laplace |
| MST | 統計 | 離散/類別欄位 | 中維度表格、邊際分佈保留 | Gaussian |
| AIM | 統計 | 離散/類別欄位 | 自適應邊際選擇、高維度 | Gaussian |
| QUAIL | 混合 | 連續 + 類別 | 機器學習下游任務 | 教師模型聚合 |
| DP-CTGAN | 深度學習 | 連續 + 類別 | 混合型表格、複雜分佈 | DP-SGD |
| PATE-CTGAN | 深度學習 | 連續 + 類別 | 混合型表格、教師-學生框架 | PATE |
| PATE-GAN | 深度學習 | 連續 + 類別 | 類似 PATE-CTGAN 但架構不同 | PATE |
2.3 隱私預算流程
sequenceDiagram
participant User as 分析師
participant Reader as Private Reader
participant Engine as DB Engine
participant Odometer as Odometer
(隱私里程表)
participant DP as DP Mechanism
User->>Reader: execute(SQL query)
Reader->>Reader: 解析 SQL, 識別聚合函數
Reader->>Engine: 執行精確查詢
Engine-->>Reader: 原始結果
Reader->>DP: 對每個聚合欄位加噪音
DP->>Odometer: 記錄 (epsilon, delta) 消耗
Odometer-->>Reader: 累計隱私花費
Reader-->>User: 加噪結果 + 花費報告
Note over Odometer: spent = (total_eps, total_delta)
使用高階組合定理追蹤
3. 安裝與設定
3.1 基本安裝
1# 建議使用 uv 建立隔離環境
2uv venv smartnoise-env
3source smartnoise-env/bin/activate
4
5# 安裝 SQL 套件(僅查詢功能)
6uv pip install smartnoise-sql
7
8# 安裝合成器套件(含 PyTorch 相依)
9uv pip install smartnoise-synth
10
11# 同時安裝兩者
12uv pip install smartnoise-sql smartnoise-synth
13
14# 安裝評估套件(可選)
15uv pip install smartnoise-eval
3.2 安裝特定合成器後端
1# 安裝 PyTorch 系列合成器(DP-CTGAN, PATE-CTGAN, PATE-GAN)
2uv pip install "smartnoise-synth[pytorch]"
3
4# 安裝 MST 所需的 OpenDP 支援
5uv pip install "smartnoise-synth[mst]"
3.3 驗證安裝
1import snsql
2from snsql import Privacy
3print(f"smartnoise-sql version: {snsql.__version__}")
4
5import snsynth
6print(f"smartnoise-synth version: {snsynth.__version__}")
7
8# 檢查可用合成器
9from snsynth import MWEMSynthesizer
10print("MWEM available: OK")
3.4 Metadata YAML 格式
SmartNoise SQL 查詢需要一個 YAML metadata 檔案來描述資料表的結構與隱私屬性。以醫療資料為例:
1# metadata.yaml - 模擬患者資料表描述
2Hospital:
3 Patients:
4 Patients:
5 row_privacy: True # 每列代表一個獨立個體
6 rows: 5000 # 近似列數(可略大於實際)
7 age:
8 type: int
9 lower: 0 # 數值下界
10 upper: 120 # 數值上界
11 sex:
12 type: string # 類別型(不需 upper/lower)
13 diagnosis_code:
14 type: string
15 lab_value:
16 type: float
17 lower: 0.0
18 upper: 1000.0
19 treatment_cost:
20 type: int
21 lower: 0
22 upper: 5000000
重要參數說明:
row_privacy: True– 表示每列是一個獨立個體,這是 DP 的基本假設rows– 原始資料的近似列數,用於校準噪音量級;可安全地稍微高估lower/upper– 數值型欄位的界限 (Clamping Bounds),超出範圍的值會被截斷
4. 使用方式與程式碼範例
4.1 範例一:差分隱私 SQL 查詢(模擬臨床資料分析)
此範例展示如何對患者資料執行 DP SQL 查詢,模擬一個藥物開發團隊需要統計患者人口分佈的場景。
1"""
2範例 1:差分隱私 SQL 查詢
3場景:在不暴露個別患者資訊的情況下,統計臨床試驗受試者的年齡與性別分佈
4"""
5import pandas as pd
6import snsql
7from snsql import Privacy
8
9# === 步驟 1:準備資料 ===
10# 模擬臨床試驗患者資料
11data = pd.DataFrame({
12 'patient_id': range(1, 501),
13 'age': [45, 52, 38, 61, 29, 55, 43, 67, 34, 58] * 50,
14 'sex': ['M', 'F', 'F', 'M', 'F', 'M', 'M', 'F', 'M', 'F'] * 50,
15 'treatment_arm': ['Drug_A', 'Drug_A', 'Placebo', 'Drug_A', 'Placebo'] * 100,
16 'response': [1, 0, 0, 1, 0, 1, 1, 0, 1, 0] * 50,
17})
18
19# === 步驟 2:定義 Metadata(也可用 YAML 檔案) ===
20metadata = {
21 'ClinicalTrial': {
22 'Patients': {
23 'Patients': {
24 'row_privacy': True,
25 'rows': 500,
26 'age': {'type': 'int', 'lower': 18, 'upper': 85},
27 'sex': {'type': 'string'},
28 'treatment_arm': {'type': 'string'},
29 'response': {'type': 'int', 'lower': 0, 'upper': 1},
30 }
31 }
32 }
33}
34
35# === 步驟 3:建立隱私保護連線 ===
36# epsilon=1.0 是常見的中等隱私保護水準
37# delta=1e-5 (遠小於 1/n) 是標準做法
38privacy = Privacy(epsilon=1.0, delta=1e-5)
39reader = snsql.from_df(data, privacy=privacy, metadata=metadata)
40
41# === 步驟 4:執行 DP SQL 查詢 ===
42
43# 查詢 1:各治療組的平均年齡
44result1 = reader.execute(
45 'SELECT treatment_arm, AVG(age) AS avg_age, COUNT(*) AS n '
46 'FROM ClinicalTrial.Patients GROUP BY treatment_arm'
47)
48print("各治療組統計(差分隱私):")
49for row in result1:
50 print(f" {row}")
51
52# 查詢 2:各性別的反應率
53result2 = reader.execute(
54 'SELECT sex, SUM(response) AS responders, COUNT(*) AS total '
55 'FROM ClinicalTrial.Patients GROUP BY sex'
56)
57print("\n各性別反應統計(差分隱私):")
58for row in result2:
59 print(f" {row}")
60
61# === 步驟 5:檢查隱私預算消耗 ===
62eps_spent, delta_spent = reader.odometer.spent
63print(f"\n累計隱私花費:epsilon={eps_spent:.4f}, delta={delta_spent:.2e}")
64
65# 預估下一次查詢的隱私成本(不實際執行)
66cost = reader.get_privacy_cost(
67 'SELECT AVG(age), AVG(response) FROM ClinicalTrial.Patients'
68)
69print(f"預估下次查詢成本:epsilon={cost[0]:.4f}, delta={cost[1]:.2e}")
關鍵概念:
- Epsilon (epsilon) – 隱私損失參數。越小 = 越強的隱私保護 = 更多噪音 = 較低的查詢精度
- Delta (delta) – 隱私機制失效的機率上界。通常設為遠小於
1/n - Odometer (里程表) – 追蹤整個 session 的累計隱私花費,使用高階組合定理 (Advanced Composition Theorem) 計算,比簡單加總更緊湊
4.2 範例二:使用 MST 合成器產生合成 EHR 資料
MST (Maximum Spanning Tree; 最大生成樹) 合成器是 SmartNoise 中最推薦的統計方法合成器,適合醫療表格資料。
1"""
2範例 2:MST 合成器生成合成 EHR 資料
3場景:從真實 EHR 資料產生可公開分享的合成版本,用於跨機構研究合作
4"""
5import pandas as pd
6import numpy as np
7from snsynth import Synthesizer
8
9# === 步驟 1:準備模擬 EHR 資料 ===
10np.random.seed(42)
11n_patients = 2000
12
13ehr_data = pd.DataFrame({
14 'age_group': np.random.choice(
15 ['18-30', '31-45', '46-60', '61-75', '76+'],
16 n_patients, p=[0.15, 0.25, 0.30, 0.20, 0.10]
17 ),
18 'sex': np.random.choice(['M', 'F'], n_patients, p=[0.48, 0.52]),
19 'diagnosis': np.random.choice(
20 ['Hypertension', 'Diabetes_T2', 'COPD', 'CKD', 'Healthy'],
21 n_patients, p=[0.25, 0.20, 0.15, 0.10, 0.30]
22 ),
23 'medication': np.random.choice(
24 ['ACE_inhibitor', 'Metformin', 'Bronchodilator', 'None'],
25 n_patients, p=[0.25, 0.20, 0.15, 0.40]
26 ),
27 'smoking_status': np.random.choice(
28 ['Never', 'Former', 'Current'],
29 n_patients, p=[0.50, 0.30, 0.20]
30 ),
31 'readmission_30d': np.random.choice(
32 ['Yes', 'No'], n_patients, p=[0.12, 0.88]
33 ),
34})
35
36print(f"原始資料形狀:{ehr_data.shape}")
37print(f"原始診斷分佈:\n{ehr_data['diagnosis'].value_counts(normalize=True)}\n")
38
39# === 步驟 2:使用 MST 合成器 ===
40# MST 要求所有欄位為類別型(已滿足)
41# epsilon=1.0 提供合理的隱私-效用平衡
42synth = Synthesizer.create(
43 "mst",
44 epsilon=1.0,
45 verbose=True
46)
47
48# 指定所有欄位為類別型
49categorical_columns = ehr_data.columns.tolist()
50
51# 訓練合成器
52synth.fit(
53 ehr_data,
54 categorical_columns=categorical_columns
55)
56
57# === 步驟 3:生成合成資料 ===
58synthetic_ehr = synth.sample(2000)
59synthetic_df = pd.DataFrame(synthetic_ehr, columns=ehr_data.columns)
60
61print(f"合成資料形狀:{synthetic_df.shape}")
62print(f"合成診斷分佈:\n{synthetic_df['diagnosis'].value_counts(normalize=True)}\n")
63
64# === 步驟 4:簡單品質檢查 ===
65print("=== 邊際分佈比較 ===")
66for col in ehr_data.columns:
67 orig_dist = ehr_data[col].value_counts(normalize=True).sort_index()
68 synth_dist = synthetic_df[col].value_counts(normalize=True).sort_index()
69 merged = pd.DataFrame({
70 'Original': orig_dist,
71 'Synthetic': synth_dist
72 }).fillna(0)
73 max_diff = (merged['Original'] - merged['Synthetic']).abs().max()
74 print(f" {col}: max 邊際偏差 = {max_diff:.4f}")
75
76# === 步驟 5:匯出合成資料(可安全分享) ===
77synthetic_df.to_csv('synthetic_ehr_dp.csv', index=False)
78print("\n合成資料已儲存至 synthetic_ehr_dp.csv(可安全分享)")
MST 演算法核心原理:
- 使用 DP 測量所有二維邊際分佈 (2-way Marginals)
- 建構互資訊 (Mutual Information) 的最大生成樹,保留最重要的欄位關聯
- 透過圖模型 (Graphical Model) 還原完整聯合分佈
- 從聯合分佈中抽樣生成合成資料
4.3 範例三:PATE-CTGAN 處理混合型臨床資料
PATE-CTGAN 適合同時包含連續型與類別型欄位的資料,利用 PATE (Private Aggregation of Teacher Ensembles; 教師集成私密聚合) 框架提供 DP 保證。
1"""
2範例 3:PATE-CTGAN 合成混合型臨床試驗資料
3場景:臨床試驗資料含連續型實驗室數值與類別型診斷,需要保留複雜的
4 非線性關聯(如年齡 vs. 肌酸酐 vs. CKD 分期的交互作用)
5"""
6import pandas as pd
7import numpy as np
8from snsynth.pytorch.nn import PATECTGAN
9from snsynth.pytorch import PytorchDPSynthesizer
10
11# === 步驟 1:模擬含連續值的臨床資料 ===
12np.random.seed(42)
13n = 1000
14
15clinical_data = pd.DataFrame({
16 'age': np.random.normal(55, 15, n).clip(18, 90).astype(int),
17 'bmi': np.random.normal(26, 5, n).clip(15, 50).round(1),
18 'creatinine': np.random.lognormal(0.2, 0.4, n).clip(0.3, 8.0).round(2),
19 'hba1c': np.random.normal(6.5, 1.5, n).clip(4.0, 14.0).round(1),
20 'sex': np.random.choice(['M', 'F'], n),
21 'ckd_stage': np.random.choice(
22 ['Stage_1', 'Stage_2', 'Stage_3a', 'Stage_3b', 'Stage_4', 'Stage_5'],
23 n, p=[0.30, 0.25, 0.20, 0.12, 0.08, 0.05]
24 ),
25 'diabetes': np.random.choice(['Yes', 'No'], n, p=[0.35, 0.65]),
26})
27
28print(f"原始資料:{clinical_data.shape}")
29print(clinical_data.describe())
30
31# === 步驟 2:設定 PATE-CTGAN ===
32# 標示類別型欄位
33categorical_columns = ['sex', 'ckd_stage', 'diabetes']
34
35# 建立合成器
36# epsilon=3.0:適中的隱私保護,適合不含直接識別子的臨床資料
37synth = PytorchDPSynthesizer(
38 epsilon=3.0,
39 gan=PATECTGAN(
40 regularization='dragan', # DRAGAN 正則化穩定訓練
41 batch_size=64,
42 epochs=100,
43 ),
44 preprocessor=None, # 使用內建前處理
45)
46
47# === 步驟 3:訓練與生成 ===
48synth.fit(
49 clinical_data,
50 categorical_columns=categorical_columns,
51)
52
53synthetic_clinical = synth.sample(1000)
54print(f"\n合成資料:{synthetic_clinical.shape}")
55print(synthetic_clinical.describe())
56
57# === 步驟 4:交叉驗證 -- 連續欄位分佈比較 ===
58print("\n=== 連續欄位 KS 統計量 ===")
59from scipy import stats
60
61for col in ['age', 'bmi', 'creatinine', 'hba1c']:
62 ks_stat, p_value = stats.ks_2samp(
63 clinical_data[col].astype(float),
64 synthetic_clinical[col].astype(float)
65 )
66 quality = "Good" if ks_stat < 0.1 else "Fair" if ks_stat < 0.2 else "Poor"
67 print(f" {col}: KS={ks_stat:.4f}, p={p_value:.4f} ({quality})")
PATE-CTGAN vs. DP-CTGAN 的差異:
| 面向 | DP-CTGAN | PATE-CTGAN |
|---|---|---|
| DP 機制 | DP-SGD (梯度加噪) | PATE (教師集成投票) |
| 隱私核算 | Moments Accountant | Data-Dependent Privacy Analysis |
| 訓練穩定性 | 中等(梯度裁剪影響收斂) | 較好(教師模型獨立訓練) |
| 適用資料量 | 中大型 (>5000 rows) | 中小型 (>500 rows) |
| 推薦場景 | 大型 EHR 資料庫 | 小型臨床試驗資料集 |
5. 在醫療結構化資料合成生態系中的定位
5.1 Bio-SDG Domain 1 定位圖
SmartNoise SDK 屬於 Sub-domain B: Privacy-Preserving SDG (隱私保護合成資料生成),與 IBM diffprivlib、OpenDP Library、dp_cgans 等工具同屬差分隱私層。
graph LR
subgraph "Domain 1: 醫療結構化資料合成"
direction TB
subgraph A["A. 患者模擬"]
Synthea["Synthea
完整病歷模擬"]
end
subgraph B["B. 隱私保護 SDG"]
OpenDP["OpenDP Library
底層 DP 演算法"]
SN["SmartNoise SDK
SQL + 合成器"]
TFP["TF Privacy
TF 深度學習 DP"]
Diffprivlib["IBM diffprivlib
scikit-learn DP"]
DPCGANS["dp_cgans
DP 條件 GAN"]
end
subgraph C["C. 醫療表格 SDG"]
Synthcity["synthcity
26+ 合成器框架"]
DataSynth["DataSynthesizer"]
CORGAN["COR-GAN"]
SynthEHRella["synthEHRella"]
end
subgraph D["D. 臨床試驗資料"]
VICTRE["VICTRE"]
Tsynth["tsynth"]
TrialSynth["TrialSynth"]
end
OpenDP -->|"核心依賴"| SN
SN -.->|"合成器對比"| Synthcity
SN -.->|"DP 互補"| Diffprivlib
Synthea -.->|"模擬資料 → DP 查詢"| SN
end
style SN fill:#ff9800,stroke:#e65100,color:#000,stroke-width:3px
style OpenDP fill:#fff3e0,stroke:#e65100
5.2 SmartNoise 的獨特價值
與其他 Bio-SDG 工具相比,SmartNoise 的獨特定位在於:
- SQL 介面:唯一提供 SQL 層差分隱私的開源工具。資料分析師不需學習新 API,用 SQL 就能進行隱私保護查詢
- 雙模式運作:同時支援「隱私查詢」(不生成合成資料)和「合成資料生成」兩種模式
- 隱私預算管理:內建 Odometer 機制,使用高階組合定理自動追蹤累計隱私花費
- 多資料庫後端:支援 PostgreSQL、Spark、BigQuery 等生產級資料庫,不僅限於記憶體內操作
5.3 醫療場景適用性
| 場景 | 適合的 SmartNoise 功能 | 替代工具 |
|---|---|---|
| 跨院 EHR 統計查詢 | smartnoise-sql | 無直接替代 |
| 去識別化研究資料集 | smartnoise-synth (MST) | synthcity, DataSynthesizer |
| 臨床試驗模擬資料 | smartnoise-synth (PATE-CTGAN) | dp_cgans, synthcity |
| 聯合學習中間聚合 | smartnoise-sql (Synopsis) | TF Privacy |
| 監管報告匿名統計 | smartnoise-sql | IBM diffprivlib |
5.4 監管合規應用
- HIPAA Safe Harbor (安全港) – SmartNoise 的 DP 保證在數學上比 Safe Harbor 的 18 項去識別化規則更嚴格
- HIPAA Expert Determination (專家判定) – DP 的 epsilon 參數可作為專家判定中的量化風險評估指標
- GDPR Article 89 (科研豁免) – DP 合成資料可主張不構成個資,降低 DPIA 負擔
- 台灣個資法第 19 條 – DP 合成資料可能有助於主張「去識別化處理後之統計資料」
6. 與其他工具的整合
6.1 與 OpenDP Library 的關係
SmartNoise SDK 是 OpenDP Library 的高階封裝。OpenDP 提供原子化的 DP 演算法 (Measurements, Transformations),SmartNoise 將其包裝成可用 SQL 操作的介面。
1# OpenDP 底層(原子操作,彈性高但複雜)
2import opendp.prelude as dp
3dp.enable_features("contrib", "honest-but-curious")
4
5space = dp.atom_domain(T=int), dp.absolute_distance(T=int)
6base_lap = space >> dp.then_laplace(scale=1.0)
7
8# SmartNoise 高階(SQL 操作,易用但彈性較低)
9import snsql
10reader = snsql.from_df(df, privacy=Privacy(epsilon=1.0), metadata=meta)
11result = reader.execute("SELECT AVG(age) FROM table") # 內部自動呼叫 OpenDP
6.2 與 synthcity 互補
synthcity 提供 26+ 種合成器但多數不具 DP 保證,SmartNoise 合成器數量較少但全部有 DP。建議的混合工作流:
1# 步驟 1:用 SmartNoise MST 生成 DP 合成資料
2from snsynth import Synthesizer
3synth = Synthesizer.create("mst", epsilon=1.0)
4synth.fit(sensitive_data, categorical_columns=cat_cols)
5dp_synthetic = synth.sample(len(sensitive_data))
6
7# 步驟 2:用 synthcity 評估合成資料品質
8from synthcity.metrics import Metrics
9score = Metrics.evaluate(
10 X_gt=sensitive_data, # 僅在安全環境中比較
11 X_syn=dp_synthetic,
12 metrics={"stats": ["jensenshannon_dist", "ks_test"]},
13)
14print(score)
6.3 與 Synthea 整合(模擬 + DP)
Synthea 產生逼真但非隱私保護的合成病歷。將 Synthea 輸出通過 SmartNoise 可為下游應用增加形式化隱私保證:
1# 情境:Synthea 產生的模擬資料仍可能過度擬合真實人口分佈
2# 加上 DP 層可消除這類風險
3
4# 步驟 1:讀取 Synthea 輸出的 CSV
5synthea_patients = pd.read_csv("synthea_output/patients.csv")
6
7# 步驟 2:透過 DP SQL 查詢統計數據
8privacy = Privacy(epsilon=0.5, delta=1e-6)
9reader = snsql.from_df(synthea_patients, privacy=privacy, metadata=synthea_meta)
10stats = reader.execute("SELECT RACE, AVG(age) FROM Patients GROUP BY RACE")
6.4 與 CDISC SDTM/ADaM 的銜接(藍海機會)
目前 SmartNoise 尚未原生支援 CDISC (Clinical Data Interchange Standards Consortium) 標準格式,但可以透過以下方式銜接:
- SDTM Domain 對應 – 將 SDTM DM (Demographics)、VS (Vital Signs)、LB (Laboratory) domain 的 metadata 轉為 SmartNoise YAML 格式
- ADaM Analysis Dataset – 對 ADSL (Subject Level)、ADAE (Adverse Events) 等分析資料集執行 DP 查詢
- IND Submission – 用 DP 合成資料進行 protocol feasibility 評估,避免在 pre-IND 階段洩漏真實臨床數據
7. 優缺點分析
7.1 優點
| 面向 | 說明 |
|---|---|
| 形式化隱私保證 | 基於差分隱私的數學證明,不依賴經驗式去識別化 |
| SQL 介面 | 分析師可直接使用 SQL,學習曲線極低 |
| 多後端支援 | PostgreSQL、Spark、BigQuery 等生產級資料庫均可直接使用 |
| 隱私預算追蹤 | Odometer 使用高階組合定理,比 naive 加總更精確 |
| 豐富的合成器選項 | 7 種演算法涵蓋統計與深度學習方法 |
| OpenDP 生態系 | 與哈佛 OpenDP 計畫深度整合,學術基礎扎實 |
| MIT 授權 | 商用無限制 |
| Private Synopsis | 可產生預計算 DP 聚合表,供 Excel / BI 工具直接使用 |
7.2 缺點
| 面向 | 說明 |
|---|---|
| 合成器數量 | 僅 7 種,遠少於 synthcity 的 26+ 種 |
| MST/MWEM 限制 | 統計方法要求欄位為類別型,連續值需預先離散化 |
| 高維度詛咒 | 當類別組合數過多時(>10 欄位 x 多值),合成品質下降 |
| SQL 子集有限 | 不支援 subquery、window function、per-field epsilon 設定 |
| max_contrib 限制 | 目前建議 max_contrib=1,對重複就診資料需額外處理 |
| 缺乏時序支援 | 不支援時間序列資料(需搭配 TemporAI 等工具) |
| 文件不夠直覺 | 官方文件以學術風格為主,缺少端到端的醫療場景教學 |
| 無 CDISC 整合 | 不支援 SDTM/ADaM 標準格式 metadata |
7.3 Epsilon 選擇指引(醫療場景)
| Epsilon 範圍 | 隱私強度 | 適用場景 | 效用影響 |
|---|---|---|---|
| 0.01 - 0.1 | 極強 | 高敏感度基因資料、罕見疾病 | 噪音極大,僅適合粗略統計 |
| 0.1 - 1.0 | 強 | 一般 EHR 查詢、跨院統計 | 聚合統計可用,小群體分析受限 |
| 1.0 - 3.0 | 中等 | 合成資料生成、研究用資料集 | 大多數下游 ML 任務可接受 |
| 3.0 - 10.0 | 弱 | 低敏感度去識別化資料、內部分析 | 合成品質佳但隱私保護有限 |
7.4 何時該選擇 SmartNoise
適合的情境:
- 需要對既有資料庫執行隱私保護的統計查詢
- 需要產生可公開分享的低維度/中維度合成表格資料
- 組織已有 SQL 基礎設施,希望低成本導入 DP
- 需要與監管機構溝通時有數學化的隱私指標
不適合的情境:
- 高維度連續型資料(考慮 synthcity + TVAE/CTGAN)
- 時間序列 EHR 資料(考慮 TemporAI)
- 影像或非結構化醫療資料(超出 SmartNoise 範圍)
- 需要 >20 個欄位的複雜合成(考慮 synthcity 或 COR-GAN)
總結:SmartNoise SDK 是 OpenDP 生態系中面向應用的差分隱私工具套件,透過 SQL 介面與 7 種合成器,讓醫療資料科學家能以最低學習成本實現形式化的隱私保護查詢與合成資料生成。在 Bio-SDG 生態系中,它是唯一同時提供「DP SQL 查詢」與「DP 合成資料」雙軌功能的開源方案。
Comments