DivideMix:将带噪标签学习转化为半监督学习
发布时间:2026/10/19 13:35:06 锦皓数字建站

干了几轮带噪声标签的项目之后我第一次看到DivideMix这篇论文心里那种老办法总差一口气的感觉终于有了出口。之前处理标签噪声常用的思路无非是拿小损失样本当干净样本、按置信度截断、给样本重新加权。思路没错但在高噪声率下模型一旦开始把错误标签当真理截断和加权都会跟着失真。DivideMix标题里那半句话——把带噪标签学习当成半监督学习来做——当时让我眼前一亮既然标签不可信就别硬着头皮去清洗它干脆把那些不确定的样本当作无标签数据用半监督学习的机制把它们重新利用起来。这篇文章我会按照原论文的章节顺序做一次完整的翻译加解读把摘要、方法、实验、还有代码复现里真正要注意的东西全部捋一遍。适合两类人看一类是想复现DivideMix做实验的研究者或工程师另一类是只需要理解为什么噪声标签可以被半监督学习拯救的产品同学。我不会只贴翻译还会补上我在实际跑实验时踩过的坑。1. 摘要翻译与核心洞察噪声标签问题如何降维成半监督问题1.1 摘要部分逐段翻译原文摘要第一句的核心意思现有的带噪标签学习方法通常是设计一种特殊的训练策略比如修改损失函数、重新加权样本或者小心地对样本进行选择这些策略都试图纠正标签噪声带来的影响。但DivideMix换了个视角它不把带噪标签当作一个问题去修补而是直接把它当作半监督学习问题来处理。具体做法可以拆成三步。第一步用两个网络的损失分布去判断哪些样本是干净的、哪些是带噪的。它不设定一个固定的损失阈值而是对全部样本的损失做高斯混合模型GMM拟合让两个分布自己浮出来小损失分量对应干净样本大损失分量对应噪声样本。第二步对判断为带噪的样本不再使用原始标签而是根据模型预测生成新的伪标签这些伪标签和干净样本的原始标签一起构成一个看似有标签、实则混合了无标签的训练集。第三步用半监督训练框架把两类样本放在一起训练。摘要里特别强调了一个词co-divide联合划分。DivideMix不是让一个网络自己给自己划分而是两个网络各自拟合GMM把两个网络的概率平均后共同决定某个样本到底算干净还是算噪声。两个网络互相提供划分结果也互相为对方生成伪标签。摘要末尾给出了实验结论在多个公开基准上包括合成噪声和真实噪声场景DivideMix都稳定超过了当时已有的方法尤其是在高噪声率下优势更明显。论文说这验证了把带噪标签学习当作半监督学习是可行且高效的。1.2 一点解读为什么这个重构是成立的要理解这里为什么把问题降维得先想清楚带噪标签学习和半监督学习在数据结构上的对应关系。半监督学习最经典的设定是一部分样本有标签一部分样本没有标签。带噪标签学习的设定是所有样本都有标签但有一部分标签是错的。如果把错标签样本的标签作废掉它们就等价于无标签样本。于是原问题就变成了给定一个由干净样本少量但有正确标签和噪声样本大量但没有可靠标签混合而成的训练集目标是训练一个分类器。这本质上就是半监督学习。难点在于半监督学习假设我们知道哪些样本是无标签的而带噪标签学习里这个划分信息是未知的需要模型自己猜。DivideMix的聪明之处就在于先用一个简单的信号损失值做初步划分然后把划分的误差交给半监督训练框架去消化。也就是说即使某个样本被错误划分了半监督的一致性正则也能让它继续发挥训练作用不会像传统方法那样因为清洗错误而造成不可逆的影响。我把这个逻辑想明白之后再看它的方法就觉得自然多了不需要设计复杂的损失修正函数只需要把无标签样本的集合估计得足够好剩下的交给MixMatch这种成熟框架。1.3 引言中的相关工作从样本加权到样本选择原论文的引言部分回顾了两条研究路线。第一条路线是样本加权。这类方法不删除任何样本只是根据每个样本被怀疑为噪声标签的概率降低它在损失中的权重。问题在于权重本身很难估计准确而且加权后的样本依然会把错误标签的信息带入梯度只是幅度减小了并没有真正切断错误信息。第二条路线是样本选择。这类方法根据损失或置信度把一部分样本认为不可靠直接剔除或忽略掉。代表性的思路包括用小损失筛选干净样本、用课程学习的方式从易到难安排样本、以及双网络的协同教学。问题在于被剔除的噪声样本携带的信息也被浪费了。在高噪声率下干净样本可能只占很小比例全部丢弃噪声样本会让训练数据过少模型反而学不动。DivideMix的定位介于两者之间不信任的样本不用于原始标签但作为无标签样本进入训练。所以它既保证了错误标签的信号不会被直接学习又避免了资源浪费。这个定位在引言的最后一段写得很清楚噪声样本不是垃圾它们只是没有可信标签的有价值数据。2. 方法部分翻译与逐段拆解Divide阶段与Mix阶段方法名DivideMix一看就知道是两个动作的组合Divide负责划分Mix负责训练。这一章我按原论文的记号和方法细节逐部分翻译并配合我在复现时对每个设计的理解。2.1 问题设定与符号说明原论文把训练集记为 (X {(x_i, \tilde{y}i)}{i1}^n)其中 (\tilde{y}_i) 是带噪标签不一定是真实标签 (y_i)。目标是从这样的数据里学到一个分类器使得它在干净测试集上的泛化能力接近用干净标签训练的结果。在每次迭代开始模型需要对每个训练样本计算一个损失值。DivideMix在这个阶段统一使用模型预测与原始标签的交叉熵 [ L_i -\sum_{c} [\tilde{y}i c] \log p{\theta}(c | x_i) ] 这个损失值就是后续划分的唯一依据。之所以用损失而不是直接看预测概率是因为损失天然包含了模型对当前标签的确认程度标签错误且被模型识别的样本损失会明显偏高。真正实现时有一个细节损失值需要做归一化再送入GMM。原论文用min-max归一化 [ L_i^{\text{norm}} \frac{L_i - \min_j L_j}{\max_j L_j - \min_j L_j} ] 原因很实际随着训练进行损失的绝对尺度会不断下降如果不归一化某一个epoch里GMM拟合出的均值差就只对当前尺度有效换一个epoch尺度又变了。归一化后的损失尺度始终在0到1之间GMM的参数才更稳定。2.2 Divide用GMM拟合损失分布为每个样本打噪声概率这是整个方法最关键的直觉干净样本和噪声样本的损失值呈现出两种不同的分布。干净样本的损失集中在较小的值附近噪声样本由于标签不一致损失整体偏高且更分散。于是原论文用一个两分量高斯混合模型去拟合全体样本的归一化损失 [ p(L_i) \alpha_1 \mathcal{N}(L_i; \mu_1, \sigma_1) \alpha_2 \mathcal{N}(L_i; \mu_2, \sigma_2) ] 拟合完成后两个高斯分量分别对应干净集和噪声集。这里需要做一个分量顺序的约定由于整个训练过程中干净分量总体上都应当集中在更小的损失区间因此可以按照均值大小来判断哪个分量是干净分量——均值更小的分量是干净分量另一个是噪声分量。根据贝叶斯后验每个样本属于噪声分量的概率为 [ w_i P(\text{noise分量} | L_i) \frac{\alpha_{\text{noise}} \mathcal{N}(L_i; \mu_{\text{noise}}, \sigma_{\text{noise}})}{\sum_{m1}^2 \alpha_m \mathcal{N}(L_i; \mu_m, \sigma_m)} ] 然后以 (w_i 0.5) 作为阈值把样本划分为干净集和噪声集。我一开始对这种做法的疑虑是GMM太简单了吧为什么不直接设定一个卡在损失排序90%位置的分位数后来实验告诉我GMM的优势在于自适应。噪声率低时噪声分量占比小噪声率高时噪声分量占比大GMM能自动调整两个分量的混合系数和均值位置不用人工调阈值。并且GMM给出的不是一刀切而是连续的概率 (w_i)这个概率在co-divide阶段和生成伪标签阶段都用得上。2.3 两网络co-divide互相给对方划分数据集合为了解决单一模型自我确认偏差的问题DivideMix同时维护两个网络记为A和B。两个网络结构相同但初始化不同、每个batch的shuffle顺序不同因此它们犯错的方式也会有一定差异。在每个epoch开始时网络A先对全体样本计算损失并拟合GMM得到概率 (w_A)网络B也做同样的事得到 (w_B)。co-divide的核心操作是把两个概率平均 [ w \frac{w_A w_B}{2} ] 再用平均后的 (w) 去划分干净集和噪声集。为什么取平均而不是取交集或并集因为单个网络可能在某些样本上过度自信或过度怀疑取平均相当于让两个网络对分歧样本互相修正降低划分的方差。如果取交集得到的安全集很小数据利用效率低取并集噪声污染率又会上升。更重要的是训练阶段的交叉原论文和开源实现里网络A不是用自己划分的结果训练自己而是用网络B划分的结果以及网络B生成的信息来做自训练。反过来网络B用网络A的结果。这种你划分我训练、我划分你训练的方式避免了模型对自己的错误预测进行自我确认。我在复现时一度觉得这个设计有点绕但它其实就是协同教学思想的延续。单个模型最怕的情况是在早期epoch把某个错误标签当真越往后越坚信最终无法纠正。两个模型互相给对方划分即便A产生了错误偏置B的划分结果还提供了一条纠偏路径。2.4 MixMixMatch把两堆样本合并训练划分完成后数据集被分成两部分干净集 (X_L) 保留原始标签噪声集 (X_U) 不保留原始标签而是作为无标签数据参与训练。DivideMix在这里直接嫁接MixMatch的半监督训练流程因此叫Mix阶段。MixMatch做的事情可以概括为三个步骤。第一步对无标签样本做弱增强和强增强分别送入模型得到预测分布然后对多个增强视图的预测做平均得到伪标签的雏形。第二步用温度锐化让这个分布变得更尖、更自信 [ \hat{p}_u \operatorname{Softmax}\left(\frac{z_u}{T}\right) ] 其中 (T) 是锐化温度(T) 越小预测分布越接近one-hot。第三步把有标签样本和无标签样本混合起来做MixUp [ \tilde{x} \lambda x_1 (1 - \lambda) x_2,\quad \tilde{y} \lambda y_1 (1 - \lambda) y_2,\quad \lambda \sim \operatorname{Beta}(\alpha, \alpha) ]这里要注意一个细节MixMatch原本是为标准半监督设置的即所有有标签样本都可靠。而DivideMix里的有标签部分只包含划分出的干净样本因此数量更少、整体规模更波动。无标签部分既包含原始噪声样本也可能混入少量被误分的干净样本。对这少部分误分样本来说原始标签被弃用改成伪标签反而可能纠正了原来的标签错误。伪标签的生成方式在实现上有讲究。训练网络A时噪声样本的伪标签来自网络B在当前batch上的预测结果反过来亦然。如果让A自己给自己生成伪标签模型会把前几个epoch的错误判断固化下来等于把一个坏的预测当成目标去逼近。用对方的预测来生成目标等于在两个网络之间建立了一道信息隔离。2.5 完整训练循环与损失函数整个训练循环可以整理成伪代码。需要说明的是我这里的写法以原论文的开源实现为基准做了提炼如果你去看源码细节会更多但主干是一致的。# 伪代码DivideMix一个epoch的主循环 for epoch in range(total_epochs): # 1. 计算两个网络的样本损失 lossA [CE_loss(netA(x_i), y_i) for x_i, y_i in all_data] lossB [CE_loss(netB(x_i), y_i) for x_i, y_i in all_data] # 2. 归一化损失分别拟合GMM wA fit_gmm_and_get_noise_prob(lossA) # 均值小分量干净 wB fit_gmm_and_get_noise_prob(lossB) # 3. co-divide两网络概率取平均 w 0.5 * (wA wB) # 4. 按 w 0.5 划分干净集 X_L其余作为无标签集 X_U X_L, X_U divide_dataset(w) # 5. 训练阶段netA用netB的输出netB用netA的输出 for batch in mixed_batches: # 干净样本使用原始标签计算监督损失 # 噪声样本使用对方网络预测锐化生成伪标签计算一致性损失 loss_A supervised_loss(netA, labeled) lambda_u * consistency_loss(netA, unlabeled, pseudo_from_B) loss_B supervised_loss(netB, labeled) lambda_u * consistency_loss(netB, unlabeled, pseudo_from_A) update(netA, loss_A) update(netB, loss_B)损失函数整体上分为两半。有标签部分使用标准的交叉熵 [ \mathcal{L}x -\frac{1}{|B_L|} \sum{x \in B_L} \tilde{y} \log p(x) ] 无标签部分使用预测分布与伪标签分布之间的均方误差 [ \mathcal{L}u \frac{1}{|B_U|} \sum{x \in B_U} | p(x) - \hat{p}_u |^2 ] 最终损失 [ \mathcal{L} \mathcal{L}_x \lambda_u \mathcal{L}_u ] (\lambda_u) 是无监督损失的权重。原论文在实验中会针对不同噪声环境做调整通常取0到1之间的值高噪声率时适当增大。为什么无标签部分用MSE而非交叉熵因为伪标签分布本身是锐化过的soft标签并不等价于真实one-hot标签用交叉熵会强迫模型完全自信反而容易在伪标签错误时造成过度拟合。MSE则允许模型对一个样本输出相对温和的分布容错性更好。2.6 原文里容易被忽略的两个实现细节第一个是warmup阶段。模型在一开始如果没有基本判别能力损失分布是彼此重叠的GMM很难划分出有意义的分量。因此实际训练会在正式的Div-Mix循环之前先在原始带噪数据上做若干轮预训练让模型具备一个还算可以的特征表示。等损失分布拉开后再开始GMM划分。我复现时warmup的长度很敏感太短划分噪声大太长模型已经开始记忆错误标签。参考常见配置在合成噪声数据集上warmup一般设在10到30个epoch之间结合验证集表现来定。第二个是划分频率。GMM不是每个batch都重新拟合而是每个epoch结束、下一个epoch开始时一次性对全体训练样本计算损失并完成划分。也就是说一个epoch内所有batch共享同一份划分结果。如果每个batch都重新划分成本太高而且batch太小的话损失分布根本不够撑起两个高斯分量。全体样本的跨度才能让GMM拟合出稳定的两个峰。3. 实验部分翻译合成噪声、真实噪声和消融实验告诉我们什么3.1 合成噪声实验在高噪声率下依然稳原论文的实验起点是合成噪声基准即在干净数据上按照一定比例随机替换标签。常用的几档是对称噪声20%、40%、60%、80%、90%以及非对称噪声40%。所谓对称噪声是标签以相等概率被替换成其他任意类别非对称噪声则是只在容易混淆的类别间替换更接近真实世界的人工标注错误。在低噪声率20%至40%下很多方法都能取得不错的效果DivideMix的优势不算特别夸张。但随着噪声率上升到80%、90%普通方法出现明显的性能崩塌而DivideMix的准确率下降幅度要平缓得多。这说明GMM加MixMatch的组合在极高噪声率下已经不是微调有效而是结构性抗噪。我当时对这种结果的疑问是90%噪声率下干净样本只剩10%这点有标注信息够用吗实验给出的答案是够。因为半监督部分并不依赖可靠标签的数量它依赖的是大量无标签样本本身的分布信息。只要划分器能保证那10%干净样本大部分被正确划入有标签集MixMatch就能用一致性正则撬动剩余的90%样本。3.2 真实噪声实验爬下来的脏数据也能用合成噪声实验再漂亮也解决不了一个质疑真实世界的标签噪声不是完全对称的随机替换。为此原论文特意在两类真实场景上做了验证。第一类是从网络上自动爬取的图像数据标注过程非常粗糙标签噪声是自然形成的、非对称的而且类别分布极不均衡。这类数据不仅噪声率高还有些样本本身就是错图、漏图挑战比合成噪声大得多。第二类是工业界常见的大规模商品图像数据比如服装图像分类场景标注来源复杂标签错误比例较高同时类别之间视觉差异很小。实验结果显示DivideMix在真实场景下的提升幅度甚至高于合成噪声场景。我的理解是真实噪声往往不是完全随机的很多错误标签其实是近类混淆。模型在训练初期就能更好地识别这类样本的损失偏大GMM能把这种系统性的近类错误识别出来。而MixMatch的伪标签机制本质上等于允许模型反悔——原始标签一旦被判为噪声就用模型自己学到特征生成新标签正好对冲近类混淆。3.3 消融实验每个模块到底贡献了多少原论文做了系统性的消融来证明三个关键设计缺一不可。第一组是去掉GMM、退回固定阈值划分。结果显示准确率明显下降尤其在训练初期和噪声率变化时固定阈值无法同时兼顾低噪声率与高噪声率。原因前面说过损失分布是动态的GMM的自动拟合相当于一直在帮你重新校准阈值固定阈值做不到这一点。第二组是去掉co-divide只用一个网络自己划分、自己训练。这种情况下低噪声率还可以高噪声率时模型容易陷入误判的恶性循环网络先错划了一批样本然后拿错划结果去训练自己错误被逐步放大。两个网络互相划分等于在数据划分阶段引入了校验机制。第三组是去掉MixMatch退化成普通的小损失样本选择加自训练。效果也下降不少。原因是半监督部分的锐化和MixUp不仅是为了利用无标签样本还起到了正则化作用让模型对错误伪标签不那么敏感。3.4 实验设定的细节原论文的实验配置有几个地方值得单独拿出来看。优化器用的是带动量的SGD配合余弦退火学习率调度权重衰减设得不重。数据增强方面除了常见的随机裁剪和水平翻转还用了类似Cutout的遮挡增强和MixMatch原论文的增强策略保持一致。这些细节在复现时都不建议随意改动因为MixMatch对增强强度非常敏感。另外两个网络在训练过程中没有做任何显式的参数差异性约束只是靠不同的随机种子和不同的batch顺序来制造差异。这个设计看起来简单但实际效果很好。如果强行加入一个鼓励两网络预测不一致的正则项反而容易让模型刻意分化影响泛化。4. 复现DivideMix时的几个关键决策与常见弯路这一章不是论文正文的翻译而是我基于复现和改造经验做的补充。网上已经有不少开源的复现版本但你直接用的时候还是会踩到一些文档里不会写的坑。4.1 GMM拟合频率与初始化最容易被忽略的是GMM的初始化。直接调用现成的高斯混合模型工具包做拟合默认的初始化方式可能不稳定不同epoch跑出来的划分结果方差会很大。稳妥的做法是每次拟合前手动对分量的均值顺序做约束。先保证均值较小的分量是干净分量再对该分量做较充分的初始化否则偶尔会出现两个分量的标签互换导致整个epoch的划分方向反了。拟合频率上每个epoch一次是默认选择。我试过每个epoch拟合两次比如在小batch上再校正一次性能几乎没有提升反而增加了额外耗时。还有一个细节GMM是对全体训练样本的损失拟合不是对每个batch单独拟合。batch太小损失分布是锯齿状的两个高斯分量很容易拟合到同一团数据里。4.2 锐化温度与无监督损失的权重锐化温度 (T) 直接影响伪标签的置信度。(T) 太大伪标签分布太平滑模型学不到锐利的分类边界(T) 太小伪标签接近硬标签一旦错误模型会快速过拟合到错误分布。常见的范围是0.5到2之间。我自己的经验是在噪声率较高时稍微降低 (T) 可以帮助模型保持自信在噪声率较低时稍微提高 (T) 反而更稳。无监督损失权重 (\lambda_u) 也有类似的规律。太高会让模型完全跟着伪标签走忽略了有限的干净标签太低则等价于普通自训练半监督的增益被削弱。原论文在不同实验里给的并不是同一个固定值复现时最好保留这个超参数作为一个自由变量用一小部分验证集做挑选。4.3 双网络的伪标签来源为什么不能自产自销我自己改造时犯过一个错误图省事把A网络自己的预测当成无标签样本的伪标签来源。结果前几个epoch看起来很正常到了中期准确率突然掉一截。原因就是自我确认偏差被逐步放大。A网络一旦在某个类别上产生了偏置自己给自己生成目标时会对偏置视而不见最终陷入局部最优。改成从B网络拿伪标签之后问题立刻缓解。这说明DivideMix的co-train并不只是工程上的冗余而是算法层面切断错误累积的机制。如果你只想要单模型部署训练完A和B后可以直接对一个模型做测试另一套网络在推理时丢弃即可。4.4 训练稳定性的常见问题我在多个数据集上跑下来最大的不稳定因素来自warmup阶段和批次采样。warmup阶段的损失如果太大说明学习率过高GMM在第一个正式epoch就会无法收敛warmup阶段如果完全不做GMM一开始拟合出的两个分量几乎没有区分度干净集和噪声集基本是随机划分。批次采样方面有标签集和无标签集最好以固定比例混合到一个batch里。如果直接在有标签集和无标签集上分别计算损失再相加梯度更新会被两边的batch大小差异带偏。实际实现里可以在构建batch时确保有标签样本和无标签样本数量大致相等混合后进行MixUp整体走MixMatch的流程。另一个常被忽略的点是数据增强的一致性。半监督部分依赖同一样本在不同增强下的预测一致性。如果对无标签样本做太强的增强比如大面积的裁剪加上Cutout模型可能根本无法在两个视图之间保持一致的语义伪标签本身就变得不可靠。因此无标签样本的增强强度通常要低于有标签样本或者至少保持在同一量级。5. 我个人实践里的额外体会最后说一点不太容易被论文原创者写进去、但实操时很有用的经验。首先DivideMix对验证集的使用比一般方法更依赖。因为训练过程中存在划分错误和伪标签错误的双重不确定性验证集几乎是你唯一可以判断当前epoch是否健康的手段。我建议每训练几个epoch记录一次干净集和噪声集的规模变化如果干净集比例迅速下降说明模型开始把越来越多的样本判为噪声划分信号正在失效如果噪声集比例过高则要检查GMM是否出现了分量翻转。其次当你把DivideMix迁移到自己的新数据集时不要一上来就照着原论文的超参数跑。数据集类别数、噪声类型、样本总数都会影响最佳warmup长度和 (\lambda_u)。一个比较省事的策略是先在原噪声比例上跑一小组网格只调warmup、(T)、(\lambda_u) 三个参数。把这三个参数稳定住后面的性能基本就定型了。还有一个小技巧和标签分布有关。原论文在做GMM拟合前会把损失归一化到0到1之间。如果你的数据集里某些类别本身特别难学损失整体大模型公平性会受干扰。我试过在归一化前按类别做一次标准化相当于先剔除类别难易差异再划分噪声在细分类任务上会稍好一些。这属于对原方法的微调原论文里没有写但实现成本很低值得试试。关于噪声样本可能包含有价值信息这件事我现在的体会比刚读论文时深得多。很多清洗方法倾向于直接丢弃噪声样本看起来更干净实际上损失了大量数据分布信息。DivideMix给出的路径是不要把噪声样本当作垃圾而是给它们一个重新被理解的机会。伪标签这个机制虽然看起来简单但它把放弃变成了再试一次。在一个标注质量无法保证、但数据量很大的真实业务环境里这种思路比任何人工清洗规则都更符合实际。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。