基因归因到底怎么计算的?
Power by GPT-5.6 Terra
核心思想是:把某个基因的表达作为输入特征,计算它对 scFM 输出该细胞 embedding 的边际贡献 。分数不是"这个基因表达多高",而是"若削弱/改变这个基因,模型对该细胞的内部表征会变化多大"。SIGnature 将这种 attribution(归因) 定义为基因重要性;公开摘要明确其分数来自 scRNA-seq foundation model 的 attribution,但摘要本身未公开具体采用的归因算子、baseline 和 embedding 标量化公式。
先明确:归因对象是什么?
对于一个细胞 i i i,把其输入表示写成:
x i = ( x i 1 , x i 2 , ... , x i G ) \mathbf{x}i=(x{i1},x_{i2},\ldots,x_{iG}) xi=(xi1,xi2,...,xiG)
其中 x i g x_{ig} xig 是基因 g g g 在细胞 i i i 的输入值;它可能是 normalized count、log-expression,或经过 scFM 特定 tokenization 后的表示。
预训练 scFM 将该输入编码为一个高维细胞表示:
z i = f θ ( x i ) , z i ∈ R d \mathbf{z}i=f\theta(\mathbf{x}_i), \qquad \mathbf{z}_i\in\mathbb{R}^{d} zi=fθ(xi),zi∈Rd
这里:
- f θ f_\theta fθ:固定参数的 scFM;
- x i \mathbf{x}_i xi:一个细胞的基因表达输入;
- z i \mathbf{z}_i zi:该细胞在模型 latent space 中的 embedding;
- d d d:embedding 维度。
SIGnature 要回答的是:
对当前这个细胞而言,基因 g g g 的输入变化,对 z i \mathbf{z}_i zi 的形成到底有多重要?
作者公开描述这一思想为:测量模型在编码某个细胞 embedding 时对每个基因的依赖程度,并由此获得全基因的重要性。
最关键的难点:embedding 是向量
传统分类模型比较简单。假设模型输出"该细胞是 T cell 的概率":
y = f θ ( x ) y=f_\theta(\mathbf{x}) y=fθ(x)
那么基因 g g g 的归因可以直接定义为它对标量 y y y 的贡献。
但 scFM 的输出通常是高维向量:
z = f θ ( x ) ∈ R d \mathbf{z}=f_\theta(\mathbf{x}) \in \mathbb{R}^d z=fθ(x)∈Rd
而"一个基因对向量贡献多少"并不是天然定义的。因此,任何 embedding attribution 方法都必须先定义一个标量目标函数:
s i = h ( z i ) s_i = h(\mathbf{z}_i) si=h(zi)
然后计算基因 g g g 对 s i s_i si 的贡献:
a i g = Attr ( s i , x i g ) a_{ig} = \operatorname{Attr}(s_i, x_{ig}) aig=Attr(si,xig)
其中 a i g a_{ig} aig 就是 SIGnature 所要的 gene attribution / gene importance score。
这个标量目标可能是什么?
在概念上, h ( ⋅ ) h(\cdot) h(⋅) 常见有几种定义:
| 标量目标 | 形式 | 生物学/模型学含义 |
|---|---|---|
| Embedding 范数 | h ( z ) = ∣ z ∣ 2 h(\mathbf{z})=|\mathbf{z}|_2 h(z)=∣z∣2 | 某基因对总体 latent activation 的影响 |
| 与原始 embedding 的相似度 | h ( z ′ ) = cos ( z ′ , z ) h(\mathbf{z}')=\cos(\mathbf{z}',\mathbf{z}) h(z′)=cos(z′,z) | 某基因是否维持当前细胞身份 |
| 与群体中心的相似度 | h ( z ) = cos ( z , c MS1 ) h(\mathbf{z})=\cos(\mathbf{z},\mathbf{c}_{\text{MS1}}) h(z)=cos(z,cMS1) | 某基因是否支持某特定 cell state |
| 到参考群体的距离 | h ( z ) = − ∣ z − c ref ∣ 2 h(\mathbf{z})=-|\mathbf{z}-\mathbf{c}_{\text{ref}}|_2 h(z)=−∣z−cref∣2 | 某基因是否使细胞接近某个状态 |
| 下游预测分数 | h ( z ) = q ( z ) h(\mathbf{z})=q(\mathbf{z}) h(z)=q(z) | 某基因对 cell type / disease / perturbation prediction 的影响 |
**SIGnature 的一般思想是解释 embedding,而不是直接解释某个人工监督标签。**这使它能在没有预定义 cell-type label 或 disease label 的情况下,给单细胞进行 gene-level 解释。
对论文复现或严谨解读来说,最值得核对 Methods 的一句话就是:
"他们如何把 cell embedding 转换为 attribution 所需的 scalar target?"
这一步决定了分数的精确定义。
两种直观计算方式
方法一:遮挡/反事实扰动
最直观的算法是对一个基因进行"删掉、置零或替换为 baseline"的反事实实验。
对原始细胞输入 x i \mathbf{x}_i xi,构造一个只修改基因 g g g 的版本:
x ~ i ( g ) = ( x i 1 , ... , x i g base , ... , x i G ) \tilde{\mathbf{x}}{i}^{(g)} = (x{i1}, \ldots, x_{ig}^{\text{base}}, \ldots, x_{iG}) x~i(g)=(xi1,...,xigbase,...,xiG)
其中 x i g base x_{ig}^{\text{base}} xigbase 可以是:
- 0;
- 该基因在背景细胞中的表达;
- 该基因的训练集均值;
- 与该细胞匹配的对照细胞表达;
- 模型定义的 mask token 或缺失 token。
然后分别编码原始细胞与扰动细胞:
z i = f θ ( x i ) \mathbf{z}i=f\theta(\mathbf{x}_i) zi=fθ(xi)
z ~ i ( g ) = f θ ( x ~ i ( g ) ) \tilde{\mathbf{z}}{i}^{(g)} = f\theta(\tilde{\mathbf{x}}_{i}^{(g)}) z~i(g)=fθ(x~i(g))
最后用 embedding 的变化作为重要性:
a i g = ∥ z i − z ~ i ( g ) ∥ 2 a_{ig} = \left\| \mathbf{z}i-\tilde{\mathbf{z}}{i}^{(g)} \right\|_2 aig= zi−z~i(g) 2
其含义非常直接:
- a i g a_{ig} aig 大:遮掉基因 g g g 后 embedding 改变很大,模型很依赖该基因;
- a i g a_{ig} aig 小:遮掉该基因后 embedding 基本不变,该基因对当前模型表征不重要。
一个玩具例子
假设一个单核细胞的原始 embedding 是:
z original = ( 0.8 , 1.2 , − 0.3 ) \mathbf{z}_{\text{original}}=(0.8, 1.2, -0.3) zoriginal=(0.8,1.2,−0.3)
遮掉某个基因 g 1 g_1 g1 后:
z − g 1 = ( 0.79 , 1.19 , − 0.29 ) \mathbf{z}_{-g_1}=(0.79, 1.19, -0.29) z−g1=(0.79,1.19,−0.29)
则:
a g 1 = ∥ z original − z − g 1 ∥ 2 ≈ 0.017 a_{g_1} = \|\mathbf{z}{\text{original}}-\mathbf{z}{-g_1}\|_2 \approx 0.017 ag1=∥zoriginal−z−g1∥2≈0.017
说明 g 1 g_1 g1 对该细胞 embedding 贡献很小。
若遮掉另一个基因 g 2 g_2 g2 后:
z − g 2 = ( 0.3 , 0.4 , − 0.8 ) \mathbf{z}_{-g_2}=(0.3, 0.4, -0.8) z−g2=(0.3,0.4,−0.8)
则:
a g 2 = ∥ z original − z − g 2 ∥ 2 ≈ 1.02 a_{g_2} = \|\mathbf{z}{\text{original}}-\mathbf{z}{-g_2}\|_2 \approx 1.02 ag2=∥zoriginal−z−g2∥2≈1.02
说明 g 2 g_2 g2 对模型编码该细胞的状态非常关键。
它的优缺点
- 优点:最符合"移除该基因后会怎样"的直觉;对模型架构要求低。
- 缺点 :若有 20,000 20{,}000 20,000 个基因,对每个细胞逐基因重跑一次模型,成本大约是 G G G 次 forward pass,面对千万级 cell atlas 很昂贵。
- 另一个问题:将表达直接置零可能产生不真实的、超出训练分布的输入;因此 baseline 的选择非常关键。
梯度归因:更可能的高效实现
为了在大规模数据上计算,实践中更可能使用梯度型归因。直观地说,梯度问的是:
当我让基因 g g g 的输入值发生一个无穷小变化时,模型的目标输出会变化多快?
若目标是标量 s i = h ( f θ ( x i ) ) s_i=h(f_\theta(\mathbf{x}_i)) si=h(fθ(xi)),则基因 g g g 的局部敏感度为:
∂ s i ∂ x i g \frac{\partial s_i}{\partial x_{ig}} ∂xig∂si
这就是 gradient saliency。
但仅用梯度有一个问题:它只衡量局部斜率,忽略了基因本身输入值的大小。因此,一个常见版本是 Gradient × Input:
a i g Grad × Input = x i g ⋅ ∂ s i ∂ x i g a_{ig}^{\text{Grad}\times\text{Input}}= x_{ig} \cdot \frac{\partial s_i}{\partial x_{ig}} aigGrad×Input=xig⋅∂xig∂si
其直觉是:
- 若 x i g x_{ig} xig 很低,即使梯度很大,其实际贡献未必大;
- 若表达值高但局部梯度接近 0,说明模型在该位置对其不敏感;
- 只有输入值和模型敏感度同时大时,分数才大。
对于 vector embedding,也可直接计算 Jacobian:
J i g = ∂ z i ∂ x i g ∈ R d \mathbf{J}_{ig}= \frac{\partial \mathbf{z}i}{\partial x{ig}} \in \mathbb{R}^{d} Jig=∂xig∂zi∈Rd
并以其范数作为"基因对整个 embedding 的局部影响":
a i g = ∥ ∂ z i ∂ x i g ∥ 2 a_{ig}= \left\| \frac{\partial \mathbf{z}i}{\partial x{ig}} \right\|_2 aig= ∂xig∂zi 2
或加入输入强度:
a i g = ∣ x i g ∣ ⋅ ∥ ∂ z i ∂ x i g ∥ 2 a_{ig}= |x_{ig}| \cdot \left\| \frac{\partial \mathbf{z}i}{\partial x{ig}} \right\|_2 aig=∣xig∣⋅ ∂xig∂zi 2
这个形式在概念上与"基因对 embedding 的贡献"最贴近:只需一次或少数几次反向传播,就可以同时得到所有基因的敏感度。
Integrated Gradients:比纯梯度更稳健
深度网络存在梯度饱和问题:某个基因从低表达变到高表达确实很重要,但在当前高表达点附近梯度可能接近零。于是常用 Integrated Gradients(IG)。
它不只看当前点的梯度,而是从一个 baseline x ′ \mathbf{x}' x′ 沿直线积分到真实细胞 x \mathbf{x} x:
IG i g = ( x i g − x i g ′ ) ∫ 0 1 ∂ h ( f θ ( x ′ + α ( x i − x ′ ) ) ) ∂ x i g d α \operatorname{IG}{ig}= (x{ig}-x'{ig}) \int_0^1 \frac{\partial h(f\theta(\mathbf{x}'+\alpha(\mathbf{x}i-\mathbf{x}')))} {\partial x{ig}} d\alpha IGig=(xig−xig′)∫01∂xig∂h(fθ(x′+α(xi−x′)))dα
实际计算时,用 m m m 个积分点近似:
IG i g ≈ ( x i g − x i g ′ ) ⋅ 1 m ∑ k = 1 m ∂ h ( f θ ( x ) ) ∂ x i g ∣ x = x ′ + k m ( x i − x ′ ) \operatorname{IG}{ig} \approx (x{ig}-x'{ig}) \cdot \frac{1}{m} \sum{k=1}^{m} \left. \frac{\partial h(f_\theta(\mathbf{x}))} {\partial x_{ig}} \right|_{ \mathbf{x}= \mathbf{x}' + \frac{k}{m} (\mathbf{x}_i-\mathbf{x}') } IGig≈(xig−xig′)⋅m1k=1∑m∂xig∂h(fθ(x)) x=x′+mk(xi−x′)
这条公式如何理解?
从 baseline 到真实细胞之间,IG 会模拟表达谱逐渐"从背景细胞变成当前细胞"的过程:
text
baseline expression
↓
10% 当前细胞表达
↓
20% 当前细胞表达
↓
...
↓
100% 当前细胞表达
对每一步,它都计算"增加基因 g g g 会让模型表征变化多少",再将所有步骤累积。
因此,IG 更接近下面的反事实问题:
从一个背景表达状态出发,逐步加入当前细胞中基因 g g g 的表达信息,它总共把 embedding 推动了多少?
归因分数的正负号意味着什么?
如果模型归因保留符号,那么:
a i g > 0 a_{ig}>0 aig>0
可解释为:增加该基因的输入,使细胞更倾向于目标 embedding / target state。
而:
a i g < 0 a_{ig}<0 aig<0
可解释为:该基因使细胞远离目标 embedding / target state,或者抑制目标程序。
但如果最终采用的是 embedding 差异范数:
a i g = ∥ z i − z ~ i ( g ) ∥ 2 a_{ig}= \|\mathbf{z}_i-\tilde{\mathbf{z}}_i^{(g)}\|_2 aig=∥zi−z~i(g)∥2
那么分数恒为非负,只能说明"重要性大小",不能区分这个基因是支持还是反对某个状态。
这也是分析 SIGnature 输出时必须确认的点:
- 输出的是有符号 attribution,还是绝对值?
- 排序时是否取 ∣ a i g ∣ |a_{ig}| ∣aig∣?
- gene set query 匹配正归因、负归因,还是两者都使用?
- 高分基因表示"激活该程序",还是只表示"模型依赖它区分该程序"?
从单细胞归因到 MS1 signature
得到每个细胞的 attribution 向量后,可以构造:
A ∈ R N × G \mathbf{A} \in \mathbb{R}^{N\times G} A∈RN×G
其中:
A i g = a i g A_{ig}=a_{ig} Aig=aig
即第 i i i 个细胞对第 g g g 个基因的重要性。
若关心 MS1 单核细胞群 C MS1 C_{\text{MS1}} CMS1,则可以聚合:
S g MS1 = median i ∈ C MS1 ( a i g ) S_g^{\text{MS1}}= \operatorname{median}{i\in C{\text{MS1}}} (a_{ig}) SgMS1=mediani∈CMS1(aig)
或使用均值:
S g MS1 = 1 ∣ C MS1 ∣ ∑ i ∈ C MS1 a i g S_g^{\text{MS1}}= \frac{1}{|C_{\text{MS1}}|} \sum_{i\in C_{\text{MS1}}}a_{ig} SgMS1=∣CMS1∣1i∈CMS1∑aig
这样就可得到一个群体级 gene importance ranking:
text
MS1 cells
↓
每个细胞有一套 gene attribution
↓
在 MS1 细胞内聚合
↓
得到 "MS1 状态最依赖哪些基因"
它与传统 DEG 的区别是:
DEG g ∼ MS1 中表达是否高于对照 \text{DEG}_g \sim \text{MS1 中表达是否高于对照} DEGg∼MS1 中表达是否高于对照
而 SIGnature 更接近:
SIGnature g ∼ scFM 编码 MS1 状态时是否依赖基因 g \text{SIGnature}_g \sim \text{scFM 编码 MS1 状态时是否依赖基因 }g SIGnatureg∼scFM 编码 MS1 状态时是否依赖基因 g
论文以 MS1 monocyte signature 为案例,在约 400 项研究中查询该程序,并据此发现其与川崎病等高炎症状态的关联,后续用患者血清诱导实验验证了 MS1-like phenotype。
关键不是"梯度",而是三个选择
即便都使用 Integrated Gradients,不同实现也可能得出不同的基因排名。真正决定 attribution 生物学含义的是以下三件事。
1. 解释什么目标?
h ( f θ ( x ) ) h(f_\theta(\mathbf{x})) h(fθ(x))
是 embedding norm、相似度、距离,还是下游分类 score?
- 若解释 cell-type classifier logit:得到的是"什么基因使模型把它判为某类细胞"。
- 若解释 MS1 signature score:得到的是"什么基因使模型认定它像 MS1"。
- 若解释 整个 embedding:得到的是"什么基因让模型形成当前细胞表示"。
SIGnature 的定位更接近第三种:从 scFM 表征出发定义基因重要性。
2. baseline 是谁?
IG 或遮挡都需要背景输入 x ′ \mathbf{x}' x′。
可选 baseline 包括:
- 全零表达;
- 数据集平均细胞;
- 同一细胞类型的健康对照;
- 同一 donor 的参考细胞;
- 与目标细胞最相似、但不具备目标状态的细胞。
这会直接改变问题含义:
Attr ( x ; x zero ) \operatorname{Attr}(\mathbf{x};\mathbf{x}_{\text{zero}}) Attr(x;xzero)
回答的是:"相对无表达状态,哪些基因塑造当前 embedding?"
Attr ( x ; x healthy mono ) \operatorname{Attr}(\mathbf{x};\mathbf{x}_{\text{healthy mono}}) Attr(x;xhealthy mono)
回答的是:"相对健康单核细胞,哪些基因驱动其转向当前炎症状态?"
对 MS1 这类 disease-state 问题,第二种通常具有更直接的生物学解释。
3. 模型输入究竟是什么?
这是 scFM attribution 中非常容易被忽略的问题。
- 对 count-based / continuous-expression 模型,可以直接对表达量做梯度。
- 对 gene-rank 模型,输入常是基因的排序或 token 序列;此时不能简单解释成"表达值增加一个单位"的梯度。
- 对 transformer 模型,归因可能针对 gene token embedding、attention path 或输入 embedding,而非原始 count。
因此,SIGnature 分数最终解释的严格表述应是:
基因 g g g 对该 scFM 所使用的输入表示和其生成的细胞 embedding 的贡献。
而不能不加限定地说成"基因 g g g 对真实细胞命运的因果贡献"。
总结
SIGnature 的基因归因并不是对表达矩阵重新做一次差异分析,而是固定一个预训练 scFM,将每个细胞的基因表达输入映射为 cell embedding,再度量单个基因被遮挡、替换或沿 baseline 到真实输入路径逐步加入时,模型 embedding 改变的程度。这个变化可通过扰动前后 embedding 距离、输入梯度、Gradient × Input 或 Integrated Gradients 等方式量化。最终,每个细胞都会得到一个 gene attribution vector;将其在某类细胞或疾病条件内聚合,便得到该状态的 gene importance ranking。高分只意味着模型依赖该基因编码当前状态,不自动等价于该基因是生物学因果驱动因子。
最精炼地说,SIGnature 的关键原理就是:
Gene importance = 该基因改变时,scFM cell embedding 改变的程度 \boxed{ \text{Gene importance}= \text{该基因改变时,scFM cell embedding 改变的程度} } Gene importance=该基因改变时,scFM cell embedding 改变的程度
但严谨版本必须补上三项限定:
importance = 特定模型 + 特定输入编码 + 特定归因目标/基线 \boxed{ \text{importance}= \text{特定模型} + \text{特定输入编码} + \text{特定归因目标/基线} } importance=特定模型+特定输入编码+特定归因目标/基线