Qwen2.5 数学评测全流程指南:基于 unilm 仓库 qwen25math 评测套件的环境搭建、模型评估与源码原理解析
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
导读
本篇文章围绕 unilm 仓库中 qwen25math 评测套件 展开,系统讲解 Qwen2.5-Math-Instruct / Qwen2-Math-Instruct 系列模型在数学基准上的完整评测流程:从依赖安装、环境校验到一键化评估脚本,再到答案解析、程序执行与数学等价判定等底层原理。读完本文,你将能够独立复现 Qwen 数学模型的评测实验,理解每一行命令背后的源码机制,并能将这套评测逻辑复用到其他数学大模型的横向对比中。该评测套件在 PFPO(Process-Feedback Preference Optimization,过程反馈偏好优化)项目中被复用为核心后处理与打分模块,是验证数学推理模型能力的标准化工具。
环境安装与依赖准备
安装步骤与版本要点
按照 README 的说明,评测环境需要依次完成四步安装:
cd latex2sympy pip install -e . cd .. pip install -r requirements.txt pip install vllm==0.5.1 --no-build-isolation pip install transformers==4.42.3各步骤的作用与注意事项如下:
- latex2sympy:评测链路中数学表达式解析(LaTeX → SymPy)的关键依赖,需以可编辑模式安装。该库在 grader.py 与 parser.py 中均有直接引用(
from latex2sympy2 import latex2sympy),用于将模型输出的 LaTeX 公式转换为可计算的符号表达式。 - requirements.txt:仓库提供了完整的依赖清单,见 requirements.txt,核心依赖如下:
| 依赖包 | 用途 | 备注 |
|---|---|---|
| vllm | 高吞吐推理引擎 | 评测默认推理后端 |
| tqdm / datasets / torch | 进度、数据加载与张量计算 | 基础运行库 |
| transformers | 模型与分词器加载 | 需配合版本4.42.3 |
| python_dateutil | 日期计算 | PythonExecutor 日期运行时使用 |
| flash_attn | Flash Attention 加速 | 可选加速项 |
| sympy==1.12 | 符号运算 | 数学等价判定核心 |
| antlr4-python3-runtime==4.11.1 | LaTeX 语法解析 | 必须与 sympy 版本兼容 |
| word2number | 英文数字转阿拉伯数字 | 答案清洗用 |
| Pebble | 多进程池 | 并行评测打分 |
| timeout-decorator | 超时控制 | 代码执行保护 |
- vllm==0.5.1:README 明确要求固定版本并加
--no-build-isolation参数,避免构建隔离导致的依赖冲突。vllm 在 math_eval.py 中通过LLM与SamplingParams提供批量生成能力。 - transformers==4.42.3:与 vllm 0.5.1 配套的分词器版本,评测中用于加载 Qwen 系列模型与构造 Chat 模板(详见后文
apply_chat_template机制)。
环境校验小实验
安装完成后,可通过 grader.py 内置的自测函数验证数学等价判定是否正常工作:
python grader.py # 运行 _test_math_equal python parser.py # 运行 _test_extract_answer_test_math_equal中预设了math_equal("x+1", "x+2n+1", timeout=True)等多组对照用例,若全部按预期输出布尔结果,则说明 latex2sympy、sympy 与 antlr4 运行时版本兼容无误。
一键评估 Qwen 数学模型
支持的模型系列与命令模板
README 给出了 Qwen2.5 与 Qwen2 两大系列、六个规格模型的评估命令,统一通过sh/eval.sh脚本驱动,核心参数为提示词类型(PROMPT_TYPE)与模型路径(MODEL_NAME_OR_PATH):
# Qwen2.5-Math-Instruct Series(建议使用 qwen25-math-cot 提示词) PROMPT_TYPE="qwen25-math-cot" export CUDA_VISIBLE_DEVICES="0" MODEL_NAME_OR_PATH="Qwen/Qwen2.5-Math-1.5B-Instruct" bash sh/eval.sh $PROMPT_TYPE $MODEL_NAME_OR_PATH| 模型规格 | 显卡分配(CUDA_VISIBLE_DEVICES) | 适用提示词类型 |
|---|---|---|
| Qwen2.5-Math-1.5B-Instruct | 单卡0 | qwen25-math-cot |
| Qwen2.5-Math-7B-Instruct | 单卡0 | qwen25-math-cot |
| Qwen2.5-Math-72B-Instruct | 四卡0,1,2,3 | qwen25-math-cot |
| Qwen2-Math-1.5B-Instruct | 单卡0 | qwen-boxed |
| Qwen2-Math-7B-Instruct | 单卡0 | qwen-boxed |
| Qwen2-Math-72B-Instruct | 四卡0,1,2,3 | qwen-boxed |
说明:
MODEL_NAME_OR_PATH既可以是 Hugging Face 模型标识(如Qwen/Qwen2.5-Math-1.5B-Instruct),也可以是本地权重路径;72B 大模型需将CUDA_VISIBLE_DEVICES扩展为多卡编号列表,供 vllm 做张量并行切分。
两种提示词模板的差异
qwen25-math-cot与qwen-boxed分别对应 Qwen2.5 与 Qwen2 两代模型的官方推理风格,其模板定义在 utils.py 的PROMPT_TEMPLATES字典中:
- qwen25-math-cot(utils.py):系统消息为
Please reason step by step, and put your final answer within \boxed{}.,采用 ChatML 格式(<|im_start|>/<|im_end|>),要求模型逐步推理并用\boxed{}包裹最终答案。 - qwen-boxed(utils.py):同样为 ChatML 格式,但系统提示为通用 assistant 描述,
\boxed{}要求被并入用户消息尾部。
二者都会触发 math_eval.py 中的stop_token_ids=[151645, 151643](对应 Qwen2/2.5 的<|im_end|>与<|endoftext|>特殊 token),确保生成在正确位置截断。
评测主入口参数全解
eval.sh最终调用评测主程序 math_eval.py,其parse_args(math_eval.py)暴露了全部可调参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
--data_names | gsm8k,math | 评测数据集,逗号分隔可同时跑多个 |
--data_dir | ./data | 数据存放目录 |
--model_name_or_path | gpt-4 | 待评测模型路径或标识 |
--output_dir | ./output | 结果输出目录 |
--prompt_type | tool-integrated | 提示词模板类型 |
--split | test | 数据集划分 |
--num_test_sample | -1 | 采样条数,-1 表示全量 |
--seed | 0 | 随机种子 |
--start/--end | 0/-1 | 样本区间切片 |
--temperature | 0 | 采样温度,0 为贪心解码 |
--n_sampling | 1 | 每个问题采样次数(用于 pass@k / maj@k) |
--top_p | 1 | 核采样参数(温度非 0 时生效) |
--max_tokens_per_call | 2048 | 单次生成最大 token 数 |
--shuffle | False | 是否随机打乱样本 |
--use_vllm | False | 是否启用 vllm 推理后端 |
--save_outputs | False | 是否保存预测结果 jsonl |
--overwrite | False | 是否覆盖已处理样本 |
--use_safetensors | False | 是否用 safetensors 加载权重 |
--num_shots | 0 | Few-shot 示例数,0 为 zero-shot |
--apply_chat_template | False | 是否应用 Chat 模板 |
--pipeline_parallel_size | 1 | 流水线并行度 |
--adapt_few_shot | False | 多选题用 few-shot、其余 zero-shot |
两个关键联动逻辑值得注意:
top_p强制约束:当temperature == 0时,代码自动将top_p置为 1(vllm 贪心解码要求),见 math_eval.py。- 断点续跑:
prepare_data会扫描输出目录中同前缀的 jsonl 并去重,processed_idxs之外的样本才会重新推理(math_eval.py),评测中断后可无缝续跑。
数据加载与持久化
数据由 data_loader.py 的load_data统一管理:
- 优先读取
data_dir/<data_name>/<split>.jsonl本地缓存; - 缓存不存在时,通过
datasets库从 Hugging Face 拉取(如competition_math、gsm8k、ChilleD/SVAMP、EleutherAI/asdiv、hails/mmlu_no_train等),并自动to_json落盘缓存; - mawps 由 singleeq / singleop / addsub / multiarith 四个子任务合并而来;
- 所有样本统一补充
idx字段并按 idx 排序。
模型加载与多轮工具式推理
setup(math_eval.py)根据CUDA_VISIBLE_DEVICES自动计算 vllm 的tensor_parallel_size与pipeline_parallel_size,并加载 Chat 分词器。核心推理循环(math_eval.py)采用最多 4 轮(max_func_call=4)的"推理-写码-执行-反馈"迭代:
- 首轮构造完整 prompt(含 few-shot 示例与系统模板);
- vllm 或 HF 后端批量生成,按
stop_words截断(["</s>", "<|im_end>|", "<|endoftext>|"]及针对各 prompt_type 的附加词); - 若输出包含
\boxed{}或未以```结尾则视为解答结束;否则从中抽取 Python 程序(extract_program); - 程序交由
PythonExecutor执行,执行结果以\n```output\n...\n```\n形式回填进对话,进入下一轮; - 达到最大调用轮数时追加
Reach max function call limit.结束迭代。
这种"写代码 + 看执行反馈"的迭代范式对应 README 提及的 tool-integrated / PAL 类提示词,prompt_type == "pal"时还会把执行结果用\boxed{...}包裹(math_eval.py)。
结果解析与打分原理
答案抽取:extract_answer 与 strip_string
模型输出是自由文本,必须从中提取可比较的"规范答案"。这一过程由 parser.py 完成:
extract_answer(parser.py)按优先级识别答案形态:final answer is $...$(minerva 风格)→\boxed{...}→the answer is/final answer is/答案是(中文)→ 兜底取最后一个数字(use_last_number=True时);strip_string(parser.py)做深度规范化:去除\left/\right、统一\frac/\dfrac/\tfrac、bmatrix→pmatrix、移除单位词表(unit_texts,主要来自 MathQA)、百分号、美元符号、\text{}包裹,英文数字转阿拉伯数字(word2number),修正a/b为\frac{a}{b}等;parse_ground_truth(parser.py)按data_name区分真实答案的解析方式:MATH/minerva 从solution抽取、GSM8K 按####切分、SVAMP 取Equation/Answer字段、mmlu_stem 取 ABCD 索引、tabmwp 按 ans_type 转换数值(分数/千分位/百分比)等。
数学等价判定:math_equal 与符号化简
grader.py 实现了严格的数学等价判定函数math_equal(grader.py),判定"预测 == 参考"成立需满足以下任一条件:
- 字符串完全一致(忽略大小写);
- 选择题答案:参考为 A–E 时走
choice_answer_clean归一化; - 数值相等:双方可转 float 时,
include_percentage=True会同时比较参考/100、参考、参考*100三种形态,容忍相对误差rel_tol=1e-4(numeric_equal); - 符号相等:通过
symbolic_equal依次尝试parse_latex/parse_expr/latex2sympy解析,再做直接相等、simplify(a-b)==0、方程两侧之差、数值近似(N())与矩阵逐元素比较; - 特殊结构:
pmatrix矩阵、区间[a,b]/(a,b)、单侧x=...等式等均递归判定; - 超时保护:
timeout=True时通过多进程call_with_timeout限制符号化简在 1 秒内完成,防止复杂表达式卡死评测。
evaluate(evaluate.py)将全部(idx, pred, gt)三元组交给 Pebble 进程池(ProcessPool(max_workers=1))并行判定,单样本 3 秒超时,最终输出acc(首列均值)与按type聚合的type_acc细分精度。
Python 程序执行器
python_executor.py 提供安全的代码执行能力:
GenericRuntime用受限exec执行程序,检测到input(即抛异常,防止交互式阻塞;DateRuntime/ColorObjectRuntime分别注入 datetime 与自定义 dict 运行时,适配日期类与颜色类题目;PythonExecutor.execute支持四种取答案方式:get_answer_from_stdout(捕获 print 输出)、answer_symbol(读全局变量)、answer_expr(求值表达式)、或执行末行表达式;结果统一做pickle序列化校验并truncate(400)截断;- 执行带 5 秒默认超时(
timeout_length),超时返回("", "Timeout Error")。
轨迹解析:text_to_trajectory
trajectory.py 实现"推理文本 ↔ 结构化轨迹"的互转:将交错出现的```python程序块与```output输出块解析为[{"role": "rationale"|"program"|"output", "content": ...}]序列;extract_program还能在程序执行失败时仅保留 import 行、合并多次修正后的程序、剔除调试用print,还原出可运行代码。
评测套件在 PFPO 项目中的工程化复用
qwen25math 评测逻辑并非孤立工具,而是深度嵌入了 PFPO 的训练-评测闭环:
- qwen25_math_callback.py:作为
OpenAICallBack子类,在 vllm 推理产出后立即调用extract_answer+strip_string清洗预测,list类型响应自动做多数投票(majority_voting_predict)得到sc_pred;打分阶段用线程池并发调用math_equal,最终输出acc、pass@k、maj@k及按data_topic细分的主题精度(qwen25_math_callback.py)。 - PFPO/README.md:明确建议采用 sympy 方式做更精确的评测,并给出了独立打分脚本的调用方式:
python scripts/math_scale/qwen25math_style_eval_v2.0.py --input_file $prediction_file_path - 数据集侧,PFPO 的
conf/api与conf/exp下大量 yaml 配置引用该评测管线,配合 vllm 推理脚本(vllm_inference.py、vllm_inference_dp.py)形成"批量推理 → 数学打分 → 偏好训练"的标准工作流。
常见问题与调参建议
| 场景 | 建议 |
|---|---|
| 复现 README 原始评测 | 严格按 README 安装vllm==0.5.1+transformers==4.42.3,使用对应系列的 PROMPT_TYPE |
| 追求更高精度判定 | 保持timeout=True符号化简,并确保sympy==1.12与antlr4-python3-runtime==4.11.1版本匹配 |
| 大批量采样评测 | 设--n_sampling 4并配合--save_outputs,从 metrics 中读取pass@k与maj@k |
| 评测中断续跑 | 保持--output_dir不变且不设--overwrite,脚本自动跳过已处理 idx |
| 多卡大模型 | 将全部 GPU 编号写入CUDA_VISIBLE_DEVICES,vllm 自动做张量并行 |
| 结果异常(如大量超时) | 检查evaluate返回的timeout_samples与empty_samples字段,定位空预测或符号化简卡死样本 |
总结
qwen25math 评测套件以 README 为入口,提供了一条"环境安装 → 一键评估 → 结果解析"的完整链路:上层由sh/eval.sh与 math_eval.py 驱动多轮工具式推理,中层由 python_executor.py 与 trajectory.py 负责代码执行与轨迹还原,底层由 parser.py 与 grader.py 完成答案抽取与数学等价判定。这套设计既保证了 Qwen 数学模型评测结果的可复现性与公平性,也被 PFPO 项目无缝复用于过程反馈偏好优化的数据生成与训练评估环节,是数学推理模型研发流程中值得直接借鉴的标准化评测基建。
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考