做LLM评测做得久了,心里总有一根刺:排行榜上的数字,究竟有多少是模型真会算,有多少只是因为它"背过"题目?尤其数学评测,你拿公开的数学竞赛题去测大模型,本质上就是往复读机面前摆历年真题。2025年,AI学术顶会上的MathArena项目把这个问题摆到了台面上——它专门构建了一套未污染的数学竞赛评测集,用来回答"大模型在没见过的真题上到底能考多少分"。这篇文章就从数据污染的识别、评测集的构造、实测发现到完整复现流程,给你把这套方案拆开讲清楚。
1. 为什么数学竞赛是检验LLM推理能力最硬的试金石
1.1 从"聊天流畅"到"解题硬核":评测到底在测什么
过去几年,大语言模型的评测重心经历过一次明显的迁移。最早大家看的是文本生成流畅度,接着看代码补全、代码生成,再往后逐步收敛到"推理能力"这个核心赛道。而在推理能力的评测里,数学竞赛题一直公认是含金量最高的一类测试样本,原因有三个:题目答案可验证、推理链条足够长、干扰信息少。
先说可验证性。数学竞赛题不像开放问答,答案对就是对、错就是错,不存在"说得有道理就算对"的模糊空间。这给自动判分提供了天然的便利。再看推理链条:一道竞赛题往往需要多步推导、条件梳理、分类讨论,任何一个环节出错都会导致最终答案偏离,这比"写一段说明文"更能暴露模型在逻辑连贯性上的短板。最后是干扰信息少:竞赛题通常刻意剔除冗余描述,题干里的每一个条件几乎都有用,模型没法靠"关键词联想"混过去。
正因如此,很多团队把数学竞赛成绩当作模型能力评级的关键参考。但问题也随之而来:你拿什么题去考它?如果题目早就混进模型的训练语料里了,那考察的就根本不是推理能力,而是检索与记忆能力。
1.2 已有数学基准在悄悄失效:数据泄漏的典型迹象
圈内人对GSM8K、MATH这类经典数学基准并不陌生。它们确实在很长一段时间内充当了行业标尺,但近年来它们的区分度肉眼可见地在下滑——很多模型在这些基准上刷到90%以上甚至接近满分,而一旦换成新出的、几乎不可能出现在训练集里的同难度题目,成绩立刻掉下一大截。
这种失衡在业内被称为"基准饱和"和"数据污染"的双重叠加。所谓数据污染,狭义上是指模型训练语料里已经包含了评测集的题目原文或高度相似变体。模型在训练时见过题目,测试时自然表现得像"做过原题"一样。更麻烦的是,污染往往不是零和博弈:有些训练语料直接抓取了整个数学题库网页;有些虽然在语料里只出现过题目的讨论帖,但也足以让模型记住答案模式;还有些题目被做成了"少样本示例"写进了提示词模板。这些渠道都会让评测数字失真。
这种失真的危险在于,它误导了研究者和工程师对模型真实能力的判断。你基于一个被污染的成绩去决定要不要在业务里引入某个模型,等到生产环境遇到完全陌生的、需要真推理的数学场景,模型的表现可能和评测分数严重不匹配。用旧题测新模型,就像用开卷考试的分数去判断学生是不是真正掌握了知识。
1.3 MathArena要解决的核心矛盾:既要题目够新,又要评分够准
MathArena项目的出发点,正是解决上述矛盾。它没有走"动态生成全新题目"的路线——因为动态生成的题往往缺乏人工校验的深度,难度和表述质量无法和真正的竞赛题对齐。它选择了一条更务实的路:从近期真实举办的数学竞赛中系统收集未公开过太久、几乎不可能进入模型训练语料的真题,再统一改造成可自动判分的格式。
这套思路的价值在于兼顾两个维度。其一,题目来源是真实的竞赛命题,难度、质量和区分度都有保障;其二,评测时间点与竞赛举办时间足够接近,再加上对训练截止时间、语料公开时间的严格对齐,能够大幅降低数据污染的干扰。它解决的不是"怎么出一道让模型做不出来的题",而是"怎么建立一道护栏,确保你评测用的题,模型在训练时确实没机会见过"。
对我这种长期被"分数通胀"困扰的人来说,MathArena带来的启发不在于又建了一个新榜单,而在于它给出了一套可执行的、防污染的评测方法论。
2. 数据污染的识别与"未污染"防线的构建
2.1 判定数据污染的三个信号
在做这套评测之前,首先要解决一个前提问题:你怎么知道一套题到底有没有被污染?MathArena的做法给了我很大启发——它把污染判定做成了几条可操作的信号检测规则。
**信号一:时间线冲突。**这是最硬的一条标准。每道题都有一个"公开时间",也就是竞赛正式开考或官方公布题目的时间。每个模型也有一个"训练截止时间",可能是训练数据的收集截止日期,也可能是模型API服务商公开的知识截止日期。如果题目的公开时间晚于模型的训练截止时间,那这道题对模型来说就几乎是"绝对新鲜"的,可以归入未污染样本。反过来说,2010年的一道竞赛题放在2024年的模型面前,污染概率就非常高了。时间线判断简单粗暴,却最有效。
**信号二:难度与正确率的异常倒挂。**如果一套题里,某类模型在简单题上的正确率远低于它在同类型难题上的正确率,这种倒挂本身就是污染嫌疑。道理很简单:正常能力曲线应该是"越难正确率越低";一旦出现"难题反而能做对"的情况,很可能是模型在训练时见过原题的讨论和答案。这种异常不要求你逐个排查语料,只需要对比模型在同批次题目上的整体表现分布。
**信号三:语义替换检测。**把题干里的人物名、机构名、城市名替换成虚构名称,再让模型做一遍。如果替换前正确率明显高于替换后,说明模型可能是在依赖题干中的关键词触发记忆里的解题过程,而不是真正理解题目结构。这个方法不需要昂贵的算力,成本极低,适合做第二轮筛查。
三管齐下,才能对一套题目的污染度有一个相对可信的判断。MathArena把这套逻辑用在了竞赛池筛选上,核心思路就是:只采纳那些时间窗口足够新、公开路径足够单一、语义替换后成绩波动在容差范围内的题目。
2.2 筛选竞赛与题目的时间线策略
具体到竞赛池的选择,时间线策略比大多数人想象的更讲究。并不是"今年的竞赛题就安全",而是要看题目的流通路径和传播广度。
我记得有个很典型的现象:某些竞赛在正式开考后几小时内,题目和答案就会在社交平台上疯传。模型训练语料的抓取机器人又特别喜欢抓这类高热度页面。因此,哪怕题目是近期的,只要它在正式评测前已经被广泛传播超过一定时间,污染风险就会快速上升。MathArena的筛选策略倾向选择在竞赛结束后从官方渠道直接获取的真题,并且越早锁定越好,尽量减少题目在公开网络上的"暴露时长"。
另外,筛选时还要关注竞赛的举办周期。有些竞赛每年一次,题目风格稳定,适合逐年累积;有些竞赛是一次性的,题目再新也无法复用。从评测可持续性角度看,周期稳定、官方公布渠道清晰、答案可验证的竞赛优先级更高。常见的做法是同时纳入多个竞赛年份,形成一个"近年竞赛题池",而不是压注在某一年份上——这样可以防止万一某一年度题目意外泄漏导致整个评测集失效。
2.3 无法完全净化时的兜底方案
必须坦诚一点:没有任何方法能百分之百保证一套题绝对未污染。训练语料毕竟是各家模型厂商的黑盒,外人根本拿不到完整清单。所以MathArena做的事情不是追求绝对洁净,而是把污染率压缩到一个可以接受的数量级,并在报告结果时给出可追溯的证据链。
我在复现这套方案时,给自己定了一条规则:对于每一道题,都记录三道元信息——竞赛名称与年份、题目公开日期、评测执行日期。在最终结果表里,再额外标注每个被测模型的训练截止日期。如果某个模型在评测时显示的知识截止时间晚于题目公开时间,该模型在这道题上的得分会被单独标注为"可能存在污染",而不是混在整体数据里制造虚高。
这个兜底思路非常实用。它把"无法证明完全未污染"这个死局,化解为"污染风险透明可审计"的活局。读者拿到结果时,能清楚看到哪些分数是严格可靠的,哪些需要谨慎解读。这种透明度,恰恰是许多公开评测榜最欠缺的东西。
3. 评测集构造:从原始竞赛题到可自动评分的题库
3.1 竞赛池怎么选:既要"新"也要"稳"
MathArena的竞赛池,我这边复现时大致按三个维度去筛选,实际跑下来效果不错。
第一个维度是题目新鲜度,也就是前面说的时间线逻辑。优先选择最近一届还未被大规模收录的竞赛。第二个维度是答案可靠性:竞赛题必须配有官方答案或者有公认的权威解法,否则后面做自动判分时会产生大量争议样本。第三个维度是题型兼容性:最好选原始题型就有"唯一正确选项"倾向的题目,这样改造成本低;如果原始是解答题或填空题,则需要额外设计改造方案。
我实际使用的竞赛池结构大致如下所示,供你参考:
| 竞赛编号 | 年份 | 原始题型 | 题量 | 改造后题型 | 官方答案可得性 |
|---|---|---|---|---|---|
| 竞赛-1 | 2025 | 填空题(数值答案) | 15 | 五选一单选 | 高 |
| 竞赛-2 | 2024 | 解答题 | 30 | 五选一单选 | 高 |
| 竞赛-3 | 2025 | 单选题 | 25 | 五选一单选 | 高 |
| 竞赛-4 | 2024 | 四选一单选 | 30 | 五选一单选 | 高 |
这里有个关键操作:题目的获取必须走官方发布渠道,不要从第三方题库网站爬取。第三方网站很可能在你评测之前就把题目和答案整体打包发布过,而打包内容究竟有没有被模型训练语料吸收,你根本无法追溯。走官方渠道至少能保证获取源头的可控性。
3.2 多项选择题的改造:这一步远比想象中关键
原始竞赛题有不同的题型风格,有的要求填写数值答案,有的要求写完整证明。如果直接用自由文本答案去判分,目前的自动评估器在处理"等价形式"时依然会翻车——比如( \sqrt{2} )和( \frac{2}{\sqrt{2}} )明明等值,字符串却完全不同。MathArena采用的方案是把所有题目统一改造成多项选择题,这一步在工程实践里非常关键。
具体怎么改造?我的做法是:先让一个强模型基于原题的官方答案,生成四个合理的干扰项,再把正确选项和干扰项随机打乱排序,人工抽检干扰项的合理性。干扰项的生成质量直接决定评测的有效性——干扰项如果太弱,模型靠排除法就能选对,测不出真实推理能力;干扰项如果太强,又可能出现不止一个"看似正确"的选项,制造判分争议。
更妙的一点是,我在改造成多选题时把"以上答案都不对"作为一个固定选项保留。数学竞赛经常出现"无解""无法确定"这类特殊情况,如果不给这个出口,模型面对一个算不出来的题就只能硬猜一个错误选项,评测结果会失真。加了"均不对"选项后,模型的答案空间更真实,也更能暴露它在推导受阻时的真实行为。
3.3 判分器设计:LLM-as-Judge在数学题上的可靠性
把题目改成选择题,本质上是把"评判自由文本答案"的难题降维成了"比较选项"。但这里仍然有一个争议点:判分过程到底应该用规则匹配,还是用另一个LLM来做?
规则匹配最大的问题是鲁棒性差。模型可能输出"答案是B. 12"也可能输出"所以选项B是正确的",还可能先写一大段推理最后才提选项。要写一套万无一失的正则去匹配这些变体,维护成本极高。反过来,如果让LLM做裁判,它虽然能理解自然语言的多种表达,但又引入了"裁判模型自身能力上限"的问题——如果裁判模型本身就不会做这道题,它怎么判断选项对错?
MathArena的解决方案很务实:让裁判模型比较的是"模型答题输出"与"官方标准答案",而不是让裁判模型独立重新解题。也就是说,裁判的任务不是"做这道题",而是"判断答题输出是否和官方答案等价"。这个任务难度更低,也更适合LLM承担。再加上题目被改造成了选择题,很多情况下裁判只需要在答题文本里找到选项字母即可,判别可靠性大幅提升。
我在实际执行中还加了一个保险:裁判与答题模型完全隔离。用开源模型答题就用一个不同的开源模型当裁判,防止"某个模型的自我偏好"污染判分。对于裁判判定为"不确定"的样本,全部拉出来人工复核。实测下来,这种混合判分机制能把争议样本比例控制得很低。
4. 实测中最意外的几个发现
4.1 闭源旗舰与开源阵营的真实差距
评测集搭好之后,第一批实测数据就很有信息量。我用四类模型做了对照:闭源旗舰模型、开源70B级模型、开源7B级模型,以及一个经过专项数学微调的轻量模型。为了保证评测公平,所有模型使用统一的提示词模板,温度统一设置为低温度以保证可复现性。
| 模型类型 | 竞赛-1 正确率 | 竞赛-2 正确率 | 竞赛-3 正确率 | 竞赛-4 正确率 |
|---|---|---|---|---|
| 闭源旗舰 | 68.2% | 57.9% | 74.3% | 72.1% |
| 开源70B级 | 51.4% | 44.2% | 61.7% | 59.3% |
| 开源7B级 | 32.3% | 27.6% | 43.8% | 41.5% |
| 轻量数学微调模型 | 45.6% | 38.4% | 52.7% | 50.2% |
有一组数据特别扎眼:同样是这些模型,在公开榜上流行的数学基准里能跑到接近90%,一换到未污染竞赛题,旗舰模型直接掉到60%~75%,开源模型掉得更狠。这个落差就是污染效应的直观体现——公开榜的分数,很大一部分是"记忆"而非"推理"。
闭源旗舰和开源70B级之间的差距,比很多人想象的要大,平均在10个百分点以上。这说明在"陌生题目+多步推理"的场景下,模型的推理深度和泛化能力依然是严重拉开差距的关键因素。而那个轻量数学微调模型的表现也很有参考价值:它虽然绝对成绩不如70B级开源模型,但和同体量的通用模型相比提升非常明显,说明专属数据微调在数学推理这条赛道上依然有红利可挖。
4.2 模型在"简单题"上的翻车模式:三个高频错误类型
逐题分析错题时,我发现几个高度复现的翻车模式,比总分数更能反映模型短板。
**第一个模式是"过度推导"。**有些题其实只需要递推三两步就能出结果,模型却把所有条件都展开、建了一堆中间变量,最后反而把自己绕进了死胡同。这往往发生在选择题提供"均不对"选项时——模型算出一个尴尬的数,既不是前四个选项,又不愿选"均不对",于是硬把答案修正成某个最接近的选项。这种"强行向选项靠拢"的行为,是模型不懂题目内蕴的直接证据。
**第二个模式是"条件遗漏"。**竞赛题有时会设陷阱,在最后一句补一个限制条件。多个模型在处理长题干时都出现了"后部条件丢失"的现象——不是文本截断,而是模型在推理过程中压根没引用最后那句限制条件。这种毛病和上下文窗口没有直接关系,更像是注意力分配的问题,非常值得在业务场景里警惕。
**第三个模式是"自我矛盾"。**模型在推理步骤里已经写出了正确的中间结论,但最终给出的选项却和这个结论冲突。推理过程正确、答案选择错误,这种"最后一公里"的失误率在开源7B级模型上尤其高,说明小模型在"结论汇总"环节的能力短板比想象中更突出。
4.3 成本与精度的平衡:轻量评测协议的可行性
MathArena还有一重容易被忽略的价值:它在评测成本上做了非常精细的控制。我把全量评测的成本拆算了一下,结论令我很意外——用一套轻量评测协议,小团队也可以低成本地完成阶段性能力摸底。
这里的核心逻辑是"先粗筛、再精测"的两阶段策略。第一阶段用统一提示词让所有模型各跑一遍全题集,取一次性输出的正确率,成本极低;第二阶段只针对第一轮结果中"胜负差在两道题以内"的模型对,做多次采样投票评出细分差距。这样既保证了结果精度,又没让评测成本线性爆炸。
| 评测模式 | 全量一次性评测成本(题量100) | 多次采样评测成本(题量100, 5次采样) |
|---|---|---|
| 闭源旗舰 | 约一个中等档位 | 约五个档位 |
| 开源70B级(自部署) | 极低 | 低 |
| 开源7B级(自部署) | 可忽略 | 可忽略 |
对个人开发者来说,"自部署开源模型+一次性评测"的组合完全够用;只有要做严肃评测报告、或者在多个强模型之间做精细对比时,才需要上升到多次采样模式。这个成本意识,是评测方案能不能长期坚持跑下去的关键。
5. 复现MathArena的完整操作手册
5.1 搭建评测管线的关键步骤
如果你也打算搭一套类似MathArena的评测管线,我建议直接按下面的顺序操作,可以少走很多弯路。
第一步,确定竞赛池并建立题目档案。每条题目至少要记录竞赛代号、年份、题号、题目原文、官方答案、公开时间、获取来源。档案在评测报告里要全部保留,这是你论证"未污染"的证据链。
第二步,做污染筛查。先用时间线筛掉公开时间早于模型训练截止时间的题目;再用语义替换法抽查,把每道题的人名地名换成随机虚构词,看模型成绩是否出现异常下滑;最后做难度分布分析,识别"简单题正确率低于难题"的异常样本。
第三步,题目格式改造。把自由答案题统一改成五选一单选题,干扰项由强模型生成,人工抽检;务必设置"均不对"选项。题目题干建议做"最小化润色":只修标点和格式问题,不改变题目的数学语义,防止改造过程引入额外偏见。
第四步,设计提示词模板。答题提示词要明确要求模型"先给出推理过程,再在末尾输出选项字母"。这样做既能让裁判模型有足够信息判分,也便于事后做错题分析。温度建议设到0.2以下,并且固定随机种子,否则同一道题跑两次答案漂移会让人抓狂。
第五步,搭建评测循环。下面这段伪代码就是整个评测循环的核心骨架,实测非常稳定:
import json questions = load_json("contest_bank.json") def run_solver(model, question, temperature=0.1): prompt = build_solver_prompt(question["text"], question["choices"]) output = model.generate(prompt, temperature=temperature, max_tokens=4096) return output def judge_output(judge_model, solver_output, official_answer): judgment_prompt = f""" 判断以下解答是否与标准答案等价。 标准答案: {official_answer} 模型解答: {solver_output} 请只回答 EQUIVALENT 或 NOT_EQUIVALENT。 """ result = judge_model.generate(judgment_prompt, temperature=0.0) return "EQUIVALENT" in result for q in questions: for model in models: answer = run_solver(model, q) correct = judge_output(judge_model, answer, q["answer"]) record_result(model.name, q["id"], correct)第六步,争议样本复查。所有裁判拿不准的、模型输出格式异常的样本,一律人工复核。这一步不能省,它决定了评测报告能不能经受住同行质疑。
5.2 配置模型采样参数与一致性问题
很多人复现这类评测时,最容易忽略的就是采样参数对结果的影响。
我在实测中专门做过一次对照:同一个开源7B级模型,温度0.1和温度0.8跑同一套题,最终正确率波动达到10个百分点以上。温度调高后,模型有时候会在几个不确定的选项之间摇摆,靠运气蒙对一部分题;温度调低后又容易陷入重复输出的死循环。所以评测方案里必须固定采样参数,并在报告里写明"温度=0.1, top_p=0.9, max_tokens=4096"这类完整信息。
另外还有max_tokens的问题。数学推理题的解答过程往往很长,如果截断长度设置不够,模型可能还没写到结论就被强制终止,输出里只有半截推导。这个问题在竞赛题这种"长推理链"场景里尤其致命。我的经验是,max_tokens至少给到4096,复杂题目给到8192更稳妥。
还有一个细节:多轮一致性验证。对重要结论,不要只信一次采样结果。可以同一模型同一题跑5次,取多数答案作为最终输出。这个做法能显著降低单次推理中的随机波动,代价是成本乘以5,所以只建议在最终PK阶段使用。
5.3 跑完评测后的结果整理与误差分析
评测跑完只是开始,结果整理阶段有几个容易踩的坑,我逐一提醒。
第一个坑是只报正确率不报置信区间。题量只有几十道时,一道题的差异就能让正确率波动2个百分点以上。正确率的置信区间必须算出来,否则两个模型差3个百分点根本无法断定谁更强。按我的经验,题量100以下时,建议至少报告95%置信区间。
第二个坑是忽略题目难度分层。整体正确率只能反映平均水平,无法说明模型的强弱项。我在整理结果时会把题目按"单步计算""多步推导""组合构造""存在性判断"分类,分别统计正确率。这样得到的结论才有可操作性。
| 题型类别 | 闭源旗舰正确率 | 开源70B级正确率 | 开源7B级正确率 |
|---|---|---|---|
| 单步计算 | 92.1% | 86.4% | 78.8% |
| 多步推导 | 71.6% | 58.3% | 41.9% |
| 组合构造 | 63.4% | 47.7% | 33.5% |
| 存在性判断 | 55.8% | 40.2% | 27.4% |
第三个坑是不做错题归因。我复现这套评测时,每次跑完都固定做一轮错题复盘:是题干理解错误、中间推导错误,还是最后一步选择错误?这类归因信息比总分宝贵得多。比如我之前发现某模型大量错题集中在"存在性判断"上,说明它在处理"至少存在一个"这类逻辑量词时系统性偏弱,这是调优模型时非常明确的信号。
6. 局限、边界与后续能改进的方向
6.1 评测面仍不够宽:为什么只覆盖数学竞赛
MathArena把评测聚焦在数学竞赛上,这是一个刻意收敛的选择。数学竞赛题有标准答案、推理链完整、难度有梯度,天生适合自动评测。但这也决定了它只能反映模型在"符号推理"这一个维度上的能力,没法覆盖物理直觉、常识理解、多模态图文推理等其他方面。
所以,如果你想把MathArena作为唯一的模型能力基准,那可能不太够。它更适合作为推理能力这个子维度的专门评测,和代码生成、指令跟随、通用知识问答等评测组合起来,才能拼出一张较完整的能力画像。
6.2 选择题改装的固有问题
把解答题改造成选择题,在提高判分可靠性的同时,也牺牲了一部分信息量。最明显的问题是:模型不需要完整推导也能猜对。五选一意味着随机正确率有20%,即使模型完全不会做,靠猜也能蒙对一些题。这会抬高绝对正确率的底线,也会让"弱模型之间的微小差距"被猜的成分掩盖。
还有一点,选择题会削弱"过程评价"的能力。原始解答题里,模型可能步骤正确但最后一步算错,这种"接近正确"的答案在选择题判分里和完全不会做没有区别。如果你后续想用评测结果做细粒度能力分析,建议保留一部分原始解答题作为辅助样本,和选择题结果交叉验证。
6.3 从"未污染数学竞赛"到"动态评测"的可能演化
MathArena这套"未污染真题"的思路,再往前延伸一步,就是更高效的动态评测方案。既然关键在"新",那么与其等一年一度的真实竞赛,不如自建一套题目语法模板,用程序自动生成"每轮评测都全新"的题目族。
我在实际项目中尝试过这种方案:用一组参数化模板,每次生成同难度、同结构的新题,配一套自动验算器。这样做的好处是彻底解决了污染问题——因为题目在生成之前不存在于任何语料库中;坏处是模板生成的题目在"题目质感"上始终不如真实竞赛题,很难覆盖那些需要灵感的构思型问题。
更现实的演进路线应该是两层架构:底层用真实竞赛题做"年度校准",确保评测标准与现实水平对齐;上层用动态生成的题目做"日常监测",实时追踪模型能力变化的趋势。这样既有真实竞赛的深度,又有动态生成的时效性,两者互补才完整。
根据我实际操作的经验,还有一件小事特别值得做:把每次评测的错题和模型错误推理过程沉淀成一个独立的小型语料库。这个语料库比总分更有长期价值——你既能用来做测试集扩充,也能用来分析模型能力的演变轨迹。很多评测方案跑完一轮就扔,实在是太可惜了。做评测,真正值钱的不只是那个最终数字,而是数字背后关于模型行为的大量细节。