☰
可微分聚类实现无监督图像分割:原理、实现与调参指南
2026/10/14 10:22:38 网站建设 项目流程

1. 为什么这篇论文值得反复读

图像分割这个方向,做的人多,但真正把"无监督"和"可微分聚类"这两件事捏在一起讲清楚的论文并不多。这篇《Unsupervised Learning of Image Segmentation Based on Differentiable Feature Clustering》我第一次读的时候,最直接的感受是:它没有绕弯子,而是正面回答了无监督分割里最核心的一个矛盾——聚类本身是不可导的,但深度学习需要梯度。

如果你做过分割任务,应该知道传统路子基本两条:一条是全监督,靠大量像素级标注喂模型;另一条是弱监督或者交互式,用框、涂鸦、点来降低标注成本。但这两条路都绕不开"标注"这件事。而无监督分割的目标是彻底甩掉标注,直接从图像本身的结构里学出分割边界。这篇论文的思路是:用深度网络提取特征,然后在特征空间里做聚类,把聚类结果当作伪标签反过来监督网络训练。听起来简单,但难点在于聚类操作(比如K-means里的argmax)是不可导的,梯度传不回去,网络就没法端到端训练。

它的解法是引入一个可微分的软聚类层,用softmax近似argmax,让整个流程可以反向传播。这个思路在当时算是比较早地把"聚类"和"端到端训练"真正打通的尝试之一。适合谁读?我觉得三类人:一是做无监督/自监督分割的研究生,二是想理解可微分聚类怎么落地到视觉任务的工程师,三是对特征聚类和对比学习感兴趣但还没找到切入点的开发者。哪怕你不做分割,这套"软分配+端到端"的范式在很多任务里都能迁移。

我读这篇论文的时候做了不少笔记,也复现过核心模块。下面我按自己的理解,把它的设计思路、关键细节、实操要点和踩过的坑拆开讲一遍。不是翻译论文,而是从一个从业者的角度,讲清楚它为什么这么设计、怎么落地、哪里容易出问题。

2. 整体设计与思路拆解

2.1 无监督分割的核心矛盾在哪

先说清楚问题本身。给定一张图,无监督分割要输出每个像素的类别,但没有任何人工标注。那监督信号从哪来?这篇论文的答案是:从特征本身的聚类结构里来。

逻辑链条是这样的:如果网络学到的特征足够好,那么同一物体的像素在特征空间里应该聚在一起,不同物体的像素应该分开。于是可以对特征做聚类,得到每个像素的簇分配,把这个分配当作伪标签,用交叉熵去监督网络。网络更新后特征更好,聚类更准,形成正循环。

但这里有个致命问题:标准聚类(比如K-means)的最后一步是argmax,即每个像素硬分配给最近的簇中心。argmax不可导,梯度断在这里,网络没法端到端训练。你可能会想,那就分两阶段交替做——先聚类生成伪标签,再训练网络。但交替训练不稳定,而且聚类结果和网络特征容易互相拖后腿。

注意:交替训练在早期确实能用,但收敛慢且对初始化敏感。我试过在类似任务上做交替,聚类中心漂移很严重,尤其是类别数设多了以后。

2.2 可微分软聚类层是怎么设计的

论文的关键创新就是把这个argmax换成softmax形式的软分配。具体来说,对每个像素的特征向量,计算它到每个簇中心的距离(或相似度),然后用softmax归一化成概率分布。这样每个像素对每个簇都有一个软分配概率,整个操作可导,梯度可以回传。

为什么用softmax而不是别的?因为softmax天然输出概率分布,且对温度参数敏感,可以通过调节温度来控制分配的"软硬程度"。温度高时分配更均匀,温度低时接近硬分配。这个温度参数在训练中很关键,后面会细讲。

另一个设计点是簇中心怎么来。论文里簇中心不是固定参数,而是通过网络特征动态计算的,相当于对当前batch内所有像素特征做加权平均。这样簇中心随网络更新而更新,不需要额外的聚类步骤。

提示:软分配和硬分配的区别,可以类比成"投票"和"举手"。硬分配是每个像素只举一个簇的手,软分配是每个像素给所有簇投票,票数加起来为1。投票的好处是信息更丰富,梯度更平滑。

2.3 为什么这个设计能work

从梯度角度看,软分配让每个像素的损失对所有簇中心都有梯度贡献,而不是只对最近的那个簇。这意味着即使某个像素当前分配错了,它仍然能通过其他簇的概率获得梯度信号,慢慢纠正。硬分配则是一旦分错,梯度只往错误方向走,容易陷入局部最优。

从表示学习角度看,软聚类相当于一种正则化,迫使网络学到的特征在簇结构上更清晰。这和对比学习里"拉近正样本、推远负样本"的思路有相通之处,只不过这里正负样本是由聚类结构隐式定义的。

从工程角度看,整个模块可以插到任意CNN后面,不需要改网络主干,也不需要额外的聚类库,实现成本低。这也是它容易被复现的原因之一。

3. 核心细节解析与实操要点

3.1 特征提取网络的选择与影响

论文里用的是全卷积网络(FCN)作为特征提取器,输出每个像素的特征向量。为什么用FCN而不是分类网络?因为分割是密集预测任务,需要保留空间分辨率。如果用分类网络,最后的空间信息会被池化层压没了。

实操中,主干网络的选择对结果影响很大。我试过用ResNet做主干,但直接拿分类网络的最后特征图,分辨率太低,分割边界很糊。后来改成在中间层接一个上采样,或者用空洞卷积保持分辨率,效果明显好一些。

另一个细节是特征维度。论文里特征维度设的是比较小的值(具体数值论文有写,我这里不照搬),维度太高容易过拟合,太低又表达不够。我的经验是,在无监督设定下,特征维度控制在几十到一百多之间比较稳,太高反而会让聚类结构变散。

注意:无监督分割对主干网络的初始化很敏感。用预训练权重(比如在大型分类数据集上训过的)比随机初始化好很多,因为预训练特征本身就有一定的语义结构,聚类更容易收敛。

3.2 软聚类层的温度参数怎么调

温度参数是软聚类层里最需要调的东西。温度高,softmax输出接近均匀分布,每个像素对所有簇都有差不多的概率,梯度信号分散但平滑;温度低,输出接近one-hot,梯度信号集中但容易震荡。

我的做法是从一个较高的温度开始,随着训练逐步降低。这叫"退火"策略。早期温度高,让网络先学到一个粗糙的簇结构;后期温度低,让分配逐渐硬化,逼近真正的分割结果。

具体怎么设?我一般初始温度设在1.0左右,然后按指数衰减到0.1。但这个值跟特征尺度和距离度量方式有关,不能照搬。如果你用的是余弦相似度而不是欧氏距离,温度的影响会不一样,需要重新调。

提示:温度调参有个实用技巧——观察聚类分配的熵。如果熵一直很高(接近均匀分布),说明温度太高;如果熵骤降然后震荡,说明温度太低。理想情况是熵平滑下降。

3.3 簇中心初始化和更新策略

簇中心怎么初始化,直接影响聚类会不会塌缩。什么叫塌缩?就是所有像素都被分到同一个簇,或者少数几个簇占了绝大多数像素,其他簇空着。这在无监督聚类里非常常见。

论文里的做法是用当前batch的特征动态计算簇中心,相当于一种在线更新。但初始化仍然重要。我试过两种初始化:一种是随机选一批像素特征当初始中心,另一种是用K-means++在第一个batch上跑一次得到初始中心。后者更稳,塌缩概率低很多。

更新策略上,论文用的是动量更新,即簇中心不是完全替换,而是按一定比例向新计算的中心靠近。这样避免中心跳变太大导致训练不稳定。动量系数我一般设0.9到0.99之间,太小了中心漂移快,太大了适应慢。

注意:如果发现训练过程中某些簇的分配数一直接近零,说明这些簇"死了"。解决办法要么减少簇数,要么在损失里加一个平衡项,鼓励各簇分配均匀。

3.4 损失函数的设计与权重

损失函数主体是软分配和伪标签之间的交叉熵,但伪标签本身也是软分配生成的,这就有点"自己监督自己"的味道。为了避免退化解(比如所有像素都分到同一簇),论文加了正则项。

具体来说,有两个关键正则:一是熵正则,鼓励分配不要太尖锐也不要太均匀;二是平衡正则,鼓励各簇的像素数大致均衡。这两个正则的权重需要调,权重太大主损失被压制,太小起不到作用。

我的经验是,主损失和正则损失的权重比大概在1:0.1到1:0.5之间。可以先固定主损失权重为1,然后调正则权重,观察簇分配是否均衡。如果发现塌缩,就加大平衡正则;如果发现分配太散,就加大熵正则。

损失项作用权重建议异常表现
主交叉熵监督软分配逼近伪标签1.0权重太小则聚类无方向
熵正则控制分配软硬程度0.1~0.3太大则分配过软,边界模糊
平衡正则防止簇塌缩0.1~0.5太小则少数簇占主导

4. 实操过程与核心环节实现

4.1 数据准备与预处理要点

无监督分割虽然不需要标注,但对数据本身有要求。图像分辨率不能太低,否则边界信息丢失严重;也不能太高,否则显存吃不消。我一般把短边缩放到256到320之间,保持长宽比,然后随机裁剪到固定大小。

归一化方面,用ImageNet的均值和方差做标准化比较稳,因为主干网络通常是在那个分布上预训练的。如果你用的主干是随机初始化的,那就用数据集自身的统计量做标准化。

数据增强在无监督设定下要小心。翻转、旋转这类几何变换可以用,因为不改变语义结构;但颜色抖动要慎用,因为颜色是聚类的重要线索,抖太狠会让同一物体的特征散开。我试过加颜色抖动,结果聚类边界明显变差,后来去掉了。

提示:如果你的数据集里物体尺度变化很大,建议做多尺度训练,即每个batch里混合不同尺度的图像。这样网络学到的特征对尺度更鲁棒,聚类更稳。

4.2 网络搭建与软聚类层实现

网络主体是FCN,后面接软聚类层。软聚类层的实现分三步:计算像素特征到簇中心的距离、softmax归一化、计算损失。

距离度量我推荐用负欧氏距离或者余弦相似度。欧氏距离对特征尺度敏感,如果特征没归一化,距离会被大值主导;余弦相似度只看方向,对尺度不敏感,但会丢失幅度信息。我的经验是,特征先做L2归一化,然后用欧氏距离,效果比较稳。

softmax的温度参数按前面说的退火策略来。实现上,温度可以作为一个可学习的参数,也可以手动调度。我倾向于手动调度,因为可学习温度容易跑偏,训练不稳定。

簇中心的计算是在每个batch内对所有像素特征做加权平均,权重就是软分配概率。这相当于EM算法里的M步,只不过这里是可导的。实现时注意用detach或者stop_gradient控制梯度流向,避免中心更新和特征更新互相干扰。

# 软聚类层核心逻辑示意(伪代码) def soft_cluster(features, centers, temperature): # features: [B, C, H, W] -> [B*H*W, C] # centers: [K, C] features_flat = features.view(-1, C) features_norm = F.normalize(features_flat, dim=1) centers_norm = F.normalize(centers, dim=1) # 余弦相似度 sim = torch.matmul(features_norm, centers_norm.t()) # [N, K] # 软分配 assign = F.softmax(sim / temperature, dim=1) # [N, K] # 更新簇中心(加权平均) new_centers = torch.matmul(assign.t(), features_flat) # [K, C] new_centers = new_centers / (assign.sum(dim=0, keepdim=True).t() + 1e-8) return assign, new_centers

4.3 训练流程与关键参数

训练流程是端到端的:前向传播得到特征,软聚类得到分配,计算损失,反向传播更新网络和簇中心。簇中心用动量更新,不参与梯度。

关键参数我列一下我的常用配置:batch size设8到16(显存允许的话越大越好,因为簇中心估计更准);学习率用1e-4到1e-3,配合余弦退火;训练轮数看数据集,一般50到100轮能看到收敛趋势;簇数K根据数据集类别数设,但无监督设定下你未必知道真实类别数,可以先设一个偏大的值,然后观察哪些簇是空的,再调整。

注意:簇数K设得比真实类别多,通常比设少好。设多了,多余的簇会分到一些边界像素或者噪声;设少了,多个类别会被合并,分割结果直接错。我一般先设真实类别数的1.5倍,然后根据空簇情况往下调。

4.4 评估与可视化方法

无监督分割的评估比较尴尬,因为没有标注就没法算标准的IoU。论文里用的是聚类质量指标,比如归一化互信息(NMI)和调整兰德指数(ARI),这些指标不需要知道簇和类别的对应关系,只看聚类结构是否和真实类别一致。

实操中,我还会做可视化检查:把软分配的概率图或者硬分配的彩色图叠加在原图上,肉眼看边界是否贴合物体轮廓。这个方法虽然主观,但能快速发现明显问题,比如边界糊、簇塌缩、某些区域被完全忽略。

如果手头有少量标注(哪怕只有几张图),可以用来做定性验证,但不参与训练。这样既能保持无监督设定,又能有个参考。

5. 常见问题与排查技巧实录

5.1 训练不收敛或损失震荡

这是最常见的问题。原因通常有三个:温度参数设得不对、学习率太大、簇中心更新太快。

排查顺序:先看温度。如果温度太低,softmax输出接近one-hot,梯度信号很尖锐,容易震荡。把温度调高试试。如果温度没问题,看学习率,无监督训练通常比监督训练对学习率更敏感,调小一个数量级试试。如果还不行,看簇中心动量系数,调大一点让中心更新更平滑。

我踩过的一个坑是:一开始用Adam优化器,默认学习率1e-3,结果损失剧烈震荡。后来换成SGD加动量,学习率降到1e-4,稳定多了。无监督任务里,Adam有时候太激进。

5.2 聚类塌缩怎么破

塌缩的表现是:大部分像素被分到一两个簇,其他簇几乎空着。这通常是因为平衡正则权重太小,或者簇中心初始化不好。

解决办法:第一,加大平衡正则权重,从0.1加到0.5甚至1.0试试;第二,换更好的初始化,用K-means++在第一个batch上跑一次;第三,检查特征是不是退化了,比如所有特征都趋同,那说明网络没学到东西,需要检查主干和预训练权重。

提示:有个简单粗暴的办法是,在训练早期强制每个簇至少分配到一定比例的像素,不满足就重新初始化那个簇的中心。这个操作不可导,但作为工程trick很有效。

5.3 边界分割不精细

无监督分割的边界通常比监督分割糊,因为缺少像素级监督信号。改善方法有几个:一是提高特征图分辨率,比如用空洞卷积或者上采样;二是在损失里加边界感知项,比如对特征梯度大的地方加权;三是后处理,用条件随机场(CRF)或者导向滤波做边界细化。

我试过加CRF后处理,边界确实锐利一些,但计算开销大,而且参数不好调。后来改用简单的导向滤波,效果够用,速度快很多。

5.4 不同数据集上表现差异大

这篇论文的方法在纹理丰富、物体边界清晰的数据集上表现好,比如一些自然图像数据集;但在纹理弱、物体和背景颜色接近的数据集上表现差。这是因为聚类依赖特征区分度,特征区分度又依赖图像本身的对比度。

如果你的数据集属于后者,建议先做预处理增强对比度,或者在特征空间做白化,让特征分布更各向同性。另外,可以尝试多尺度特征融合,把不同层的特征拼起来,低层提供边界信息,高层提供语义信息。

问题可能原因排查方法解决手段
损失震荡温度低/学习率大观察softmax熵调高温度、降学习率
簇塌缩平衡正则弱统计各簇像素数加大正则、换初始化
边界糊特征分辨率低可视化特征图空洞卷积、后处理
跨数据集差特征区分度低对比特征分布预处理、多尺度融合

6. 这套方法还能怎么扩展

读完论文并复现之后,我觉得这套可微分聚类的框架不止能用在分割上。任何需要"从特征结构里自动发现类别"的任务,都可以套这个思路。比如视频里的动作分割,可以把时序特征做聚类;比如点云分割,可以把点特征做聚类;甚至在一些非视觉任务里,只要你能定义特征和距离,就能用。

另一个扩展方向是把软聚类和对比学习结合。对比学习里的正负样本对是人工构造的,而软聚类可以自动发现哪些样本应该靠近、哪些应该远离。这两者结合,可能能减少对数据增强策略的依赖。

还有一个方向是动态调整簇数。论文里簇数是固定的,但真实数据里类别数可能未知或者变化。可以引入一个非参数化的聚类方法,让簇数随数据自适应增减。这个方向有一些后续工作在做,但还没看到特别成熟的方案。

我个人在实际操作中的体会是,这套方法的上限取决于特征质量,而特征质量又取决于主干网络和数据本身。所以与其在聚类层上反复调参,不如先把主干和数据预处理做扎实。聚类层是锦上添花,不是雪中送炭。另外,温度退火策略和簇中心动量这两个超参,对结果影响比想象中大,值得多花时间调。最后分享一个小技巧:训练时定期保存软分配的可视化图,不用等训练完,中途就能发现很多问题,比只看损失曲线直观得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询