FixMatch 伪标签 conf 阈值
无标数据用模型伪标签自训练能涨点,但错误标签会以高置信度固化——confidence threshold、EMA teacher 和 curated ratio 是防 collapse 的关键。

1. 高置信伪标签也会固化错误
工业检测里常见局面:产线换型后只有几百张有标图,历史库存里却躺着几万张同场景无标图。团队很自然想到 pseudo-label——把模型预测直接当 label 继续训。曲线前几 epoch 看似收敛,某类 recall 却在 val 上永久塌掉:早期模型对背景纹理错得自信,这些错误会以高置信度写进 unlabeled loss,后续再也拉不回来。根因不是「无标数据没用」,而是噪声标签进入梯度的速率没有被约束。
FixMatch 用两道闸:weak augmentation 产伪标签,strong augmentation 学伪标签;只有置信度超过阈值的样本才计入 unlabeled loss。阈值宁缺毋滥——coverage 下降换 pseudo 纯度。这与监督学习里「label noise 不可逆」的教训一致:半监督的上限由伪标签质量决定,不由 unlabeled 数量决定。现场调参时最常争论「阈值降到 0.8 能多收多少 unlabeled」——答案必须连同 per-class recall 一起看;总 mAP 涨而某类消失,说明噪声标签已固化进决策边界。
2. FixMatch 骨架与超参接线
有标分支照常 cross-entropy;无标分支在 torch.no_grad() 里用 weak aug 预测,mask 高 conf 样本,strong aug 上算 CE:
loss_l = F.cross_entropy(model(weak_aug(x_l)), y_l)
with torch.no_grad():
probs = F.softmax(model(weak_aug(x_u)), dim=1)
conf, pseudo = probs.max(dim=1)
mask = conf > 0.95
loss_u = (F.cross_entropy(
model(strong_aug(x_u)), pseudo, reduction='none') * mask).mean()
loss = loss_l + lambda_u * loss_u # lambda_u 从 0 ramp 到 1conf > 0.95 是 FixMatch 论文默认值,工程上常在 0.95–0.99 之间扫。strong aug 用 RandAugment/CutOut,迫使模型学语义而非 memorization weak view。lambda_u 前几个 epoch 从 0 线性增到目标值——early noise 若主导,整网会被带偏;ramp 长度通常与总 epoch 的 5–10% 对齐。
Mean Teacher 变体:teacher 权重是 student 的 EMA,teacher 产伪标签,student 学;一致性正则 权重同样 ramp。FixMatch 通常比 plain pseudo 稳,因为「高 conf + 强增广」两道闸;Mean Teacher 适合 batch 小、增广弱的场景,但 teacher 更新 lag 时需调 EMA beta。
3. 失败模式与路线取舍
阈值过低:错误标签以高置信度固化,某类 precision 崩而总 acc 仍高——最危险的 silent failure。阈值过高:unlabeled 利用率极低,mask 比例长期低于 5%,等于只用有标数据,算力浪费在无标 forward 上。label 域与 unlabeled 域差大(不同产线、不同传感器):伪标签噪声结构性偏高,应先做 domain 对齐或 curated sampling,而非盲目降阈值。
与全监督 fine-tune 比:半监督适合「标注贵、无标多、类分布相对稳」。类极度长尾且无标样本缺少数类时,伪标签往往加剧偏置——少数类在 unlabeled 里本就稀少,模型更不自信,进不了 mask,形成恶性循环。此时应优先补少数类有标样本,而非堆 unlabeled loss weight。
4. 数据划分与训练契约
有标/无标 batch 比例要固定并写进配置:labeled_batch : unlabeled_batch 常见 1:1 或 1:7。GroupSplit 按 scene_id 划分,避免同场景泄漏进 train 和 val——否则 pseudo acc 虚高。AMP 下注意 GradScaler 须在 unscale_ 后再 clip grad;NaN 回溯 LR、loss scale、augment 强度、num_classes 是否与 head 一致。CrossEntropyLoss 的 target 须为 long 型 class index,one-hot 未转 long 会 silent wrong。
5. 案例:阈值从 0.8 降到 0.6 后某类消失
某产线缺陷检测,plain pseudo 用 conf>0.8,总 mAP 涨 2pt,但 scratch 类 recall 从 0.7 掉到 0.2。抽查 pseudo label 发现 scratch 常被标成 background,且 conf>0.8 样本占 unlabeled 的 40%。改 FixMatch conf=0.95 + strong aug + lambda_u ramp 后,mask 比例降到 12%,scratch recall 回到 0.65,总 mAP 仍涨 1.5pt——牺牲 coverage 换纯度,少数类才保住。
6. 验收
- 在人工标注的 unlabeled 子集上算 pseudo label accuracy——应随训练上升,不应长期低于 random baseline。
- 对比
conf=0.95vs0.80vs 无 mask:看 coverage(mask 比例)与 val mAP 的 Pareto,不只看总 loss。 - 固定 seed,单变量改
lambda_uramp 或 strong aug 强度;val best checkpoint → test 一次,不用 test 调参。 - 监控 per-class recall:半监督最怕「多数类更好、少数类消失」的 silent collapse。
- EMA eval 权重与 training 权重对比——teacher-student 架构下 eval 应用哪套要写进 run config。
伪标签半监督的 conf 阈值和 ramp 是防 collapse 的第一道闸。改一项时固定其余变量,日志含 loss、lr、grad_norm、AMP scale,才分得清是阈值问题还是数据域问题。上线前在 hold-out 有标子集上复核 pseudo accuracy 曲线——若与 val mAP 走势背离,优先查 domain 与阈值,而非继续加大 unlabeled 权重。
相关
也可以看看
- ·16 分钟阅读
KV cache 分页与前缀复用:吞吐上去后正确性怎么验
沿 block table、前缀哈希与抢占回收拆开缓存一致性风险,说明错页复用为何表现为「偶发胡话」;用确定性前缀集、强制抢占和逐 token 对照验收。
- ·18 分钟阅读
混合精度下的梯度累积:loss 缩放、裁剪与 step 顺序
沿 autocast、GradScaler、unscale_、裁剪与 optimizer.step 的数据流说明静默错误;区分 micro-batch 平均与求和,并用等价性测试验收。
- ·9 分钟阅读
torch.compile 图断裂:先定位重编译,再谈模式选择
从 Dynamo guard、graph break 与动态形状入手,建立可复现的编译诊断和冷启动、稳态验收方法。
johan's blog