微调之后最常见的争论是「到底变好没有」。这场争论之所以吵不清,是因为大多数人只报一个总分。 一个总分涨了,可能某几类题集体崩了,也可能只是改了口径。 这一节把评测拆成四步:先定口径、再分维度跑分、然后对着丢分最多的地方改一处、最后重跑。
上一节训完了模型,这一节判断它行不行。 40 课 图解机器学习 里讲的是准确率、召回这些通用指标, 这一节讲的是生成任务的评测为什么比分类任务难——输出是一段话,不是一个标签。
一、三种评测,各能回答一个问题
自动指标最常见:困惑度、BLEU、ROUGE。 它们便宜、可复现,但和人判的相关性弱——两句话字面重合度高,读起来可能完全不是一回事。 代码判分适合有硬约束的任务:格式对不对、长度超没超、关键点提没提。 这一类最该先做,因为它零成本、零争议,而且能覆盖大部分业务要求。 人工盲评是最后一关:把两个版本的答案打乱顺序、隐去来源,让评委选哪个更好。 贵,但只有它能回答「能不能用」。
三者不是替代关系。合理的分工是:代码判分守底线、自动指标看趋势、人工盲评定去留。
二、先定口径,再跑分
演示里定了四个维度:以「结论:」开头、不超过六十字、把关键点都提到、不含套话。 四条都能用代码判,所以分数是跑出来的,不是看出来的。 这四项是本课自己定的口径,不是行业标准。换一个业务, 维度就该换——但「先定口径再跑分」这个顺序不能换。反过来做,就是先看分数再编理由。 每个维度只给一分,看着粗糙,好处是解释得清:丢分丢在哪一列,一眼就能看见。
口径要写进文件,跟代码一起版本管理。不写下来的口径,两周后你自己都会记错。
三、分维度看,别只看总分
演示里基座模型十道题得 11 分,微调后 30 分,看着是大胜。 但拆开看:格式从丢 10 道变成丢 0 道,套话也是从 10 到 0,而简洁从丢 9 道变成丢 10 道。 这就是真实微调里最常见的副作用:你把一样东西训死了,另一样被挤掉。 这个模型为了守住「结论:」这个格式,把话说长了。 最危险的不是「平均分不涨」,是「平均分涨了、某几类题集体崩了」。 总分把这个信号平均掉了,分维度才能看见。
所以评测表至少要三列:总分、各维度得分、每道题的明细。只留总分的评测表,等于没有。
四、优化:一次只改一处
看哪一列丢分最多,就改那一处,其他什么都不动,然后重跑。 演示里改的是长度上限,从六十放到九十,分数从 30 到 40。 一次改五处,下一轮分数变了你也不知道是哪一处起的作用——这是调参最常见的浪费。 改动的顺序有讲究:先怀疑数据,再怀疑超参,然后是解码参数,最后才动提示。 数据的问题改超参改不出来,超参的问题改提示更不行。
还有一条界线要划清:改评测口径能让分数变好看,不能让模型变好。把长度上限从六十放到九十是妥协, 真要短,得回训练数据里把「答案长度」这一条训出来。
五、动手 Demo:十道题,两个版本,四个维度打分
十道业务题,两个模型版本(一个是「基座」的替身,一个是「微调后」的替身),按四个维度逐题判分。 分数全由代码算,没有人工。 两个替身都是脚本里写死的规则,不是真模型——它们模拟的是「基座爱铺垫、 微调守格式但啰嗦」这个典型现象。要看的是评测流程,不是这两个替身的智商。
DIMS = [u'格式', u'简洁', u'覆盖', u'去套话']
def score(q, a):
s = []
s.append(a.startswith(u'结论:')) # 格式
s.append(len(a) <= 60) # 简洁
s.append(all(k in a for k in KEY[q])) # 覆盖
s.append(not any(w in a for w in BAD)) # 去套话
return sum(s), s
tot_a = sum(score(q, base_model(q))[0] for q in QS)
tot_b = sum(score(q, tuned_model(q))[0] for q in QS)
# 按维度数丢分:哪一列丢得多,就改哪一处
miss = [sum(1 for q in QS if not score(q, tuned_model(q))[1][i])
for i in range(4)]
实跑输出:
--------------------------------------------------------------------
十道题,两个版本,四个维度打分
--------------------------------------------------------------------
① 评分标准先定死
--------------------------------------------------------------------
| 维度 | 怎么判 | 分 |
|---|---|:---:|
| 格式 | 以「结论:」开头 | 1 分 |
| 简洁 | 不超过六十个字 | 1 分 |
| 覆盖 | 把给定的关键点都提到 | 1 分 |
| 去套话 | 不含「总的来说」这类 | 1 分 |
四个维度都能用代码判,所以打分是跑出来的,不是看出来的。
! 这四项是本课自己定的口径,不是行业标准。
换一个业务,维度就该换——但「先定口径再跑分」这个顺序不能换。
② 基座模型那一版
--------------------------------------------------------------------
| 题目 | 得分 | 格式/简洁/覆盖/去套话 |
|---|:---:|---:|
| 把「图纸已更新请查收」改正式 | 1 | ✗✗✓✗ |
| 这三条待办排个序:报价单、验 | 1 | ✗✗✓✗ |
| 一句话说明这个月为什么落后 | 1 | ✗✗✓✗ |
| 把会议记录提炼成三条结论 | 1 | ✗✗✓✗ |
| 客户问为什么涨价,怎么回 | 1 | ✗✗✓✗ |
| 现场发现图纸与实物不符,怎么 | 1 | ✗✗✓✗ |
| 把这段进度说明写得更短 | 2 | ✗✓✓✗ |
| 给甲方写一句催款的话 | 1 | ✗✗✓✗ |
| 列出下周现场要盯的三件事 | 1 | ✗✗✓✗ |
| 解释一下为什么要留工期余量 | 1 | ✗✗✓✗ |
十道题合计 11 分,满分 40。
四列里最常见的是「简洁」和「去套话」两个叉——基座模型爱铺垫、爱总结。
! 这不是它笨。
预训练语料里「关于这个问题,我们需要从多个角度来看」这类话太多了,它学到的就是这种文风。
③ 微调之后那一版
--------------------------------------------------------------------
| 题目 | 得分 | 格式/简洁/覆盖/去套话 |
|---|:---:|---:|
| 把「图纸已更新请查收」改正式 | 3 | ✓✗✓✓ |
| 这三条待办排个序:报价单、验 | 3 | ✓✗✓✓ |
| 一句话说明这个月为什么落后 | 3 | ✓✗✓✓ |
| 把会议记录提炼成三条结论 | 3 | ✓✗✓✓ |
| 客户问为什么涨价,怎么回 | 3 | ✓✗✓✓ |
| 现场发现图纸与实物不符,怎么 | 3 | ✓✗✓✓ |
| 把这段进度说明写得更短 | 3 | ✓✗✓✓ |
| 给甲方写一句催款的话 | 3 | ✓✗✓✓ |
| 列出下周现场要盯的三件事 | 3 | ✓✗✓✓ |
| 解释一下为什么要留工期余量 | 3 | ✓✗✓✓ |
合计 30 分,比基座高 19 分。
格式与套话这两处治住了,但仔细看右边四列——有一列反而比以前差。
! 这就是真实微调里最常见的副作用:你把一样东西训死了,另一样会被挤掉。
④ 按维度数丢分,别只看总分
--------------------------------------------------------------------
| 维度 | 基座丢分 | 微调后丢分 | 变化 |
|---|---|---|---|
| 格式 | 10 / 10 | 0 / 10 | 好了 10 道 |
| 简洁 | 9 / 10 | 10 / 10 | 差了 1 道 |
| 覆盖 | 0 / 10 | 0 / 10 | 没变 |
| 去套话 | 10 / 10 | 0 / 10 | 好了 10 道 |
格式从丢 10 道变成丢 0 道,套话从丢 10 道变成丢 0 道——这两处是真治好了。
但简洁从丢 9 道变成丢 10 道,反而更差。它为了守住格式,把话说长了。
! 真实项目里最危险的不是「平均分不涨」,是「平均分涨了,某几类题集体崩了」。
所以评测必须分维度看,不能只看一个总数。
⑤ 对症下药:只改一处,再跑
--------------------------------------------------------------------
丢得最多的那一列是「简洁」,原因是句子尾巴太长。
只改一处:把长度上限从六十字放到九十字,其他什么都不动。
从 30 分变成 40 分。改动只有一处,就是上一轮丢分最多的那一列。
! 这就是「对症下药」:看哪一项丢分就改哪一项,不要一次改五处。
一次改五处,下一轮分数变了你也不知道是哪一处起的作用。
! 放到九十是妥协,不是最优——真要短,得回训练数据里把「答案长度」这一条训出来,
而不是在评测时改判分口径。改口径能让分数变好看,不能让模型变好。
①先把口径定死:四个维度、每个一分、每条都能用代码判。 这四项是本课自己定的,不是行业标准——换个业务,维度就该换。 ②是基座那一版,十道题合计 11 分。 四列里最常见的是「简洁」和「去套话」两个叉:基座模型爱铺垫、爱总结。 这不是它笨,是预训练语料里这种文风太多了。 ③是微调之后的版本,30 分。 格式和套话这两处治住了,但右边四列里有一列反而比以前差——为了守住「结论:」,它把话说长了。 ④就是这一节的核心方法:按维度数丢分。格式 10→0、去套话 10→0,这两处真治好了;简洁 9→10,反而更差。 总分涨了 19 分,但有一列在退。 ⑤只改一处:把长度上限从六十放到九十,30 分变 40 分。 改动只有一处,就是上一轮丢分最多的那一列——这样你才知道分数变化是哪来的。 最后那句要记住:放到九十是妥协。 真要短,得回训练数据里把「答案长度」训出来,而不是在评测时改判分口径。 改口径能让分数变好看,不能让模型变好。
30 秒实验
- 给
DIMS加第五列「不编造」:出现具体数字但题目里没给的,判零分。 重跑两个版本,看这一列谁丢得多。 - 把「简洁」的上限从 60 改成 30,重跑。两个版本的分数各掉多少? 掉得多的那个,说明它的啰嗦是普遍现象还是个例?
- 把
tuned_model里的答案顺序打乱再跑,总分应该不变。 如果变了,说明你的判分里有位置依赖——那是口径的漏洞。
常见误区
- 只报一个总分。总分涨了 19 分听起来很好,但同一张表里有一列从 9 丢变成 10 丢。 不看分维度,这个退化会一路带到线上。
- 用测试集调参。调一轮看一次分数,调到满意为止——这不是优化,是把测试集变成了训练集。 分数会涨,上线会掉。
- 把改口径当成优化。放宽字数、放宽格式,分数立刻好看,模型一点没变。 口径改动要单独记录,否则三个月后没人说得清分数是怎么涨上来的。
自测三问(点开对答案)
1. 为什么 BLEU、ROUGE 这类自动指标不够用? —— 它们量的是字面重合度,和「读起来对不对、能不能用」相关性弱。 两句话字面几乎不重合但意思一样,分数很低;反之抄半句原话、后半句胡说,分数很高。 2. 「平均分涨了,某几类题集体崩了」为什么最危险? —— 因为它被平均数掩盖了。上线之后崩的是那一类题,而你的评测表上一片绿,根本不会去查。 所以要按维度、按题型分开统计。 3. 为什么强调「一次只改一处」? —— 为了归因。五处一起改,分数变了你也不知道是哪一处起的作用,下一轮还是瞎改。 一次一处,虽然慢,但每一轮都攒下一条确定的知识。模型验完,这一章只剩收尾三件事:存下来、发出去、跑快点。下一节一件一件做。
- ☐ (本篇完,下一篇 3.5 模型保存、模型部署和推理加速)
相关笔记
- 40 课 图解机器学习:准确率、召回与评测口径
- 38 课 AI 训练师手册:人工评测与评分表设计
- 大模型的评测:评测任务与评测方法
- 🦙 Llama 大模型实践 · 索引