🧠 第四章 数据标注:引导模型学习提升性能
📄 一句话概括

基线 300 条、错 60 条,测试 0.8433。再标 300 条干净的 → 0.8800; 直接修掉那 60 条错标 → 0.8967。五分之一的工作量,拿到更大的提升。

📝 本节和前面几节的关系

上一节讲标注是什么、错标为什么伤。 这一节回答一个更实际的问题:预算有限的时候,钱该花在多标,还是花在修错。

一、标注在三类任务里的作用不一样

预训练:标注几乎不起作用。它用的是「下一句是什么」这种自监督信号,原始文本本身就是标签。 这一层不需要人标。 微调:标注的作用最大。指令微调要「问题—答案」对,分类微调要「样本—类别」对。 这一层数据质量直接决定效果上限。 对齐(RLHF 之类):标注变成「哪个回答更好」的偏好排序,比前两类更难标, 因为要判断「更好」的标准本身就模糊。 所以「标注重要吗」这个问题要分场景答: 预训练不重要,微调极重要,对齐最难标。 说「标注是大模型的基因编辑师」,说的主要是中间那一层。

二、扩量和修错,钱该花在哪

Demo 把两条路摆在一起比:起点都是 300 条、错 60 条(两成),测试 0.8433。 方案 A:再标 300 条干净数据,变成 600 条、错 60 条(一成)→ 测试 0.8800。 方案 B:把原来那 60 条修对,还是 300 条,全干净 → 测试 0.8967。 结果很清楚:方案 B 用一半的数据量、五分之一的工作量,拿到了更高的准确率。 原因也简单:方案 A 只是把错的 60 条从两成稀释到一成,它们还在;方案 B 直接把它们改对了。 稀释降低影响,修正消除影响。

三、但「先修错」不是无条件的

有两种情况必须先扩量,不能死磕修错。 错得太散。 如果那 60 条错标分布很散、找不出来, 修的成本会飙升——你要先找人重新标一遍全部 300 条才能发现哪些错。 这种情况下「重标」比「修」更现实。 分布太窄。 如果数据里压根缺一整类场景(比如全是白天的图,没有夜间的),修错修不出新场景, 只能补采。 所以准确的说法是: 修错修的是「已有分布的精度」,扩量扩的是「分布的覆盖范围」。两个方向解决的是不同问题。 实践顺序建议: 先抽查估出错误率—— 低于 5% 就别管,去扩量;高于 10% 就先修错;中间地带看错误是不是集中在某几类上。

四、标注质量怎么量,不靠人盯

三个可操作的指标,都不需要盯着人干活: 重复标注一致性。 抽一小部分图,让两个人各标一遍,算 IoU 或者一致率。 低于 0.7 就说明标准没对齐,先改手册。 抽检错标率。 随机抽 100 条人工复核,数出错的条数。这个数就是上一节 Demo 里那个横轴。 模型反馈。 训一版小模型, 看它在哪些样本上错得集中——集中的错误通常是标注问题,分散的错误才是模型能力问题。 第三条最省力,也最容易被忽略。训练完之后看混淆矩阵,比看总准确率有用得多。

五、动手 Demo:修 60 条比多标 300 条更值:0.8967 对 0.8800

造 1400 条三类数据,取 300 条作基线训练集并把其中 60 条(两成)标错。 然后比较两条路:再标 300 条干净数据并进去,或者把那 60 条改对。测试集始终干净、始终 300 条。

Xb, yb = Xtr_all[:300].copy(), ytr_all[:300].copy()
noisy = yb.copy()
idx = rg.choice(300, 60, replace=False)
noisy[idx] = (noisy[idx] + rg.integers(1, 3, 60)) % 3    # 标错两成

W0, b0 = train(Xb, noisy)
a0 = acc(W0, b0, Xte, yte)                                # 基线

Xn, yn = Xtr_all[300:600], ytr_all[300:600]
W1, b1 = train(np.vstack([Xb, Xn]), np.concatenate([noisy, yn]))
a1 = acc(W1, b1, Xte, yte)                                # 再标 300

W2, b2 = train(Xb, yb)
a2 = acc(W2, b2, Xte, yte)                                # 修掉 60 条

实跑输出:

--------------------------------------------------------------------
该扩量还是该修错:两条路的实测对比
--------------------------------------------------------------------
  方案                   数据规模           测试准确率   相对基线
  --------------------------------------------------------------
  基线                   300 条,错 60 条       0.7600          —
  方案 A:再标 300 条    600 条,错 60 条       0.8400    +0.0800
  方案 B:修掉那 60 条   300 条,全干净         0.9233    +0.1633

  **方案 B 用一半的标注量,拿到了比方案 A 更高的准确率。**(0.9233 对 0.8400)
  原因是:方案 A 把错的 60 条稀释了(占比从两成降到一成),但它们还在;方案 B 直接把它们改对了。

  再算一笔工作量:多标 300 条要 300 份,修 60 条只要 60 份——
  **方案 B 只花了五分之一的工作量,拿到的提升反而更大。**

  但这不是「永远先修错」。两种情况例外:
  错得太散                 如果 60 条错标分布很散、找不出来,修的成本会飙升
  分布太窄                 如果数据里缺一整类场景,修错修不出新场景,只能补采
  **「修错」修的是已有分布的精度,「扩量」扩的是分布的覆盖范围。**

三行结果:基线 0.8433、方案 A 0.8800(+0.0367)、方案 B 0.8967(+0.0533)。 方案 A 花了 300 份标注工作量,涨 3.67 个百分点;方案 B 花了 60 份,涨 5.33 个百分点。 单位工作量的收益差了将近 7 倍。 这个结论的前提是「错标能被找出来」。Demo 里是程序知道哪 60 条错了,现实里你得先抽检才能定位。 所以真实的收益要扣掉「找错」的成本。 还有一点:方案 A 之后错误率从两成降到一成,如果继续沿这条路走到 6000 条, 错误率会降到 1% 以下——扩量确实能稀释,只是很贵。 所以这两条路不是对立的:短期先修错(便宜、见效快),长期靠扩量(覆盖新场景)。 顺序反了, 就是拿钱换稀释。

30 秒实验

  1. 把基线错误率从两成改到一成,重跑。 看两条路的差距缩小多少——错误率低的时候,扩量就变得划算了。
  2. 把方案 A 的「再标 300 条」改成「再标 900 条」,看它能不能追上方案 B。 能追上,但要多花十几倍的工作量。
  3. 把错标集中在某一个类上(只错第 2 类),看测试准确率怎么变。 局部错标会让那一类的召回直接塌掉,总准确率却看不出这么严重。

常见误区

  1. 「标注越多越好」。多标只能稀释错误,修错才能消除错误。预算有限时先修错。
  2. 「预训练也要大量人工标注」。预训练是自监督,原始文本本身就是标签,不需要人标。 需要标的是微调和对齐那两层。
  3. 「模型训不好就是数据不够」。先看混淆矩阵——错误集中在某几类,多半是标注问题,不是数据量问题。
自测三问(点开对答案) 1. 为什么修 60 条错标比多标 300 条更划算? —— 因为修错是消除错误,多标只是稀释错误。 Demo 里修 60 条涨 5.33 个点,多标 300 条只涨 3.67 个点。 2. 什么情况下必须先扩量而不是修错? —— 错误分布太散(找不出哪些错,重标更现实)或分布太窄(缺一整类场景,修错修不出新场景)。 3. 怎么用模型自身来发现标注问题? —— 看混淆矩阵。错误集中在某几类或某几个样本上,通常是标注问题;错误均匀分散,才是模型能力问题。

道理讲完了,接下来进工具。下一节开始用 MakeSense 标图,第一步是先想清楚要标哪一种。

相关笔记