2. scVI 的数学原理:变分自编码器基础
这一章,我们来聊聊 scVI 背后的数学引擎——变分自编码器(VAE)。
你可能听说过 VAE 是生成模型的一种,专门用来“创造”新数据。但在单细胞数据里,它的角色其实更像个“翻译官”——把混乱的高维表达数据,解码成一条条清晰的生物信号。
别被“变分”两个字唬住。说白了,它就是一套用神经网络做贝叶斯推断的框架。我在项目中第一次推导 VAE 损失时,也觉得这个公式很绕。但理解它,是掌握 scVI 抗批次干扰能力的关键。
2.1 从自编码器到变分自编码器
传统的自编码器长什么样?输入 -> 编码器 -> 压缩成低维向量 -> 解码器 -> 重构出原始数据。这个过程很直观,就像把一个 10000 维的基因表达向量压扁成 10 维,再把它撑回 10000 维。
但普通自编码器有个致命问题:它得到的潜变量是确定性的点。什么意思?每个细胞只能映射到一个具体的 10 维点上。一旦你换了一个有点差异的输入,那个点就会飘走。这种“过拟合”式的压缩,对批次效应特别敏感——不同批次的同类型细胞,会跑到潜空间中不同的角落里。
VAE 的改进很聪明:它不输出单一的潜变量点,而是输出一个概率分布。具体来说,编码器输出的是潜变量的均值和方差。这样,每个细胞在潜空间中不再是一个点,而是一团“云”。
我早期做跨批次整合时,用过普通自编码器做降维对齐,效果非常差。换用 VAE 后,不同批次的同类型细胞终于能聚到同一团“云”里了。这里的概率化,就是抗干扰的起点。
2.2 VAE 的三大组成部分
咱们把 VAE 拆开来看。三部分,不多不少。
| 组件 | 角色 | 在 scVI 中的体现 |
|---|---|---|
| 编码器(Encoder) | 将输入 x 映射为潜变量 z 的后验分布 q(z|x) |
输入基因表达量,输出潜变量均值和方差 |
| 解码器(Decoder) | 从潜变量 z 重构出数据分布 p(x|z) |
生成零膨胀负二项分布(ZINB)的参数 |
| 潜变量空间(Latent Space) | 低维隐变量 z 的分布区域,通常假设为标准正态 |
10-20 维,用于细胞聚类和批次校正 |
为什么编码器要输出方差?因为我们要对那个“不确定性”建模。想一想,一个测序深度很低、基因捕获不全的细胞,它的表达模式本来就模糊。VAE 的方差能捕捉这种模糊性——不确定性越大的细胞,它在潜空间里的“云”就越散。这在后续整合时,能有效避免将低质量细胞强行拉到错误的位置。
2.3 重参数化技巧(Reparameterization Trick)
嗯,这里有个经典问题:VAE 编码器输出的是分布参数(均值 μ 和标准差 σ),然后我们要从分布 N(μ, σ²) 中采样得到具体的潜变量 z。但采样操作是不可导的,梯度传不回去,神经网络就没法训练了。
重参数化技巧是怎么破的?它把采样过程分成两步:
- 从标准正态分布
N(0, 1)中采样一个随机噪声ε - 通过线性变换得到
z = μ + σ ⊙ ε
这样一来,μ 和 σ 的梯度就能直接传递到编码器,整个模型便可端到端训练。
我在调试自己的单细胞模型时,重参数化这一步经常写错。最常见的是标准差预热(annealing),即在训练初期把 σ 标准差的初始值设大一些,让模型先探索潜空间,再逐渐收紧。这个技巧在 scVI 的官方实现中也是可选的。
2.4 VAE 的损失函数
VAE 的损失由两部分构成,这个公式我建议你记在笔记本上:
L = 重构损失 + KL散度
重构损失 = -E_{z~q(z|x)}[log p(x|z)]
= 衡量解码器重构数据的质量
KL散度 = D_KL(q(z|x) || p(z))
= 衡量后验分布与先验分布(标准正态)的差异
这个损失有两个目标,其实是相互制衡的:
- 重构损失:让潜变量尽可能保留原始表达信息,避免信息丢失
- KL 散度:让潜变量分布不要偏离标准正态太远,起到正则化作用
你想啊,如果没有 KL 项,模型就会退化成普通自编码器,潜空间毫无结构可言。如果 KL 项权重过大,重构又会变得很差,生成的数据都是“大路货”。这个平衡,在 scVI 里是通过一个超参数 β(kl_weight)来调节的。
2.5 从 VAE 到 scVI:批次感知编码
scVI 在标准 VAE 基础上加了一个关键设计:把批次标签(batch label)作为条件信息输入到模型中。
具体做法是:
- 编码器输入:基因表达量 x + 批次标签 b → 输出潜变量分布参数
- 潜变量 z:只携带生物变异信息,批次变异被剥离
- 解码器输入:潜变量 z + 批次标签 b → 输出基因表达分布
为什么这样做能抗批次干扰?因为解码器在重构时,知道每个细胞的批次标签。它会“学会”把由批次引起的表达差异,归因于标签变量,而不是潜变量。这样,潜变量 z 就只包含纯粹的生物学信号。
2.6 VAE 在 scVI 中的整体数据流
下面这张图总结了 scVI 从输入到输出的完整流程:
整张图展示了 scVI 训练时的数据流向。注意批次标签 b 既输入到编码器,也输入到解码器——这就是它“记住”批次差异,从而解放潜变量 z 的关键。
2.7 小结:VAE 之于 scVI 的意义
咱们快速回顾一下:
- VAE 输出概率分布,而不是确定性点,这对于建模单细胞数据的不确定性非常关键
- 重参数化技巧让模型可训练,这一步的实现细节直接影响模型收敛
- KL 散度和重构损失的平衡,是调参的核心
- scVI 将批次标签作为条件变量加入 VAE,这是它抗批次干扰的底层机制
我个人觉得,理解 VAE 的这些数学细节,对于后续调整 scVI 的架构、甚至自己写一个定制化模型,都有很大帮助。至少你不会对着那几个损失项发呆,知道“哦,我调 kl_weight 其实是在调潜空间的紧致度”。