评测这件事有一句不太好听的真话:你测什么,模型就长成什么样。 这一节讲评测任务有哪几类、数据集从哪来、方法有几种,以及四个绕不过去的坑。 最后用三个模型、两套题,把「在同一套题上比,等于让背题库的赢」这件事跑出来。
这是第 1 章最后一篇。 前面四节讲的是模型怎么来、怎么训, 这一节讲怎么判断它行不行——也是全书后面每讲一次「效果变好了」都要回来对账的地方。 评测驱动的迭代, 22 课 Harness 技术架构原理 里讲过。 那一节讲的是工程流程,这一节讲的是评测本身的局限。
一、评测任务分几类
第一类是知识。给一道选择题,看选对没有。 最出名的是 MMLU,五十七个学科、从初中数学到专业医学,几万道四选一。 它的好处是自动判分,坏处是选择题做得好不代表会说话。 第二类是推理。小学数学应用题(GSM8K)、竞赛题(MATH),要求给出推理过程和最终数字。 这类题最能拉开模型差距,也最容易被「背题」污染。 第三类是代码。给函数签名和说明,让模型写出实现,然后真跑一遍单元测试。 HumanEval 是一百六十四道题,指标叫 pass@1,意思是一次就过。
第四类是中文。C-Eval、CMMLU 是中文的多学科选择题。 这两套题对国内模型是必报的,因为英文榜单高的模型,中文未必好——第 7 章会讲为什么。 第五类是对话质量与安全。这一类没有标准答案,只能靠人打分或者让强模型当裁判。 Arena 那种让两个模型匿名对打、由用户投票的办法,就是在解决这一类的「没有标准答案」。
二、数据集从哪来,为什么会泄漏
公开榜单的数据集是公开的。 这意味着它一定会进训练语料——做数据的人不会特意排除,因为「多一份数据总是好的」。 于是就有了数据污染:模型在测试集上分数很高,其实是因为它训练时见过这些题。 检测的办法是拿测试题去训练语料里做 n-gram 匹配,看有没有长片段重合。 更隐蔽的一种是「间接泄漏」:题没进语料,但解题思路、同类题、答案讨论进了。 这种几乎查不出来,只能靠换新题。
所以严肃的评测都会留一份从来不公开的留出集,只在内部跑。这份数据不外流,也就不可能被训进去。
三、方法:三种口径
第一种是困惑度。不用标注,拿一份语料算「模型对下一个词有多意外」,越低越熟。 它便宜、快、可复现,但只说明熟不熟,不说明对不对。 第二种是任务准确率。给出题、判对错,最直观。它的问题是依赖标注,而且题目一旦公开就会被污染。 第三种是人工或模型当裁判。给两个回答让人选,或者让一个强模型按标准打分。 最贴近真实用途,也最贵、最难复现——同一个回答,不同人打分能差出很多。
四、四个绕不过去的坑
坑一是污染,上面说过。 坑二是提示敏感:同一道题,换个问法、加一句「请一步一步想」,分数能差十几个点。 所以报分数必须连提示模板一起报。 坑三是裁判偏差。用强模型当裁判,它会偏爱长回答、偏爱跟自己风格像的回答。 这叫位置偏差与长度偏差,论文里都量过。 坑四是饱和。榜单出了一年,头部模型全顶到九十几分,就分不出高下了。 这时候要么换更难的题,要么承认这个榜已经没用了。
四个坑合起来指向一句话:任何单一指标都可以被优化,包括被优化到失真。所以工业上报评测, 从来是一组数加一段口径说明。
五、动手 Demo:三个模型两套题,看困惑度怎么骗人
造三个模型:一个均匀瞎猜、一个真学到规律的、一个把见过的题连答案背下来的。 给两套题,各十道。第一套是训练里见过的,第二套是从没见过的。 分别算答对几道、困惑度多少,然后把两组结果摆在一起看。
# 困惑度:正确概率的几何平均的倒数
def _ppl(ps):
return math.exp(sum(-math.log(p) for p in ps) / len(ps))
# 三个模型在同一批题上给「正确答案」的概率
A_UNI = [1.0 / 50] * 10 # 均匀瞎猜
A_WITH = [0.62, 0.58, 0.66, 0.71, 0.55, 0.60, 0.68, 0.64, 0.59, 0.70]
A_MEM = [0.97, 0.96, 0.98, 0.97, 0.95, 0.96, 0.99, 0.97, 0.98, 0.96]
# 换一套没见过的题,背题库那个的概率直接塌掉
B_WITH = [0.30, 0.22, 0.44, 0.12, 0.38, 0.26, 0.35, 0.18, 0.41, 0.28]
B_MEM = [0.001] * 10
实跑输出:
--------------------------------------------------------------------
困惑度低不等于答得对:三个模型两套题
--------------------------------------------------------------------
① 三个模型,三种毛病
--------------------------------------------------------------------
| 模型 | 怎么来的 | 毛病 |
|---|---|---|
| A 均匀瞎猜 | 每个词概率都是 1/V | 没学到东西 |
| B 老实训练 | 学到的是规律,不是答案 | 没见过的只能对一半 |
| C 背题库 | 把见过的题连同答案一起背下 | 见过的全对,换一份就崩 |
词表 50 个词,所以「完全不知道」的困惑度基准线就是 50。
② 第一套题:十道训练里见过的
--------------------------------------------------------------------
| 模型 | 答对 | 困惑度 |
|---|---:|---:|
| A 均匀 | 0 / 10 | 50.00 |
| B 老实 | 10 / 10 | 1.58 |
| C 背题 | 10 / 10 | 1.03 |
A 的困惑度正好是词表大小 50——这就是「完全不知道」的基准线。
C 的困惑度低到 1.03,十道全对。光看这两个数,C 是最好的模型。
! 绝大多数「我们这个模型在某某榜单上第一」的评测,就到这一步为止。
③ 第二套题:另外十道从没见过的
--------------------------------------------------------------------
| 模型 | 答对 | 困惑度 |
|---|---:|---:|
| A 均匀 | 0 / 10 | 50.00 |
| B 老实 | 5 / 10 | 3.63 |
| C 背题 | 0 / 10 | 1000.00 |
C 还是那个 C,换一套题十道全错,困惑度从 1.03 涨到 1000.00,翻了 969 倍。
B 的困惑度只从 1.58 涨到 3.63,因为它学的是规律,换个问法还算得出来。
! 这就是评测里最经典的坑:在同一套题上比,等于让背题库的赢。真正的评测集要留一份从来不给人看的。
④ 两套题摆在一起看
--------------------------------------------------------------------
| 模型 | 见过的答对 | 见过的困惑度 | 没见过的答对 | 没见过的困惑度 |
|---|---:|---:|---:|---:|
| A 均匀 | 0 / 10 | 50.00 | 0 / 10 | 50.00 |
| B 老实 | 10 / 10 | 1.58 | 5 / 10 | 3.63 |
| C 背题 | 10 / 10 | 1.03 | 0 / 10 | 1000.00 |
两套题之间掉得最狠的是 C(从 10 道全对掉到 0),最稳的是 B(只掉一半)。
! 一个模型好不好,不看它在你手上这套题能打多少分,看它换一套题还剩下多少。
⑤ 除了困惑度还该看什么
--------------------------------------------------------------------
| 指标 | 量什么 | 盲区 |
|---|---|---|
| 困惑度 | 它对语料有多熟 | 不看对错,只看像不像 |
| 任务准确率 | 答对的比例 | 要标注,且题目会泄漏 |
| 人工偏好 | 人觉得哪个好 | 贵,但最贴近真实用途 |
| 鲁棒性 | 换个说法还对不对 | 要专门造对抗样本 |
四个指标各有一个盲区,所以工业上从来不报一个数就下结论。
! 本课后面每讲一次「效果变好了」,都会说清是哪个指标变好、另外几个有没有一起看。
第一套题上,均匀瞎猜的困惑度正好 50,因为词表就是 50 个词——这就是「完全不知道」的基准线, 任何模型超过它,说明它在这批数据上还没学到东西。 背题库的那个,困惑度 1.03、十道全对。老实训练的那个,困惑度 1.58、也十道全对。 光看这两个数,背题库的赢——绝大多数「我们这个模型在某某榜单第一」的评测,就到这一步为止。 换一套没见过的题,局面立刻翻。背题库的十道全错,困惑度从 1.03 涨到 1000,翻了九百多倍; 老实训练的那个只从 1.58 涨到 3.63,因为它学的是规律,换个问法还算得出来。 最后那张四列表最该记住: 两个模型在见过的题上打平,在没见过的题上差了整整十道。这就是为什么要留一份从来不公开的题。 还有一层:这批数字是我构造出来的,不是真模型跑出来的。构造得刻意,所以倍数夸张。 真实的污染效应没有这么戏剧化,通常是三五个点的差距——但那三五个点,恰恰决定谁排第一。
30 秒实验
- 把
B_MEM从 0.001 改成 0.02(也就是背题库的模型对新题也有一点点常识), 看困惑度从 1000 掉到多少。想想「残存的一点通用能力」在评测里值多少分。 - 把均匀模型的概率从 1/50 改成 1/60(相当于它在 60 个词的词表上瞎猜),困惑度会变成多少? 为什么这时候它的困惑度反而比基准线高?
- 自己写一套十道题,故意让其中三道跟「训练语料」一模一样,七道是新的。 然后算两个模型的分数——你会得到一条介于上表两组之间的曲线。
常见误区
- 只看一个榜单的分数就下结论。 任何单一指标都能被优化到失真,报评测必须连提示模板、样本数、判分口径一起报。
- 以为困惑度低就是好模型。把测试集背下来的模型困惑度极低,但它换一套题就崩。 困惑度量的是「熟不熟」,不是「对不对」。
- 以为公开榜单的分数可以横向比。提示不同、few-shot 数不同、判分脚本不同,分数就没有可比性。 要比就得自己重跑一遍,用同一套口径。
自测三问(点开对答案)
1. 为什么说「在同一套题上比,等于让背题库的赢」? —— 因为公开的题一定会进训练语料,见过的模型天然占便宜。 要区分「真会」和「背过」,只能换一套它没见过的题。所以严肃评测都要留一份不公开的留出集。 2. 提示敏感为什么是个问题? —— 因为它意味着分数不是模型的属性,是「模型加提示」的属性。 同一个模型,加一句「请一步一步想」能涨十几个点。 所以报分数必须报提示模板,否则两个数根本不可比。 3. 用强模型当裁判,会有什么偏差? —— 已知的有两种:偏爱长回答(长度偏差),偏爱跟自己风格接近的回答(自我偏好)。 所以做裁判评测要交换两个回答的顺序各跑一遍,再取平均,抵消位置偏差。第 1 章到此结束。下一章开始动手:把 Llama 2 的权重拉下来,先让它跑起来。
- ☐ (本篇完,下一篇 2.1 部署前的准备)
相关笔记
- 22 课 Harness 技术架构原理:评测驱动的迭代
- 40 课 图解机器学习:交叉验证与过拟合
- 🦙 Llama 大模型实践 · 索引