本地代码大模型评测实战(五):公平对比的5个陷阱

模型评测方法论:公平对比的5个陷阱

系列目录
篇1: 模型选型
篇2: 评测框架
篇3: 数据挖掘的13个发现
篇4: 8个坑和1个崩溃
篇5: 公平对比的5个陷阱 ← 当前

你以为在选模型,其实在选评测方法。方法论的偏差,比模型之间的差距更大。


榜单第一名,真的最好吗?

打开任何一个模型排行榜,你看到的是一列数字:通过率、准确率、得分。数字越大,模型越好。选最高的那个,下单。

这个逻辑看起来无懈可击,但它藏着一个致命假设:所有数字都是在同一条赛道上跑出来的。

事实恰恰相反。同一个模型,在不同的评测设置下,通过率可以相差7个百分点以上。思维模式开不开、错误怎么处理、跑几次取哪个值、题目有没有泄露——每一个你没注意到的变量,都在悄悄扭曲那个"最终得分"。

这篇是系列的最后一篇。前面四篇我们做了工具、跑了数据、排了名次。现在该退后一步,看看这些名次到底有多大意义。


陷阱1:思维模式 vs 非思维模式

是什么

有些模型支持"思维模式"(thinking mode)——在生成最终回答之前,先在内部做一轮推理链。Bonsai、ThinkingCap 属于这一类。另一些模型直接输出答案,没有中间推理步骤,比如 Qwen3-Coder、Gemma4。

这两种模式产生的输出,性质完全不同。思维模式的模型会把推理过程写进<think>标签里,然后再给最终答案。非思维模型一步到位。

为什么危险

当你看到"Bonsai 48%,Qwen3-Coder 22%",直觉告诉你 Bonsai 强了一倍多。但这两个数字根本不在同一条赛道上。Bonsai 有额外的推理时间——它相当于先打了一遍草稿再交卷,而 Qwen3-Coder 是直接写答案。

这不是模型能力的差距,是比赛规则的差距。

实际案例

在我们的50题基准测试中,Qwen3-Coder(无思维模式)通过率22%,Bonsai(有思维模式)通过率48%。差距26个百分点,看起来是显著优势。

但如果把 Qwen3-Coder 也开启思维模式(如果它支持的话),或者把 Bonsai 的思维模式关掉,这个差距很可能会大幅缩小——甚至反转。我们没有做这个对照实验,这就是问题所在:没有对照的比较,数字毫无意义。

怎么避免

三条路,选一条走到底:

  1. 全开思维模式:所有被测模型都开启 thinking(前提是它们都支持)。代价是推理时间变长,token 消耗翻倍。
  2. 全不开思维模式:所有模型都用直接输出模式。这测的是"裸"推理能力,更接近实际部署中对速度敏感的场景。
  3. 分开报告:思维模式一组,非思维模式一组,两组各自排名,不交叉比较。

最忌讳的是混着来——有些开有些不开,然后放一张表里比高低。那张表的排名,取决于谁开了 thinking,不取决于谁更强。


陷阱2:错误处理不一致

是什么

评测过程中会出现各种错误:模型超时(timeout)、网络断开(connection reset)、API 返回 500、输出格式不对无法解析。这些错误的性质不同——超时可能是模型太慢,网络错误可能是基础设施问题——但它们都会导致"这道题没有结果"。

问题在于:没有结果的题,算通过还是算失败?

为什么危险

如果从分母里剔除(只算"有结果的题"),通过率会被高估。如果不剔除(算作失败),通过率会被低估。两种处理方式之间的差距,可能比模型之间的差距还大。

更麻烦的是,不同模型的错误数量差异巨大。基础设施更稳定的模型(错误少)看起来通过率更高,但这可能跟模型能力无关——它只是跑得更顺而已。

实际案例

Sonnet 在我们的测试中产生了40个超时错误。如果把这些错误从分母中剔除,通过率是45.3%。如果算作失败,通过率跌到37.9%。

7.4个百分点。

这个差距比 Sonnet 和排名相邻模型之间的差距还大。换句话说,"怎么处理错误"这个决定,比"选哪个模型"这个决定更有影响力。

Bonsai 的情况不同——它主要是17个网络错误,不是超时。网络错误更明显是基础设施问题,而超时更可能反映模型本身的速度。把这两种错误一刀切地同等处理,或者一刀切地同等剔除,都是不公平的。

怎么避免

同时报告两个数字:

  • 严格通过率:所有错误算作失败。分母 = 总题目数。
  • 宽松通过率:错误从分母剔除。分母 = 有结果的题目数。
  • 附带错误明细:每种错误类型(timeout / connection / 500 / parse error)各有多少个。

让读者自己判断。你的工作是提供足够的信息,不是替读者做决定。


陷阱3:Run-to-Run 方差

是什么

同一个模型,同一套题目,同一种评测设置,跑两次——通过率不一定一样。

这不是 bug。语言模型在生成时有随机性(temperature、采样策略),加上评测环境的微小差异(网络延迟、API 路由),每次运行的结果会有波动。

为什么危险

50题的基准测试,每道题占2%的权重。如果两次运行之间有5-6道题的结果不同,通过率就会波动4-12个百分点。这个幅度足够改变排名。

你在排行榜上看到的"Bonsai 排第二",可能只是某一次运行碰巧多对了几道题。换一次运行,它可能排第四。

实际案例

Bonsai 在50题基准上跑了两次。第一次48%(24/50),第二次44%(22/50)。两次之间有6道题的结果不同——3道从对变错,3道从错变对。

12%的翻转率。在4个百分点的差距里,你分不清哪些是模型的真实能力差异,哪些是随机噪声。

这就引出一个尴尬的问题:如果 Bonsai 某次跑出48%,你报告48%;另一次跑出44%,你报告44——两个数字都"正确",但给读者的印象完全不同。

怎么避免

  • 增大样本量:50题的方差太大。316题可以把置信区间从 ±14% 收窄到 ±5.5%(详见陷阱5)。如果条件允许,1414题的 LiveCodeBench 可以把区间压到 ±2.6%。
  • 多次运行取均值:跑3-5次,报告均值和标准差。如果3次运行分别是48%、44%、46%,均值46%比任何单次都更可靠。
  • 报告置信区间:不要只写"通过率48%“,要写"通过率48%(95% CI: 34%-62%)”。后者诚实地告诉读者:这个数字有 ±14% 的不确定性。

陷阱4:数据泄露

是什么

大语言模型的训练数据是一个黑箱。你不知道它在训练时见过哪些代码、哪些题目、哪些评测基准。如果某个模型的训练数据里包含了你正在用来评测的题目——那它不是在"解题",它是在"背答案"。

为什么危险

数据泄露导致通过率虚高,而且你很难发现。模型在"见过的题"上通过率天然更高,在"没见过的题"上通过率更低。如果你的评测集和训练数据有重叠,整体通过率就不能代表模型的真实推理能力。

这个问题对开源模型尤其严重——因为开源模型的训练数据有时会公开,你可以检查。闭源模型(Sonnet、GPT-4)你根本无从得知。

实际案例

Qwen3.6-27B 在316题上跑出59.5%的通过率,比 Bonsai 的50.5%高了6个百分点。看起来 Qwen3.6 是更强的模型。

但 Qwen 系列模型的训练数据中很可能包含大量 GitHub 代码和竞赛题目。如果这316题中有一部分在 Qwen3.6 的训练集中出现过——哪怕只出现过10%-15%——就足以解释这6%的差距。

我们没有做污染检测,所以这个差距是真实的能力差还是数据泄露的红利,不得而知。

怎么避免

  • 用时间切分的题目:LiveCodeBench 按时间窗口组织题目。用模型发布日期之后的题目,可以大幅降低泄露风险。
  • 检查泄露信号:比较模型在"可能见过"和"几乎不可能见过"的题目上的通过率差异。如果差异显著,说明可能存在泄露。
  • 公开评测集的陷阱:HumanEval、MBPP 这些经典基准已经被各种论文引用了无数次,几乎所有新模型的训练数据都可能包含它们。用这些基准评测出来的"高分",参考价值越来越低。

陷阱5:样本量与统计显著性

是什么

统计学的基本事实:样本量越小,结论越不确定。50道题的评测,每道题2%的权重——一道题的翻转就能改变排名。316道题,每道题0.32%的权重——需要翻转很多道题才能改变结论。

但很多评测报告(包括本系列前面的文章)用的是50题的小样本。这意味着所有的排名和差距,都带着很大的不确定性。

为什么危险

50题时,Bonsai 排第2(48%)。316题时,Bonsai 还是排第2(50.5%)。排名稳定——但差距变了。50题时它比第3名高4%,316题时差距可能缩小到2%,也可能扩大到8%。

如果你基于50题的数据写了一篇"Bonsai 比 X 强4%"的结论,这个结论的可靠性很低。95%置信区间可能覆盖了0——也就是说,你不能排除"Bonsai 和 X 一样强"的可能性。

实际案例

具体算一下。假设模型真实通过率是50%:

样本量标准误95% 置信区间区间宽度
50题7.07%36.1% - 63.9%±13.9%
316题2.81%44.5% - 55.5%±5.5%
1414题1.33%47.4% - 52.6%±2.6%

50题的置信区间宽度是 ±13.9%。两个模型的真实通过率如果差5个百分点,在50题的样本上你根本分不出来——置信区间完全重叠。

316题把区间收窄到 ±5.5%,开始有分辨力了。1414题进一步收窄到 ±2.6%,这时候5个百分点的差距才真正"显著"。

怎么避免

  • 报告置信区间:这应该是标配,但大多数评测不报告。读者看到"48%“和"44%”,不知道这4%的差距是否有意义。
  • 用 McNemar 检验做配对比较:不要比较两个模型的绝对通过率,而是看"模型A对了但B错了"的题有多少,反过来有多少。这个配对检验比独立样本检验更敏感。
  • 样本量优先:如果只能选一个改进,选增大样本量。从50题到316题,可靠性提升约6倍(方差缩小到1/6)。这不是线性提升,是质变。

一张图看清决策路径

面对"我要比较两个模型"这个任务,下图展示了你应该走的检查路径:

只有1轮

>= 3轮

你要比较两个模型?

思维模式相同?

陷阱1: 统一思维模式
全开 / 全不开 / 分开报告

错误处理方式一致?

陷阱2: 同时报告
严格通过率 + 宽松通过率

跑了几轮?

陷阱3: 多次运行
报告均值和标准差

评测集时间
在模型发布之后?

陷阱4: 检查泄露
用时间切分的题目

样本量 >= 200?

陷阱5: 增大样本量
报告置信区间

可以公平比较
报告CI + 配对检验

重新设计评测


样本量 vs 置信度:一张图说明为什么要多跑题

1414题 — 可靠

通过率 55%

95% CI: 52.4% - 57.6%

区间宽度: ±2.6%
可以区分 55% 和 52%

316题 — 开始有分辨力

通过率 50.5%

95% CI: 48% - 59%

区间宽度: ±5.5%
可以区分 53% 和 47%

50题 — 看不清

通过率 48%

95% CI: 34% - 62%

区间宽度: ±13.9%
无法区分 48% 和 44%


合格评测的四个条件

走完这五个陷阱,一个"合格的评测"应该满足什么条件?

可复现。冻结评测样本(题目列表、版本号)、记录所有模型配置(temperature、max_tokens、system prompt)、公开评测脚本。任何人拿到你的配置,应该能跑出一模一样的数字。如果别人复现不了,你的结果就不是"事实",是"声明"。

公平。所有模型在同一组规则下比赛——统一的思维模式、统一的错误处理、统一的评测环境。任何模型之间的差异条件,都需要在报告中明确标注,而不是藏在脚注里。

有统计意义。样本量足够大,报告置信区间,做配对检验。50题的评测可以作为初步探索,但不应该作为选型依据。316题是基本门槛。1414题的 LiveCodeBench 是目前最可靠的选项。

诚实。报告不确定性,不只报好看的数字。如果你的评测有局限性(样本小、题目可能泄露、没做对照实验),明说。读者需要的是信息,不是安慰。


写在最后

这个系列从工具搭建开始,经过数据收集、结果分析、排名讨论,最后落到方法论。回头看,最重要的发现不是"哪个模型最强"——而是"怎么评测才不算骗自己"。

一个残酷的事实:大多数公开的模型评测,都不满足上面四个条件中的至少两个。思维模式混着比、错误处理藏着掖着、50题就敢排座次、从不提置信区间。这些评测不是在误导读者——它们的作者往往也不知道自己踩了哪些坑。

如果你从这个系列只带走一件事,应该是这句:

评测方法论的偏差,比模型之间的差距更大。

在你宣布"模型A比模型B强5%"之前,先确认这5%不是你的评测方法制造出来的幻觉。