不均衡:采样还是加权
长尾类 CE 训练会被 head 类主导——class-weight、focal loss 和 oversampling 要一起看 per-class recall,别只盯 overall acc。

1. accuracy 96%,稀有缺陷 recall 8%
工业缺陷检测,head 类「正常」占 95% 样本。plain CE 训到 overall acc 96%,但 rare 缺陷 recall 8%——线上漏检比误检贵。overall acc 被 majority dominate,macro-F1 和 per-class recall 才是验收面。向业务汇报只贴 acc 会掩盖关键类失败,SOP 应要求 rare 类 recall 下限与 confusion matrix 存档。
2. 两条杠杆:采样 vs 损失
WeightedRandomSampler——训练分布偏向小类:
counts = np.bincount(train_labels)
weights = 1.0 / counts[train_labels]
sampler = torch.utils.data.WeightedRandomSampler(
weights, num_samples=len(weights), replacement=True)
loader = DataLoader(dataset, batch_size=32, sampler=sampler)Weighted CE——不改采样,改梯度权重:
w = torch.tensor(1.0 / counts, dtype=torch.float32)
criterion = nn.CrossEntropyLoss(weight=w)Cui effective number:weight_c = (1-\beta)/(1-\beta^{n_c}),。与 sampler 二选一先试,别叠太狠——叠加常 loss 震荡且难归因。先试 inverse freq weight,再试 sampler,记录哪条路径在 val 真实分布上 rare recall 升而 macro-F1 不崩。
3. eval 必须用真实分布
train 用 oversampling 可以,val/test 用真实分布——别 weighted sampler 进 val。report confusion matrix + macro-F1;业务常盯 rare 类 recall@固定 precision。val 曲线若用采样分布,会与线上 FP/FN 完全脱节。test 集只跑一次,选 checkpoint 靠 val 真实分布 metric。
4. focal loss 何时上
小类极 rare、easy negative 主导梯度时,focal down-weight 易样本。与 class weight 叠加易震荡——先 weighted CE 或 sampler 单变量 ablation。focal 不替代表层 capacity 或数据增广。γ 过大时 loss 曲面变陡,小 batch 训练不稳。
5. 采样与 BN 的交互
WeightedRandomSampler 改变 batch 内类分布,BatchNorm 统计偏离真实部署——小 batch + 强采样时考虑 SyncBN、GroupNorm 或 frozen BN。对比 sampler on/off 的 val(真实分布)曲线,而不是只看 train loss。冻结 BN backbone + 只训 head 是工业检测常见组合,与强采样兼容更好。
6. 数据增广与少数类
少数类 overfit 常因 增广不足 而非 sampler 不够。对 rare 类加强 augment 与 copy-paste,再调 weight——否则 sampler 只是把同几张图刷更狠。hard example mining 进 train 集比无限加 weight 更健康。类别合并(把极 rare 并到「其他」)有时是产品决策,不是纯算法问题。
7. 失败模式
| 现象 | 原因 |
|---|---|
| 小类 overfit | sampler 过重 |
| loss 震荡 | weight 过大 |
| val 与 deploy 脱节 | eval 分布错 |
8. 验收
macro-F1 与 rare 类 recall 相对 plain CE 有明确增益。confusion matrix 目视小类行。train weighted / eval natural 写进 config。val best → test 一次。上线前用真实线速 clip 抽检 FP/FN。
9. 案例:双杠杆叠加震荡
某线同时 WeightedRandomSampler + 5× class weight,train loss 震荡、val rare recall 无升。去掉 sampler 只留 mild weight 后 rare recall 从 8% 到 19%,macro-F1 持平。教训:单变量;工业长尾先 weight 再 sampler,别抄论文组合拳。
10. 与 cost-sensitive 业务对齐
漏检代价 asymmetric 时,class weight 应按 业务 cost 设,不是简单 inverse freq。稀有类 weight 过大导致 FP 升,要 jointly 看 rare recall 与 overall FP 预算。与产品定 operating point:在 val 真实分布上画 cost curve,选 threshold 或 weight,而不是 chase macro-F1 单指标。
11. 长尾数据的版本管理
新增 rare 类样本时,class count 与 weight 向量长度变——旧 checkpoint 不能 silent load。dataset manifest 版本与 weight yaml 绑定;train 脚本启动 assert len(weight)==num_classes。copy-paste 增广 rare 图要防 duplicate 泄漏进 val。open-set 长尾里「其他」类 merge 后 weight 向量要重算,不能留旧维度 silent broadcast。report 给业务时同时给 majority 与 minority 的 precision/recall,避免只展示 headline acc。semi-supervised 伪标签会改变 effective 类分布,weighted sampler 与 pseudo label 同开时 val 必须仍用真实标签。cost matrix 非对称时,macro-F1 可能与业务 cost 不一致,以 cost 为准选 weight。Class merge 后重新统计 counts 再生成 weight 向量,禁止手工改长度。Long-tail 比赛常用 balanced val 误导——工业验收坚持 real-world val 分布,比赛 metric 仅作参考。Rare 类样本新增后重新跑 weight 统计脚本,禁止手工改 yaml 一个数而不改 counts。
12. 案例:双杠杆 loss 炸
缺陷检测同时 10× weight + WeightedRandomSampler,train loss NaN;留 inverse freq weight 单杠杆后 rare recall 12→21%,macro-F1 持平。SOP:长尾先试 weight 或 sampler;focal 第三顺位。每次改杠杆 val 用真实分布报 per-class 表。Head 类 downsample 有时比 upweight rare 更稳——视 FP 预算而定,不是永远加 weight。Confusion matrix 存档进 release artifact,便于与线上 FP 报告对照。Semi-supervised 伪标签改变 effective 分布时重新评估 weight,禁止 set-and-forget。Oversample 小类时 duplicate 进 val 是 leak——split 在 augment 前按 image id 做。Business cost matrix 非对角项非零时,weighted CE 系数要按 cost 行归一,不是 raw inverse freq。Val 上 rare 类 precision 太低时降 weight 或减采样,而不是只 chase recall。Release notes 附 per-class 表,便于与线上 FP 报告对照。Bootstrap 估 rare recall 置信区间,单次 val 差 2 pt 不 claim 显著。Copy-paste rare 增广要检查与 val 的 image id disjoint。Rare 类 FN 代价高时 acceptable FP 上升要产品 sign-off,不是工程师单方面加 weight。
不均衡不是调一个 magic weight——采样改分布、损失改梯度,验收必须 per-class。
相关
也可以看看
- ·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