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.pySCGEN主模型類別,繼承 scvi-tools 的 BaseModelClass;提供 predict()batch_removal()、繪圖方法
_scgenvae.pySCGENVAEVAE 模組,繼承 BaseModuleClass;定義 encoder/decoder/loss
_base_components.pyDecoderSCGEN自訂 decoder,使用 FCLayers + Linear 輸出
_utils.pyextractor, 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 依賴版本相容性

依賴最低版本備註
Python3.8+建議 3.10
scvi-tools0.20.0+核心框架
scanpy1.6+數據前處理
anndata0.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,可做擾動預測但架構完全不同
splatterscRNA-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 藍海機會

  1. Biologics + scGen:目前 scGen 主要應用於小分子擾動場景,但理論上可擴展至抗體藥物 (biologics) 的細胞響應預測——結合 Domain 5A 的蛋白質設計工具 (RFdiffusion, DiffAb) 設計候選抗體,再用 scGen 預測其對免疫細胞的影響
  2. Multi-omics Integration:scGen 目前只處理 transcriptomics,結合 biomed-multi-alignment 的多組學對齊能力,可擴展到 proteomics/epigenomics 擾動預測
  3. 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 與其他擾動預測工具的比較

工具方法優勢劣勢
scGenVAE + 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_hidden800隱藏層節點數
n_latent100潛在空間維度
n_layers2encoder/decoder 層數
dropout_rate0.2Dropout 率
kl_weight0.00005KL 散度權重(極小值偏重建)

單行摘要: scGen 是基於 VAE 向量算術的單細胞擾動預測模型,可透過潛在空間 delta 向量預測未觀測條件下的基因表達,適用於藥物開發管線 WP1-WP2 標靶辨識與驗證階段的 in-silico 擾動模擬。