Harmony算法原理:软聚类与迭代调整的核心思想
好,在动手跑代码之前,咱们先把Harmony的黑盒拆开看一眼。
我当年第一次用Harmony时,心里就犯嘀咕:这玩意儿凭什么能把不同批次的细胞cluster对齐在一起?后来看了论文才明白——它干的其实是个很聪明的「轮流改错」的活。
说白了,Harmony的核心就两件事:软聚类和迭代调整。听起来玄乎,其实就是「假设-校正-再假设」的循环。
2.1 软聚类:不再是「非此即彼」
你用过K-means吧?每个点硬邦邦地只属于一个簇。Harmony可不这么干——它给每个细胞发一张「概率卡」,上面写着它属于各个簇的可能性。
为什么非得软?因为批次效应往往只影响部分细胞。你硬把它分给某一个中心,那批次差异就会「漏」到聚类结果里。软聚类让细胞可以同时沾多个簇,拟合时才知道偏差到底来自哪个方向。
- 硬聚类:0 或 1,非黑即白
- 软聚类:0.1 给A簇,0.7给B簇,0.2给C簇
- 关键:每个细胞有一组概率,和为1
我在做小鼠脑单细胞数据时遇到过:同一个细胞类型在两个批次里被分开,硬聚类死活拉不回来。换成Harmony后,那些概率值在0.4~0.6之间晃荡的细胞,正好是批次差异最严重的部分——软聚类第一周就把它揪出来了。
2.2 迭代调整:就像两个人互相校准
软聚类只是第一步。接下来Harmony进入一个循环:
- E步(Expectation):根据当前的聚类中心和批次矫正向量,重新计算每个细胞对各簇的概率。
- M步(Maximization):用这些概率做权重,重新估计聚类中心,同时调整每个批次的偏移量。
E和M轮流干,干一次细胞坐标就会挪一点。直到所有批次在同一个簇内的分布变得不可区分。
我个人的看家经验:迭代次数不是越多越好。我曾在淋巴瘤数据上跑了200步,结果过度对齐把真实的亚群差异给抹掉了。一般15~20步就够了,你可以在输出日志里看convergence那个值,跌到1e-5以下基本就稳了。
2.3 藏在背后的数学直觉
Harmony用的损失函数我简单翻译一下:
它想最小化的其实有两项——
| 目标 | 数学含义 | 现实意义 |
|---|---|---|
| 紧凑性 | 每个细胞尽可能靠近它所属的簇中心 | 同类细胞聚在一起 |
| 混杂性 | 每个簇里各批次的细胞数量尽量均匀 | 批次差异被消除 |
这两项是互斥的:你让细胞往cluster中心靠,那批次偏移就凸显出来了;你把批次拉匀,细胞又容易散开。Harmony用软聚类权重做杠杆,每一次迭代都会重新平衡这两个力量。
我习惯把这过程想象成「拔河比赛」——左边是生物学差异的绳子,右边是批次效应的绳子。软聚类就是一个裁判,每次喊「停」,然后重算两边的力。
2.4 Harmony的实际运作流程
下面这张图你可以存下来,跑Harmony时脑子里过一遍:
2.5 代码层面怎么体现?
Harmony在R包里只有一行核心调用,但内部循环我们其实可以手动拆着玩。我用Python的harmony-pytorch做过一个迷你版本,核心逻辑就几十行:
# 伪代码示意:一次迭代
def harmony_iteration(Z, batch_labels, K, theta):
# E步:计算软聚类概率
distances = compute_pairwise_distances(Z, cluster_centers)
probabilities = softmax(-distances / theta, axis=1)
# M步:更新聚类中心(加权平均)
cluster_centers = (probabilities.T @ Z) / probabilities.sum(axis=0)
# 更新批次校正向量(每个批次一个偏移)
for b in unique_batches:
mask = (batch_labels == b)
batch_offset[b] = Z[mask].mean(axis=0) - cluster_centers_offset
注意那个theta参数——它控制软分配的「软度」。theta越大,概率越平均,细胞越模糊;theta越小,越接近硬聚类。我一般设0.4~0.8,具体看你的数据离散度。
我曾经踩过一个坑:theta设成0.1,结果每个细胞概率几乎都是1,软聚类退化成了硬聚类,批次效应纹丝不动。所以啊,theta太小就白做了。
2.6 为什么Harmony能胜过传统方法?
传统批次校正(比如ComBat)假设批次效应是线性可加的,但单细胞数据里批次偏移往往是非线性的、局部的。Harmony的软聚类让每个细胞可以「半推半就」地归入一个簇,迭代调整时只修正那些批次间不一致的部分,不碰生物学信号。
你想想看:一个细胞在批次1里属于cluster A的概率是0.7,在批次2里却是0.2——那Harmony就知道这个细胞的坐标需要往A簇方向拉一拉。而如果两个批次里概率一样,它就不动。这就是它聪明的点。
我个人习惯把Harmony的迭代过程输出成动画看一下——每次迭代细胞颜色的混杂度逐渐升高,看着很解压。
好了,算法原理就到这里。下一章我们会用真实数据集一步一步跑通Harmony,并对比校正前后的UMAP图。到时候你就能用眼睛验证我刚才讲的所有东西了。
好了,算法原理就到这里。你心里应该有数了:软聚类让批次效应无处藏身,迭代调整让细胞坐标一点点往对的方向挪。这就是Harmony能成为单细胞批次校正头号选手的秘密。