如果你曾经让标准的大语言模型 (LLM) 去解决一个复杂的数学问题,你可能注意到了一种令人沮丧的模式。模型通常会写出一段文笔优美、充满自信的解释,但在实际算术上却栽了跟头,无比确信地给出一个错误答案。相反,专门设计用来写代码的模型可以完美地进行计算,但往往难以理解应用题中的细微之处。

为了让开源模型达到 GPT-4 级别的性能,研究人员通常分为两个阵营: 一派致力于通过推理 (思维链) 教模型更好地“思考”,另一派则致力于教模型“使用工具” (如 Python 解释器) 。

但是,如果一个模型能兼顾两者呢?

在这篇文章中,我们将深入探讨 MuMath-Code , 这是一篇提出统一方法的各类研究论文,旨在结合两者的优势。通过将多视角的数据增强工具使用能力相结合,研究人员创建了一个在数学基准测试中达到最先进 (SOTA) 性能的开源模型,其实力可与专有巨头模型相媲美。

数学推理的两条路径

要理解 MuMath-Code 的重要性,我们首先需要了解 LLM 数学推理的现状。从历史上看,改进主要来自两个截然不同的方向:

1. 无工具方法 (纯推理)

这种方法依靠模型的内部权重来解决问题。为了让模型在这方面表现更好,研究人员使用了数据增强 。 他们获取现有的数学问题,并对其进行重述、更改数字或增加复杂度。然后,模型在这个巨大的“思维链” (CoT) 推理数据集上进行微调。

  • *优点: * 模型学会了逻辑地分解问题。
  • *缺点: * LLM 在充当计算器方面表现糟糕。它们很容易产生数字幻觉。

2. 工具使用方法 (代码执行)

这种方法承认 LLM 不是计算器。我们不要求模型计算 \(1234 \times 5678\),而是教模型编写 Python 脚本来完成计算。像 思维程序 (PoT)PAL 这样的方法会生成代码块,在外部 Python 解释器中执行它们,并读取结果。

  • *优点: * 完美的计算准确性。
  • *缺点: * 如果模型不理解问题的逻辑,代码就会是错的,即使计算过程是正确的。

缺口: 直到现在,很少有方法能有效地结合这些策略。工具使用模型往往忽视了 CoT 丰富的语言推理能力,而推理模型则忽略了工具的精确性。

MuMath-Code 的解决方案

MuMath-Code 的作者提出了一种将工具使用与广泛的数据增强相结合的方法。他们引入了一个新的数据集 MuMath-Code-Data , 以及一种新颖的 两阶段训练策略

其核心思想是模拟一位人类专家: 先勾勒出计划 (推理) ,编写程序解决困难部分 (编程) ,运行程序 (执行) ,甚至在代码出错时进行修复 (调试) 。

通用流程

如下图所示,该过程通过两个不同的微调阶段,将基础模型 (如 Llama-2) 转变为数学高手。

Figure 2: Illustration of our proposed method. The foundation model is first trained through an initial stage, resulting in an intermediary model that possesses more powerful math reasoning capability. This intermediary model is then further trained on the proposed dataset to learn code generation and tool interaction, leading to the final model, MuMath-Code.

让我们拆解一下使这个流程运作的各个组件。

1. 多视角数据增强

你不能仅仅依靠 GSM8K 或 MATH 的训练集来训练一个强大的模型——它们太小了。研究人员使用了之前工作 (MuMath) 中的技术来大幅扩展训练数据的规模。

他们选取一个种子问题并应用各种转换:

  • 重述 (Rephrasing) : 用不同的词语问同一个问题。
  • 问题变更 (Question Alteration) : 更改数字或添加约束条件。
  • FOBAR: 掩盖问题中的某个条件并提供答案,将其转化为一个“逆向”问题。
  • 后向-前向转换 (Backward-Forward Transformation) : 生成用于验证理解的问题。

这产生了一个巨大的、多样化的数据集。但这里有一个转折: 对于 MuMath-Code,他们不只想要文本答案。他们使用 GPT-4 为这些增强的问题合成了嵌套代码的解答

2. 构建“思维-代码”解答

训练数据的结构至关重要。研究人员不只是希望模型输出代码。他们为解答设计了一种特定的格式,称为 \(\mathcal{D}_{\mu\text{-}code}\)

单个解答是一个自然语言、代码执行交错的序列。解答 \(s\) 的数学表示为:

Equation describing the solution structure.

这里:

  • \(c_i\) 是 思维链 (CoT) 文本段 (推理) 。
  • \(p_i\) 是 Python 代码 块。
  • \(o_i\) 是代码执行的 输出
  • 该序列不断重复,直到得出最终答案。

为了使这些数据具有高质量,作者在数据合成过程中引入了三种具体策略:

A. 前缀思维链 (Prefix CoT)

模型不是直接跳进 Python 代码,而是被训练去执行“前缀 CoT”——在编写任何代码之前进行深思熟虑的自然语言分析。这反映了程序员的思维方式: “首先,我需要定义变量,然后我将使用距离公式……” 然后才输入 def calculate_distance():

B. 代码调试

真正的程序员也会犯错。为了教导模型具备韧性,训练数据包含了“调试”回合。当 GPT-4 生成的代码在数据创建阶段无法执行时,研究人员并没有将其丢弃。他们保留了损坏的代码和错误信息,然后提示 GPT-4 修复它。

通过在训练数据中包含这些纠错循环,MuMath-Code 学会了如何阅读错误信息并进行自我修正——这对于工具使用模型来说是一项关键技能。

C. 伪答案引导过滤

当你通过更改数字 (问题变更) 来增强数据时,你会丢失原始的“基本事实”答案。你怎么知道新的合成解答是否正确? 研究人员使用了多数投票 。 他们为这些新问题生成了多个解答。如果其中绝大多数得出了相同的答案,该答案就被视为“伪答案”。只有导致此答案的解答才会被保留用于训练。

3. 两阶段训练策略

这可能是该论文最重要的架构贡献。作者认为,直接在嵌套代码的数据上训练模型并非最佳选择,因为模型尚未掌握数学推理

阶段 1: 纯推理 (基础) 首先,模型在 MuMath-Data (\(\mathcal{D}_{\mu}\)) 上进行微调,该数据集由纯文本的思维链推理组成 (没有代码) 。

这里的训练目标是标准的语言建模:

Equation for Stage 1 training loss.

这一阶段构建了一个“中间模型” (简称为“MuMath”) ,它理解逻辑和数学概念,但尚未使用工具。

阶段 2: 工具交互 (专业化) 接下来,中间模型在 MuMath-Code-Data (\(\mathcal{D}_{\mu\text{-}code}\)) 上进行微调。这个数据集包含了交错的 文本/代码/执行 结构。

至关重要的是,在计算损失 (模型试图最小化的误差) 时,他们屏蔽了执行输出的损失 。 模型应该学习生成思维 (\(c_i\)) 和代码 (\(p_i\)),但不应该尝试预测执行输出 (\(o_i\))——那是来自外部工具 (Python 解释器) 的内容。

此阶段的目标函数如下所示:

Equation for Stage 2 training loss.

到了阶段 2 结束时,模型 (现在称为 MuMath-Code )可以对问题进行推理,编写代码来解决问题,并利用结果。

实验与结果

这个复杂的流程真的有效吗?研究人员在 GSM8K (小学数学) 和 MATH (高中竞赛数学) 等标准基准上测试了 MuMath-Code。他们使用 Llama-2 和 CodeLlama 作为基础模型。

SOTA 性能

结果显示性能有了巨大的飞跃。

Figure 1: The comparison between our MuMath-Code and other state-of-the-art tool-use LLMs. MuMath-Code exhibits a substantial improvement in performance on both GSM8K and MATH, relative to the previous approaches.

如图 1 所示,MuMath-Code 优于其他最先进的开源方法。

  • GSM8K: 70B 模型达到了 90.7% 的准确率。即使是 7B 模型也达到了 83.8% , 击败了许多更大的模型。
  • MATH: 70B 模型达到了 55.1%

表 1 提供了详细的细分数据。请注意 MuMath-Code (底部几行) 如何始终优于纯无工具模型 (如 WizardMath) 和早期的工具使用模型 (如 ToRA) 。

Table 1: Comparison of the state-of-the-art methods on various datasets.

为什么要两个阶段?

两阶段训练真的有必要吗?我们能不能把所有数据混合在一起?

研究人员进行了一项消融实验来证明其策略的价值。表 2 比较了不同的训练方法。结果清楚地表明,先在 CoT 数据上训练 (\(\mathcal{D}_\mu\)),然后在代码数据上训练 (\(\mathcal{D}_{\mu\text{-}code}\)),比单独在代码数据上训练或混合训练的效果要好。

Table 2: A two-stage training strategy improves the models’ performance, as opposed to a single-stage training.

“先思考”再“编程”的价值

研究人员还测试了其解答结构中特定组件的作用。

  1. 前缀 CoT: 移除初始文本分析会导致性能显著下降。
  2. 代码调试: 移除纠错示例也会损害准确性。

这证实了盲目编程不如“计划 -> 编程 -> 调试”有效。

Table 3: Ablation study for prefix CoT and code debugging.

缩放定律

最后,研究人员考察了数据量。添加更多的合成数据会有持续的帮助吗?

图 3 显示了不同数据子集 (如 Rephrase, Alter, FOBAR) 的缩放曲线。上升的轨迹表明模型尚未达到天花板——更多高质量的增强数据会产生更好的数学推理器。

Figure 3: Scaling all the subsets of MuMath-Code-Data. The models undergo a single stage (only Stage-2) of training.

有趣的是,即使模型已经在阶段 1 进行了微调,在阶段 2 添加更多数据仍然会继续提高性能,如图 4 所示。

Figure 4: Scaling all the subsets of MuMath-Code-Data. The model has already been finetuned on MuMath-Data.

结论

MuMath-Code 代表了开源大语言模型向前迈出的重要一步。通过有效地将 LLM 的语言推理能力与 Python 的计算精度相结合,研究人员创建了一个在特定任务上可与 GPT-4 等专有模型相媲美的框架。

这项工作的主要启示包括:

  1. 不要二选一,要结合: 无工具与工具使用之间的争论是一个错误的二分法。最好的系统会同时使用两者。
  2. 数据质量至关重要: 像前缀 CoT 和在训练数据中保留“调试”痕迹等技术,能显著提高模型的鲁棒性。
  3. 课程学习行之有效: 两阶段策略——在学习工具 (阶段 2) 之前先学习概念 (阶段 1) ——是训练专业化智能体的一种强大方式。

展望未来,像 MuMath-Code 这样的方法表明,配备正确工具的小型、训练有素的模型可以执行令人惊讶的复杂推理任务,从而普及强大 AI 能力的使用权。