3、自监督学习基础:对比学习、掩码建模、生成式方法
要理解自监督学习在空间转录组中的应用,得先搞明白它最核心的三大流派。这三派都是从无标签数据中硬“抠”出监督信号,但路子完全不同。咱们一个个来看,顺便聊聊我在实际项目里踩过的坑。
3.1 对比学习:让相似靠拢,让不同远离
对比学习的思路挺直白。拿一张猫的照片,你做两次不同的数据增强,比如旋转、裁剪、加噪声。这两张增强后的图,还是一只猫,对吧?那它们的特征表达就应该尽量相近。换一张狗的照片,那它的特征就应该和猫的离得远一些。
说白了,就是拉近正样本对,推开负样本对。
在空间转录组里,这个概念怎么落地?
- 正样本:同一个空间spot的不同“视角”。比如,对这个spot的基因表达谱做随机掩码、加高斯噪声,或者用空间邻居的平滑表达。
- 负样本:其他不相关的spot,或者来自不同切片区域的表达谱。
我最初做对比学习项目时,有一个特别深的体会:负样本选不对,模型直接崩。你想想看,如果负样本里混进了正样本,模型就糊涂了,训练根本没法收敛。
实践中,batch size是关键。很多主流对比学习框架(如SimCLR)要求较大的batch size来容纳足够的负样本。但空间转录组数据量可能不够大,这时可以考虑用MoCo这种动量队列结构来维护一个负样本库。
对比学习的典型损失函数:
# InfoNCE 损失,简化版伪代码
def info_nce_loss(features, temperature=0.07):
# features: [batch_size, 2, dim] (两个增强视角)
batch_size, n_views, dim = features.shape
# 计算所有样本间的余弦相似度
similarity_matrix = torch.matmul(features.view(batch_size * n_views, dim),
features.view(batch_size * n_views, dim).T)
# 正样本对:每个样本和它的另一个视角
positives = torch.diag(similarity_matrix, batch_size)
# 负样本:去掉正样本和自身
negatives = ...
# 计算对比损失
logits = positives / temperature
loss = -torch.log(torch.exp(logits) / (torch.exp(logits) + negatives.sum(dim=0)))
return loss.mean()
嗯,这里要注意一点。千万别用全部负样本,那样计算量太大。我一般随机采样一部分,效果够了就好。
3.2 掩码建模:像填空一样的自监督
掩码建模是另一条路。它不搞“拉近推远”,而是把输入的一部分遮住,让模型去猜遮住的是什么。
BERT就是这么干的。把句子里的词用[MASK]遮住,然后训练模型去预测被遮住的词。放到图像里,就是MAE(Masked Autoencoder),遮掉图块,再重建。
这在空间转录组里有什么价值?
我个人习惯用的一个做法是:随机掩码空间点的基因表达,然后让模型根据周围邻居的表达来预测被掩码的位置。
- 输入:部分spot被掩码后的空间表达矩阵。
- 任务:重建被掩码的那些spot的基因表达。
- 学习成果:模型必须理解空间位置关系和基因共表达模式。
我在一次尝试中,不小心把掩码比例设到了90%。结果出乎意料,模型重建出来的结果居然还能看。这说明空间转录组的冗余信息很足,掩码比例高一些反而能迫使学生学到更鲁棒的表征。
我曾经犯过一个低级错误:把掩码操作写成了固定位置掩码。每次训练用的掩码位置都一样。结果模型记住了掩码模式,泛化能力极差。正确的做法是每次epoch或每次迭代随机生成掩码。
3.3 生成式方法:学会创造,才算真的懂
生成式方法走得更远。它不只是判别(对比学习)或填充(掩码建模),而是试图学会整个数据分布的完整描述。模型能生成新的样本。
两个典型的代表:
- 变分自编码器 (VAE):学习一个隐空间,然后从隐空间采样,解码器还原出数据。常用于去噪或生成新样本。
- 扩散模型 (Diffusion Models):向数据逐步加噪,再训练网络学会去噪。从纯噪声开始逐步降噪,就能生成新数据。
在空间转录组领域,你可能想回答一个更高级的问题:如果有一个未见过的空间区域,它的基因表达模式应该是怎样的?
生成式方法就能帮你做这件事。训练一个VAE或扩散模型,输入一些空间spot的表达,就能生成出在形态、分布上都接近真实的空间表达谱。
不过要注意,生成式方法的训练通常比重建任务更不稳定。我试过调VAE的KL散度权重,调了大半天,模型的loss曲线才从“过山车”变为“慢匀速”。
这三者并不互斥。实际上,在空间转录组里,我们经常组合使用:
- 用对比学习来对齐空间邻域和全局特征。
- 用掩码建模来强化局部重建能力。
- 用生成式方法来做数据增广或下游任务的条件生成。
3.4 三者对比一览
我用一张表格帮你快速理清这三个流派的核心区别:
| 方法 | 核心思想 | 正/负样本 | 常见损失 | 空间转录组典型应用 |
|---|---|---|---|---|
| 对比学习 | 拉近正样本,推开负样本 | 需要明确的正/负样本定义 | InfoNCE、NT-Xent | 对齐空间邻居,区分不同组织区域 |
| 掩码建模 | 遮住一部分,预测被遮部分 | 不需要,自动构造输入输出对 | MSE、交叉熵 | 重建被掩码的spot表达,学习空间依赖 |
| 生成式方法 | 学习完整数据分布,可生成新数据 | 不需要,依赖隐变量/随机过程 | ELBO、扩散损失 | 生成空间表达,填补缺失区域 |
3.5 一张图看懂三种范式
下面这张SVG图,用一个统一的对比框架,帮你直观理解三种自监督学习范式的核心差异。
3.6 怎么选?我的建议
在实际项目里,我不会死磕某一种方法。我的选择思路是这样的:
- 如果你想做聚类或分型:对比学习通常更直接。它能学出区分度高的表征,直接用于Spot聚类。
- 如果想做空间填补或降噪:掩码建模很有效。你遮掉噪声点,模型能还原出干净的信号。
- 如果想做数据增强或模拟:生成式方法上场。扩散模型甚至能生成全新的切片数据用于预训练。
当然,这三种方法现在越来越融合。比如SpaceMamba里就同时用了掩码和对比策略。开头那会我只用对比,效果总差一口气,后来加了掩码辅助任务,loss曲线立马好看了。
嗯,基础说完了。其实真正的战场是后续的组合和使用技巧,不过那是后面的话题了。