reasoning-from-scratch 第 3 章实战:基于 MATH-500 评估推理模型——从 \boxed 答案提取、符号等价判分到混合 LaTeX 解析器

发布时间:2026/10/13 6:18:00
reasoning-from-scratch 第 3 章实战:基于 MATH-500 评估推理模型——从 \boxed 答案提取、符号等价判分到混合 LaTeX 解析器 示例工程【免费下载链接】reasoning-from-scratchImplement a reasoning LLM in PyTorch from scratch, step by step项目地址https://gitcode.com/gh_mirrors/re/reasoning-from-scratch点击查看免费下载本篇技术指南以开源仓库 reasoning-from-scratch 的第 3 章「Evaluating Reasoning Models」为核心完整讲解如何在本项目搭建的 Qwen3-0.6B 模型上运行 MATH-500 数学评测从逐条流式评估evaluate_math500.py、批量并行评估evaluate_math500_batched.py到离线记录重算evaluate_json.py并深入剖析答案提取与符号等价评分器的源码级原理最后介绍可选的进阶方案——覆盖区间、并集、矩阵等 LaTeX 边界情况的混合解析器hybrid parser。读完本文你将能够直接复现第 3 章的 500 题评测流程理解 base 模型与 reasoning 模型的准确率差异来源并掌握如何用自定义解析器处理长尾答案格式。1. 章节代码结构主章节代码与两块附加材料第 3 章的配套代码在ch03目录下分为三块各自承担不同职责01_main-chapter-code主章节代码与习题解答。其中 ch03_main.ipynb 是章节正文配套 notebookch03_exercise-solutions.ipynb 是习题解同目录下的 math500_test.json 是 MATH-500 评测数据集共 500 条记录每条包含problem题目、solution官方解答、answer标准答案LaTeX 格式、subject学科、level难度 1–5与unique_id六个字段。02_math500-verifier-scripts命令行评测脚本共三个evaluate_math500.py单序列流式评估、evaluate_math500_batched.py生成阶段并行、更高吞吐、evaluate_json.py对已保存的 JSON/JSONL 记录重算准确率。03_advanced-parser进阶解析器实验源自仓库 issue #133 中提出的混合 LaTeX 解析器用于处理章节默认解析器容易漏判的边界情况。两个评估脚本都从reasoning_from_scratch包导入功能避免代码重复。环境安装细节参考第 2 章安装指引仓库根目录的 pyproject.toml 声明了sympy1.14.0等依赖SymPy 正是第 3 章评分器的符号等价判定依赖uv.lock锁定 PyTorch 2.10.0。2. 运行方式uv 与 python 二选一原文档明确给出两条运行路径对非uv用户只需把uv run ...py换成python ...py# 方式一原生 python python evaluate_math500.py # 方式二uv自动创建虚拟环境并按 uv.lock 安装依赖 uv run evaluate_math500.py仓库测试 test_math500_scripts.py 会对上述三个脚本逐一执行--help冒烟测试test_script_help_runs_without_import_errors确保脚本在仓库根目录下可直接运行、无导入错误这侧面验证了两条命令路径的可用性。3. 单序列流式评估evaluate_math500.py3.1 命令行参数运行uv run evaluate_math500.py --help可查看全部参数原文档完整列出如下options: -h, --help show this help message and exit --device DEVICE Device to use: auto (default) or any torch device string (e.g., cpu, cuda, cuda:0, mps). --which_model {base,reasoning} Model variant to load (default: base). --dataset_size DATASET_SIZE Number of MATH-500 examples to evaluate (default: 10). --max_new_tokens MAX_NEW_TOKENS Max new tokens to generate (default: 2048). --compile Enable torch.compile. --verbose Print per-sample correctness while evaluating.对照脚本源码 evaluate_math500.py--which_model实际还接受instruct内部映射为reasoning模型权重并关闭 thinking 段并额外支持--checkpoint_path加载自定义.pth检查点——这是为第 6 章 RL 训练产出的检查点预留的入口。--device auto时调用reasoning_from_scratch/ch02.py中的get_device()自动选择 CUDA 或其他可用设备。模型与分词器加载逻辑位于 reasoning_from_scratch/ch03.py 的load_model_and_tokenizerbase变体使用tokenizer-base.json与qwen3-0.6B-base.pthreasoning变体使用tokenizer-reasoning.json与qwen3-0.6B-reasoning.pth且分词器开启聊天模板、生成提示与 thinking 段apply_chat_template、add_generation_prompt、add_thinking三个标志。模型统一按QWEN_CONFIG_06_B配置实例化Qwen3Model。3.2 评估管线四步核心流程从源码可见单条样本的评估被拆成清晰的四步见 mini_eval_demo 与evaluate_math500_stream渲染提示render_prompt(problem)将题目套入固定模板——You are a helpful math assistant. Answer the question and write the final result on a new line as: \boxed{ANSWER} Question: {problem} Answer:模板强制模型把最终结果写在\boxed{ANSWER}中这是后续extract_final_candidate能稳定提取答案的前提。流式生成generate_text_stream_concat调用第 2 章实现的generate_text_basic_stream_cacheKV-cache 逐 token 流式解码把产生的 token 序列解码回文本。提取答案extract_final_candidate从生成文本中取出候选答案详见第 4 节。判分grade_answer(extracted, row[answer])对预测与标准答案做符号等价判定。evaluate_math500_streamreasoning_from_scratch/ch03.py会逐条处理数据集统计正确数与平均响应长度token 数并实时打印进度与 ETAeta_progress_message。每条样本生成一条 JSON 记录写入输出文件默认math500-{设备名}.jsonl如math500_base-cpu-evaluate-script.jsonl记录字段为{ index: 1, problem: Compute 1/2 1/6., gtruth_answer: 2/3, generated_text: ……\n\\boxed{2/3}, extracted: 2/3, correct: true }这种「先生成落盘、再判分」的设计让结果可复检也支撑了第 6 节evaluate_json.py的离线重算。4. 评分器源码解析提取、规范化与符号等价4.1 答案提取extract_final_candidate 与 get_last_boxedget_last_boxed(text)定位文本中最后一次出现的\boxed跳过其后空白要求紧跟着{再用括号深度计数处理嵌套花括号如\boxed{outer {inner} ok}括号不平衡或缺失时返回None。extract_final_candidate优先返回最后一个 boxed 表达式去掉外层$与空格若无 boxed 则回退fallbacknumber_then_full先用正则RE_NUMBER找最后一个数字支持分数\d/\d、小数、科学计数法仍找不到才返回整段文本。测试用例 test_ch03.py 覆盖了嵌套括号、\boxed { x^2 }带空格、多个 boxed 取最后等情形。4.2 轻量规范化normalize_textnormalize_textreasoning_from_scratch/ch03.py是一套「轻量 LaTeX 规范化」按规则依次处理处理项规则示例聊天特殊 token剥离|assistant|等RE_SPECIAL标记选择题标签c. 3→3、b: 2→2角度记号删除^{\circ}、^\circ、Unicode°文本包裹整体为\text{...}时解包数学环境删除\( \) \[ \]LaTeX 定宽微调删除\left/\right、\, \! \; \:\cdot、·、×→*\dfrac/\tfrac→\fracUnicode 上标2²→2**2SUPERSCRIPT_MAP 映射⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁽⁾根式/分式\sqrt{x}→sqrt(x)\frac{a}{b}→(a)/(b)幂符号^→**带分数1 2/3→12/3千位分隔1,234→1234收尾删除花括号、.strip().lower()注意normalize_text只做文本形态的统一不做数学化简\sqrt{2}保持为sqrt(2)字符串。4.3 符号等价sympy_parser 与 equality_checksympy_parser(expr)用sympy.parsing.sympy_parser.parse_expr解析启用standard_transformations与implicit_multiplication_application支持2x、3(12)、x(1y)这类省略乘号写法evaluateTrue使简单常量立即化简23→5对长度超过 2000 的垃圾输出直接返回None防崩溃并捕获SympifyError、SyntaxError、TokenError、PolynomialError等异常。equality_check(expr_gtruth, expr_pred)先做字符串精确相等短路否则两边都过sympy_parser若能同时解析成功则用simplify(gtruth - pred) 0判定符号等价——这就是「0.5与1/2判对、0.3333333333与1/3判错」的原理见 test_ch03.py 的test_grade_answer用例。split_into_parts(text)若文本形如(a, b)或[x, y, z]首尾括号且内部含逗号拆分为多个独立部分grade_answer要求两边拆分后的部分数一致再对每一对调用equality_check全部等价才算对——因此(2, 1)与(1, 2)判错、(1, 2, 3)与(1, 2)判错。仓库测试进一步保证了评分器的自洽性test_math500_parser_self_answers 验证 500 条标准答案自比全部判对test_math500_parser_boxed_answers验证把答案包进\boxed{...}后提取判分仍全对test_math500_parser_boxed_constant_mismatch验证统一填\boxed{123}时全部判错。5. 批量并行评估evaluate_math500_batched.py5.1 使用方式与额外参数与单序列版相比批处理版本把并行度扩展到生成阶段本身实现并行解码uv run evaluate_math500_batched.py --help除第 3.1 节公共参数外额外选项为--batch_size BATCH_SIZE Number of examples to generate in parallel (default: 4). --disable_efficient_mode Use a simpler batched inference method. Slower and more memory-intensive, but easier to debug.5.2 实现说明per-sequence 提前停止默认高效模式下批内某条序列一旦生成 stop token 就停止参与后续 forward pass其余序列继续生成而--disable_efficient_mode下所有序列都跑到最长序列结束才停。二者的对应实现是 qwen3_batched.py 中的两个函数generate_text_basic_batched_cacheL339朴素批解码全批同步推进直到max_new_tokens或全批结束generate_text_basic_batched_cache_stopL466维护finished_full掩码与active_idx活动行索引已结束的行从批中剔除、KV-cache 随之收缩实现按序列提前停止。脚本主流程evaluate_math500_batched.py在--disable_efficient_mode时导入朴素版否则导入 stop 版。原文档特别说明该差异只影响计算效率不影响定性结果——因为 stop token 之后的 token 在解码时会被丢弃解码后按 EOS 位置截断见row_tokens[: eos_pos[0]]。批处理版还采用左填充pad_id填充到批内最大长度以适配 KV-cache 前缀共享。5.3 MPS 设备提示部分高效批解码用到的 PyTorch 算子尚未在 MPSApple Silicon上支持原文档给出两条缓解路径# 方式一启用 MPS fallback PYTORCH_ENABLE_MPS_FALLBACK1 uv run evaluate_math500_batched.py # 方式二改用朴素批解码 uv run evaluate_math500_batched.py --disable_efficient_mode5.4 参考性能与准确率原文档实测数据原文档给出两组 500 题实测数据分别对应顺序与批量模式这些是在文档所载环境中测得的结果不同硬件上数值会有差异仅作量级参考顺序模式evaluate_math500.py --dataset_size 500设备 / 数据集规模Base 模型Reasoning 模型Mac Mini M4 CPU500 例顺序43.6 min未运行过热Mac Mini M4 GPU500 例顺序37.5 min未运行过热DGX Spark500 例顺序10.0 min182.2 minH100 GPU500 例顺序13.3 min185.4 min批量模式evaluate_math500_batched.py --dataset_size 500 --batch_size 128设备 / 数据集规模Base 模型Reasoning 模型Mac Mini M4 CPU500 例batch 128167.2 min未运行过热Mac Mini M4 GPU500 例batch 128报错*报错DGX Spark500 例batch 12816.3 min119.3 minH100 GPU500 例batch 1283.3 min14.6 min同批评测得到的准确率base 模型 15.6%78/500reasoning 模型 48.2%241/500——reasoning 模型在 MATH-500 上的显著提升正是本仓库「从零实现推理模型」各章节训练管线RLVR/GRPO见第 6、7 章所要验证的核心指标。6. 离线重算evaluate_json.py如果已经生成了记录文件只想重新计算准确率无需再次跑模型uv run evaluate_json.py --json_path math500_base-mps-evaluate-script.jsonl # Accuracy 15.6% (78/500)自定义字段名默认键为gtruth_answer与generated_textuv run evaluate_json.py \ --json_path my_records.json \ --gtruth_answer gtruth_answer \ --generated_text generated_text从源码看load_records兼容多种输入形态标准 JSON 数组、{records: [...]}包裹、单个 JSON 对象以及逐行 JSON 的 JSONL 文件对每行会做 JSON 解析并报告出错行号。evaluate_records逐条执行extract_final_candidategrade_answer后输出准确率。仓库测试 test_math500_scripts.py 用两条 JSONL 记录验证了默认键输出Accuracy: 50.0% (1/2)并用自定义键answer_key/model_output验证了--gtruth_answer/--generated_text参数生效。7. 进阶混合 LaTeX 解析器03_advanced-parser7.1 背景与定位该目录源于仓库 issue #133 中提出的混合 LaTeX 解析器实验用于处理章节默认解析器容易漏判的边界情况。目录内容compare_with_current_parser.ipynb带使用示例的对比 notebookmath500_gpt_answers.json 与 math500_qwen3_answers.json带 LLM 答案的 MATH-500 样本notebook 对比所用gen_llm_answers.py便捷脚本用 Qwen3 模型批量生成\boxed答案并写入 JSON默认--which_model reasoning、--dataset_size 500输出math500_qwen3_answers.jsonevaluate_math500_advanced.py与第 3 章 evaluate_math500.py 等价但新增--hybrid_parser参数切换混合解析器。7.2 与章节解析器的差异章节解析器reasoning_from_scratch/ch03.py的设计目标是紧凑、可教学主打轻量规范化加符号等价检查主要把答案当作算术/符号表达式处理。混合解析器reasoning_from_scratch/bonus/parser.py则是模式优先、覆盖面更广在回退解析之前先识别答案格式额外支持区间interval、并集union、方程equation、矩阵matrix、集合记号、隶属关系\in与\pm更好地保留关键边界情况如带进制下标52_8与文本大小写\text{Evelyn}。行为差异示例节选原文档与测试用例 test_ch03_advanced_parser.py输入章节解析器混合解析器52_8常解析为528保留为52_811,\! 111,\! 111,\! 100可能变成元组(11, 111, 111, 100)规范化为11111111100(0,9) \cup (9,36)通常保持为文本返回符号并集Union(Interval.open(0, 9), Interval.open(9, 36))x5保持x5解析为方程Eq(x, 5)\text{(C)}解包后变小写c保留(C)\$32,\!348文本解析为32348.0权衡取舍章节解析器更简单、更快、更易解释混合解析器LaTeX 边界情况覆盖更好但规则更多、复杂度更高且额外引入 SymPy LaTeX 后端依赖sympy.parsing.latex.parse_latex。7.3 使用方式在完整评测中启用混合解析器uv run evaluate_math500_advanced.py --dataset_size 500 --hybrid_parser也可以直接从包中导入解析器单独使用from reasoning_from_scratch.bonus.parser import normalize_text_hybrid, sympy_parser_hybrid更详细用法见 compare_with_current_parser.ipynb。需要留意的是 LaTeX 后端依赖evaluate_math500_advanced.py启动时会自检normalize_text_hybrid(r\frac{1}{2}) 1/2若后端未就绪会提示uv pip install antlr4-python3-runtime4.11.*测试 test_ch03_advanced_parser.py 也区分了「无 LaTeX 后端」与「有 LaTeX 后端」两组用例前者验证52_8、\text{Evelyn}、\$32,\!348等不依赖后端的路径后者验证并集、方程、\pi等依赖后端的路径。8. 小结与延伸至此你已掌握 reasoning-from-scratch 第 3 章评估推理模型的完整工具箱单序列与批量两种评测脚本、可复检的 JSONL 记录、离线重算工具以及可选的混合 LaTeX 解析器。这些脚本与reasoning_from_scratch/ch03.py中的评分函数被仓库测试test_ch03.py、test_math500_scripts.py、test_ch03_advanced_parser.py系统性覆盖可作为可靠的评估基座。往后的章节在此基础上进一步扩展第 4 章的 推理缩放脚本CoT 提示、self-consistency与第 5 章 best-of-N 等更多推理期缩放方案都会复用第 3 章的 MATH-500 评测基础设施第 6 章 RLVR/GRPO 训练产出的检查点则可通过--checkpoint_path直接接入本评估脚本。赞分享示例工程【免费下载链接】reasoning-from-scratchImplement a reasoning LLM in PyTorch from scratch, step by step项目地址https://gitcode.com/gh_mirrors/re/reasoning-from-scratch点击查看免费下载相关推荐reasoning-from-scratch 实战用 MATH-500 命令行脚本评测推理模型含批量加速与答案校验reasoning from scratch 实战用 MATH 500 命令行脚本评测推理模型含批量加速与答案校验 本篇技术指南围绕开源仓库 reason示例工程reasoning-from-scratch 第 6 章实战用 RLVR GRPO无 KL 项从零训练推理模型reasoning from scratch 第 6 章实战用 RLVR GRPO无 KL 项从零训练推理模型 本章是 reasoning from示例工程reasoning-from-scratch 第 6 章实战用 GRPO无 KL在 PyTorch 中从零训练推理模型reasoning from scratch 第 6 章实战用 GRPO无 KL在 PyTorch 中从零训练推理模型 导读 本文围绕 reasonin示例工程上一篇ViT模型剪枝终极指南从千兆到百兆的完整解决方案下一篇Buster工具入门5分钟快速上手电子邮件侦察创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询