scGen 完整教學
Repository: https://github.com/theislab/scgen Stars: 348 | Forks: 70 | Language: Python | License: GPL-3.0 Tags:
single-cell,perturbation,VAE,transcriptomics,deep-learning,generative-model,bioinformatics,scrna-seq,single-cell-genomics文件: https://scgen.readthedocs.io 論文: Lotfollahi et al., “scGen predicts single-cell perturbation responses.” Nature Methods, 2019.
2. 核心架構
2.1 整體架構圖
flowchart TB
subgraph INPUT["輸入層 Input Layer"]
A["scRNA-seq AnnData
(control + stimulated
× multiple cell types)"]
end
subgraph PREPROCESS["前處理 Preprocessing"]
B1["Normalize (正規化)"]
B2["Log1p 轉換"]
B3["HVG Selection
(高變異基因篩選
~7000 genes)"]
B4["setup_anndata()
註冊 batch_key +
labels_key"]
end
subgraph VAE["SCGENVAE 模型"]
direction TB
subgraph ENCODER["Encoder (編碼器)"]
E1["FCLayers
(n_layers × n_hidden)"]
E2["LeakyReLU + BatchNorm
+ Dropout"]
E3["mu (均值) / var (變異數)"]
E4["Reparameterization
(重參數化取樣)"]
end
Z["Latent Space z
(n_latent = 100)"]
subgraph DECODER["Decoder (解碼器)"]
D1["FCLayers
(n_layers × n_hidden)"]
D2["Linear Output
(n_latent → n_genes)"]
end
LOSS["Loss = MSE + KL_weight × KL_divergence"]
end
subgraph PREDICT["預測 / 推論 Prediction"]
P1["avg(z_stim) - avg(z_ctrl)
= delta vector"]
P2["z_target_ctrl + delta"]
P3["Decoder → predicted
gene expression"]
end
subgraph OUTPUT["輸出 Output"]
O1["Predicted AnnData
(擾動預測結果)"]
O2["Corrected AnnData
(批次校正結果)"]
O3["R² Plots
(驗證圖表)"]
end
A --> B1 --> B2 --> B3 --> B4
B4 --> ENCODER
ENCODER --> Z
Z --> DECODER
DECODER --> LOSS
LOSS -->|"訓練完成"| PREDICT
Z --> P1
P1 --> P2
P2 --> P3
P3 --> O1
Z -->|"batch_removal()"| O2
O1 --> O3
2.2 模組結構
scGen 的程式碼結構極為精簡,僅包含 5 個核心檔案:
| 檔案 | 類別 | 職責 |
|---|---|---|
_scgen.py | SCGEN | 主模型類別,繼承 scvi-tools 的 BaseModelClass;提供 predict()、batch_removal()、繪圖方法 |
_scgenvae.py | SCGENVAE | VAE 模組,繼承 BaseModuleClass;定義 encoder/decoder/loss |
_base_components.py | DecoderSCGEN | 自訂 decoder,使用 FCLayers + Linear 輸出 |
_utils.py | extractor, balancer | 輔助函式:細胞類型提取與族群平衡 |
__init__.py | — | 套件入口,匯出 SCGEN, SCGENVAE |
2.3 擾動預測核心流程
sequenceDiagram
participant User as 使用者
participant Model as SCGEN Model
participant Enc as Encoder
participant Dec as Decoder
User->>Model: setup_anndata(adata, batch_key, labels_key)
User->>Model: SCGEN(adata).train()
Note over Model: 在 control + stimulated 數據上訓練 VAE
User->>Model: predict(ctrl_key, stim_key, celltype_to_predict)
Model->>Model: balancer() 平衡各細胞類型數量
Model->>Enc: encode(ctrl_cells) → latent_ctrl
Model->>Enc: encode(stim_cells) → latent_stim
Model->>Model: delta = avg(latent_stim) - avg(latent_ctrl)
Model->>Enc: encode(target_ctrl_cells) → latent_target
Model->>Model: predicted_latent = latent_target + delta
Model->>Dec: decode(predicted_latent) → predicted_expression
Model-->>User: (predicted_adata, delta)
2.4 損失函數 (Loss Function)
scGen 使用加權的 VAE 損失函數:
1Loss = Reconstruction_Loss (MSE) + kl_weight × KL_Divergence
- Reconstruction Loss: Mean Squared Error (MSE; 均方誤差),衡量重建品質
- KL Divergence: 正則化項,迫使潛在空間趨近標準常態分佈 (standard normal distribution)
- kl_weight: 預設極小值
0.00005,使模型更偏向重建精度而非潛在空間正則化
3. 安裝與設定
3.1 基本安裝
1# 建議使用 uv 建立隔離環境
2uv venv scgen-env --python 3.10
3source scgen-env/bin/activate
4
5# 安裝 scgen(會自動安裝 scvi-tools, scanpy, pytorch 等依賴)
6uv pip install scgen
7
8# 或安裝開發版
9uv pip install git+https://github.com/theislab/scgen.git
3.2 完整環境(含教學依賴)
1# 核心 + 教學所需額外套件
2uv pip install scgen scanpy leidenalg python-igraph scikit-misc
3
4# 驗證安裝
5python -c "import scgen; print(f'scGen v{scgen.__version__}')"
6# 預期輸出: scGen v2.1.1
3.3 GPU 加速
scGen 透過 scvi-tools 自動偵測 GPU。如需明確指定:
1import scvi
2scvi.settings.dl_pin_memory_gpu_training = True
3
4# 或在訓練時指定
5model.train(max_epochs=100, accelerator="gpu", devices=1)
3.4 依賴版本相容性
| 依賴 | 最低版本 | 備註 |
|---|---|---|
| Python | 3.8+ | 建議 3.10 |
| scvi-tools | 0.20.0+ | 核心框架 |
| scanpy | 1.6+ | 數據前處理 |
| anndata | 0.7.5+ | 數據格式 |
| PyTorch | (由 scvi-tools 管理) | 自動安裝 |
| matplotlib | != 3.7.0 | 避開已知 bug |
4. 使用方式與程式碼範例
4.1 範例一:擾動預測 (Perturbation Prediction)
這是 scGen 最核心的使用場景——預測某個細胞類型在受到擾動(如藥物處理、基因敲除)後的基因表達變化。
1import scanpy as sc
2import scgen
3import numpy as np
4
5# ============================================================
6# 步驟 1:載入與前處理數據
7# ============================================================
8# 使用 Kang et al. (2018) IFN-beta 刺激 PBMC 數據集
9# 此數據含 control / stimulated 兩個條件 × 多種免疫細胞類型
10train = sc.read(
11 "./data/train.h5ad",
12 backup_url="https://drive.google.com/uc?id=1r87vhoLLq6PG2d3rpXQYOdNU7GpDnYlU"
13)
14
15# 標準 scanpy 前處理流程
16sc.pp.normalize_total(train, target_sum=1e4)
17sc.pp.log1p(train)
18sc.pp.highly_variable_genes(train, n_top_genes=7000)
19train = train[:, train.var.highly_variable].copy()
20
21# ============================================================
22# 步驟 2:設定 AnnData 並建立模型
23# ============================================================
24# batch_key: 條件欄位(control vs stimulated)
25# labels_key: 細胞類型欄位
26scgen.SCGEN.setup_anndata(
27 train,
28 batch_key="condition",
29 labels_key="cell_type"
30)
31
32model = scgen.SCGEN(
33 train,
34 n_hidden=800, # 隱藏層節點數
35 n_latent=100, # 潛在空間維度
36 n_layers=2, # encoder/decoder 層數
37 dropout_rate=0.2 # dropout 率
38)
39
40# ============================================================
41# 步驟 3:訓練模型
42# ============================================================
43model.train(
44 max_epochs=100,
45 batch_size=32,
46 early_stopping=True,
47 plan_kwargs={"lr": 1e-3}
48)
49
50# ============================================================
51# 步驟 4:預測 CD4T 細胞的擾動響應
52# ============================================================
53# 假設我們只有 CD4T 的 control 數據,想預測它的 stimulated 狀態
54pred, delta = model.predict(
55 ctrl_key="control",
56 stim_key="stimulated",
57 celltype_to_predict="CD4T"
58)
59
60# pred 是一個 AnnData,包含預測的基因表達矩陣
61print(f"預測結果: {pred.shape[0]} cells × {pred.shape[1]} genes")
62print(f"Delta vector shape: {delta.shape}")
63
64# ============================================================
65# 步驟 5:驗證預測品質
66# ============================================================
67# 取得真實的刺激組數據
68eval_adata = train[train.obs["cell_type"] == "CD4T"].copy()
69# 加入預測數據
70pred.obs["condition"] = "pred"
71cd4t_all = eval_adata.concatenate(pred)
72
73# 繪製 R² 迴歸圖(均值匹配)
74r2_value = model.reg_mean_plot(
75 cd4t_all,
76 axis_keys={"x": "control", "y": "pred", "y1": "stimulated"},
77 gene_list=["ISG15", "CD3D", "IFIT1", "STAT1"], # 標記感興趣的基因
78 labels={"x": "Control mean", "y": "Predicted mean"},
79 path_to_save="./reg_mean_cd4t.pdf",
80 show=True
81)
82print(f"All genes R²: {r2_value:.4f}")
4.2 範例二:批次效應移除 (Batch Effect Removal)
scGen 也可以用來移除來自不同實驗批次的技術偏差,同時保留生物學差異。
1import scanpy as sc
2import scgen
3
4# ============================================================
5# 步驟 1:載入含批次效應的數據
6# ============================================================
7adata = sc.read("./data/multi_batch_pbmc.h5ad")
8sc.pp.normalize_total(adata, target_sum=1e4)
9sc.pp.log1p(adata)
10
11# 視覺化批次效應(校正前)
12sc.pp.neighbors(adata)
13sc.tl.umap(adata)
14sc.pl.umap(adata, color=["batch", "cell_type"], save="_before_correction.pdf")
15
16# ============================================================
17# 步驟 2:訓練 scGen 模型
18# ============================================================
19# 注意:batch_removal 需要 batch_key(批次標籤)和 labels_key(細胞類型標籤)
20scgen.SCGEN.setup_anndata(
21 adata,
22 batch_key="batch", # 批次欄位
23 labels_key="cell_type" # 細胞類型欄位
24)
25
26model = scgen.SCGEN(adata, n_latent=100, n_hidden=800)
27model.train(max_epochs=100, batch_size=32)
28
29# ============================================================
30# 步驟 3:執行批次校正
31# ============================================================
32corrected_adata = model.batch_removal()
33
34# corrected_adata.X: 校正後的基因表達矩陣
35# corrected_adata.obsm["latent"]: 校正後的潛在空間表示
36# corrected_adata.obsm["corrected_latent"]: 對校正後數據重新編碼的潛在表示
37
38# ============================================================
39# 步驟 4:視覺化校正結果
40# ============================================================
41sc.pp.neighbors(corrected_adata, use_rep="corrected_latent")
42sc.tl.umap(corrected_adata)
43sc.pl.umap(corrected_adata, color=["batch", "cell_type"], save="_after_correction.pdf")
44
45# 優勢:不要求所有細胞類型都出現在所有批次中
46# 未共享的細胞類型會被保留而不被扭曲
4.3 範例三:跨條件擾動預測 + 模型存取
此範例展示如何使用自訂的 AnnData 進行預測,以及模型的儲存與載入。
1import scanpy as sc
2import scgen
3import anndata
4import numpy as np
5
6# ============================================================
7# 步驟 1:準備數據並訓練
8# ============================================================
9train = sc.read("./data/train.h5ad")
10sc.pp.normalize_total(train)
11sc.pp.log1p(train)
12
13scgen.SCGEN.setup_anndata(
14 train, batch_key="condition", labels_key="cell_type"
15)
16model = scgen.SCGEN(train)
17model.train(max_epochs=100)
18
19# ============================================================
20# 步驟 2:儲存與載入模型
21# ============================================================
22model.save("./scgen_model/", overwrite=True)
23
24# 在新的 session 中載入
25loaded_model = scgen.SCGEN.load("./scgen_model/", adata=train)
26
27# ============================================================
28# 步驟 3:使用自訂 AnnData 進行預測
29# ============================================================
30# 提供特定的未擾動細胞進行預測(而非指定 celltype_to_predict)
31# 這在跨研究預測時特別有用
32unperturbed_cells = train[
33 (train.obs["cell_type"] == "CD4T") &
34 (train.obs["condition"] == "control")
35].copy()
36
37pred, delta = loaded_model.predict(
38 ctrl_key="control",
39 stim_key="stimulated",
40 adata_to_predict=unperturbed_cells, # 直接傳入 AnnData
41 restrict_arithmetic_to="all" # 使用所有細胞類型計算 delta
42)
43
44# ============================================================
45# 步驟 4:限制特定細胞類型計算 delta
46# ============================================================
47# 只用特定細胞類型來計算擾動向量
48pred_restricted, delta_r = loaded_model.predict(
49 ctrl_key="control",
50 stim_key="stimulated",
51 adata_to_predict=unperturbed_cells,
52 restrict_arithmetic_to={"cell_type": ["CD4T", "CD14+Mono", "B"]}
53)
54
55# ============================================================
56# 步驟 5:潛在空間分析
57# ============================================================
58# 取得潛在空間表示
59latent = loaded_model.get_latent_representation(train)
60train.obsm["X_scgen"] = latent
61
62# 在潛在空間做 UMAP
63sc.pp.neighbors(train, use_rep="X_scgen")
64sc.tl.umap(train)
65sc.pl.umap(train, color=["condition", "cell_type"], save="_latent_umap.pdf")
66
67# 二元分類器視覺化:delta 向量與各細胞的點積分佈
68loaded_model.binary_classifier(
69 train, delta, ctrl_key="control", stim_key="stimulated",
70 path_to_save="./binary_classifier.pdf"
71)
5. 在蛋白質設計/基因組模擬生態系中的定位
5.1 Domain 5 生態系定位
在 Bio-SDG Domain 5「蛋白質設計與基因組模擬」的 22 個專案中,scGen 屬於 B 子群:Genomics & Single-cell Simulation (基因組與單細胞模擬),專注於單細胞擾動響應的虛擬預測 (in-silico perturbation prediction)。
1Domain 5 生態系
2├── A. Protein Design (蛋白質設計) — 14 repos
3│ ├── Language Models: ESM, ProstT5, AbLang, ProGen2
4│ ├── Diffusion: RFdiffusion, Chroma, EvoDiff, SE3-diffusion, ...
5│ └── Antibody: DiffAb, AbLang
6│
7└── B. Genomics & Single-cell Simulation (基因組模擬) — 8 repos
8 ├── Foundation Models: scGPT, scvi-tools
9 ├── ★ scGen ← 擾動預測 (perturbation prediction)
10 ├── Simulation: splatter (scRNA-seq 模擬)
11 ├── Sequence: wgsim, HyenaDNA
12 ├── Multi-omics: biomed-multi-alignment
13 └── Features: PyFeat
5.2 scGen 在 B 子群中的獨特角色
| 工具 | 主要功能 | 與 scGen 的關係 |
|---|---|---|
| scvi-tools | 單細胞 VAE 框架 | scGen 的底層框架,scGen 建構於其上 |
| scGPT | 單細胞基礎模型 | 更通用的 foundation model,可做擾動預測但架構完全不同 |
| splatter | scRNA-seq 模擬 | 生成全合成數據(de novo),scGen 則是條件預測 |
| scGen | 擾動響應預測 | 專精於「已知 control,預測 stimulated」的特定任務 |
5.3 在藥物開發管線 (WP1-WP7) 中的應用
scGen 的擾動預測能力直接服務於 pre-IND 藥物開發的多個階段:
| 工作包 | scGen 應用場景 |
|---|---|
| WP1:標靶辨識 (Target Identification) | 預測 gene knockout / knockdown 後各細胞類型的轉錄組變化,輔助評估標靶可行性 |
| WP2:標靶驗證 (Target Validation) | 在僅有部分細胞類型實驗數據時,預測其他細胞類型的擾動響應,減少實驗成本 |
| WP3:先導物優化 (Lead Optimization) | 預測候選藥物在不同細胞類型中的差異反應,早期識別選擇性 (selectivity) 問題 |
| WP5:毒理學評估 | 預測藥物處理後非標靶細胞的基因表達變化,協助評估 off-target effects |
5.4 藍海機會
- Biologics + scGen:目前 scGen 主要應用於小分子擾動場景,但理論上可擴展至抗體藥物 (biologics) 的細胞響應預測——結合 Domain 5A 的蛋白質設計工具 (RFdiffusion, DiffAb) 設計候選抗體,再用 scGen 預測其對免疫細胞的影響
- Multi-omics Integration:scGen 目前只處理 transcriptomics,結合 biomed-multi-alignment 的多組學對齊能力,可擴展到 proteomics/epigenomics 擾動預測
- Dose-response Modeling:scGen 的向量算術假設是線性的,開發非線性延伸(如 dose-dependent delta scaling)是未探索的方向
6. 與其他工具的整合
6.1 與 scvi-tools 的深度整合
scGen v2 完全重寫為 scvi-tools 框架的模組,這意味著:
1# scvi-tools 的所有基礎設施都可直接使用
2from scvi.model.base import BaseModelClass
3
4# 模型儲存/載入(scvi-tools 標準介面)
5model.save("./model_dir/")
6model = scgen.SCGEN.load("./model_dir/", adata=adata)
7
8# GPU 訓練(scvi-tools 標準介面)
9model.train(accelerator="gpu", devices=1)
10
11# DataLoader 管理(自動處理)
12model._make_data_loader(adata=adata, batch_size=128)
6.2 與 scanpy 的工作流整合
1import scanpy as sc
2import scgen
3
4# scanpy 前處理 → scGen 預測 → scanpy 分析
5adata = sc.read_h5ad("data.h5ad")
6sc.pp.normalize_total(adata)
7sc.pp.log1p(adata)
8sc.pp.highly_variable_genes(adata, n_top_genes=7000)
9
10# scGen 預測
11scgen.SCGEN.setup_anndata(adata, batch_key="condition", labels_key="cell_type")
12model = scgen.SCGEN(adata)
13model.train()
14pred, delta = model.predict(ctrl_key="ctrl", stim_key="stim", celltype_to_predict="CD4T")
15
16# 回到 scanpy 做下游分析
17sc.tl.rank_genes_groups(pred, groupby="condition", method="wilcoxon")
18sc.pl.rank_genes_groups(pred)
6.3 與 AIKT Pipeline 的整合架構
flowchart LR
subgraph AIKT["AIKT Pipeline"]
direction TB
PS["paper-search
(Layer 9)"]
PQ["paper-qa-lite
(Layer 10)"]
TU["tu-plan-generator
(Layer 19)"]
end
subgraph BioSDG["Bio-SDG Domain 5"]
direction TB
SCVI["scvi-tools
(框架層)"]
SCGEN["scGen
(擾動預測)"]
SCGPT["scGPT
(基礎模型)"]
SPLAT["splatter
(數據模擬)"]
end
subgraph DrugDev["Drug Development WP"]
WP1["WP1: Target ID"]
WP2["WP2: Target Validation"]
WP5["WP5: Toxicology"]
end
PS -->|"文獻支持
perturbation datasets"| SCGEN
TU -->|"ChEMBL compound →
perturbation condition"| SCGEN
SCVI --> SCGEN
SPLAT -->|"合成訓練數據
augmentation"| SCGEN
SCGPT -->|"預訓練 embedding
fine-tune"| SCGEN
SCGEN --> WP1
SCGEN --> WP2
SCGEN --> WP5
PQ -->|"RAG 問答
解讀預測結果"| DrugDev
6.4 與其他擾動預測工具的比較
| 工具 | 方法 | 優勢 | 劣勢 |
|---|---|---|---|
| scGen | VAE + vector arithmetic | 簡單直觀、訓練快、scvi-tools 整合 | 線性假設、無劑量效應建模 |
| CPA (Lotfollahi et al., 2023) | Compositional perturbation autoencoder | 支援組合擾動、劑量效應 | 更複雜、需更多數據 |
| GEARS (Roohani et al., 2023) | GNN-based | 支援未見過的基因擾動組合 | 需要基因調控網路先驗 |
| scGPT (Cui et al., 2024) | Transformer foundation model | 通用性最強、zero-shot 能力 | 計算成本高、需大量預訓練數據 |
7. 優缺點分析
7.1 優點
| 面向 | 說明 |
|---|---|
| 概念簡潔 | 向量算術方法直觀易懂,可解釋性 (interpretability) 高於 black-box 方法 |
| 輕量高效 | 核心程式碼僅 5 個檔案、~800 行;訓練速度快(100 epochs 通常 5-15 分鐘) |
| scvi-tools 整合 | 繼承完整的 scvi-tools 生態系(GPU、DataLoader、模型存取、AnnData 管理) |
| 多場景適用 | 擾動預測 + 批次校正 + 跨物種預測三合一 |
| Nature Methods 驗證 | 經過同儕審查 (peer-reviewed),在多個基準數據集上有可靠表現 |
| 內建評估工具 | 提供 reg_mean_plot()、reg_var_plot()、binary_classifier() 等驗證方法 |
7.2 缺點
| 面向 | 說明 |
|---|---|
| 線性假設 | 擾動向量為全域平均 delta,假設擾動效應在潛在空間中是線性且均勻的——對非線性/異質性響應效果有限 |
| 無劑量建模 | 不支援劑量-反應 (dose-response) 關係建模,只有 binary(control vs stimulated) |
| 無組合擾動 | 不支援多重擾動組合預測(如同時敲除兩個基因),後繼工具 CPA 解決了此問題 |
| Cell type 依賴 | 預測品質高度依賴訓練數據中是否有足夠多樣的細胞類型與條件 |
| GPL-3.0 授權 | 商業使用需注意 copyleft 條款,相較 MIT/Apache 較不自由 |
| 維護頻率 | 最後更新 2026-06(仍在維護),但核心架構自 2019 年以來未有重大更新 |
7.3 適用場景建議
| 場景 | 推薦度 | 說明 |
|---|---|---|
| 單一擾動 × 多細胞類型預測 | ★★★★★ | 最佳使用場景,設計初衷 |
| 批次效應移除(有細胞類型標籤) | ★★★★☆ | 有效,但 scVI/Harmony 也是好選擇 |
| 跨物種擾動遷移 | ★★★★☆ | 論文已驗證,需 ortholog 基因對應 |
| 組合擾動預測 | ★★☆☆☆ | 不支援,建議改用 CPA 或 GEARS |
| 劑量效應建模 | ★☆☆☆☆ | 不支援,建議改用 CPA |
| 大規模 Perturb-seq 數據 | ★★★☆☆ | 可用但 scGPT/GEARS 更適合 |
附錄:快速參考
API 速查表
1# 設定數據
2scgen.SCGEN.setup_anndata(adata, batch_key="condition", labels_key="cell_type")
3
4# 建立模型
5model = scgen.SCGEN(adata, n_hidden=800, n_latent=100, n_layers=2, dropout_rate=0.2)
6
7# 訓練
8model.train(max_epochs=100, batch_size=32, early_stopping=True)
9
10# 擾動預測
11pred, delta = model.predict(ctrl_key="ctrl", stim_key="stim", celltype_to_predict="CD4T")
12
13# 批次校正
14corrected = model.batch_removal()
15
16# 潛在空間
17latent = model.get_latent_representation(adata)
18
19# 解碼
20decoded = model.get_decoded_expression(adata)
21
22# 儲存/載入
23model.save("./model_dir/")
24model = scgen.SCGEN.load("./model_dir/", adata=adata)
關鍵超參數
| 參數 | 預設值 | 說明 |
|---|---|---|
n_hidden | 800 | 隱藏層節點數 |
n_latent | 100 | 潛在空間維度 |
n_layers | 2 | encoder/decoder 層數 |
dropout_rate | 0.2 | Dropout 率 |
kl_weight | 0.00005 | KL 散度權重(極小值偏重建) |
單行摘要: scGen 是基於 VAE 向量算術的單細胞擾動預測模型,可透過潛在空間 delta 向量預測未觀測條件下的基因表達,適用於藥物開發管線 WP1-WP2 標靶辨識與驗證階段的 in-silico 擾動模擬。
Comments