复旦大学研究揭示合成数据在提升大模型归纳推理能力中的潜力
复旦大学研究揭示合成数据在提升大模型归纳推理能力中的潜力
推理是人类基本的认知过程,对学习、问题解决和科学发现至关重要。常见的推理方式包括演绎推理和归纳推理。演绎推理是从一般前提推导特定结论,而归纳推理则是从具体实例中提炼出一般性结论或规律。
尽管研究人员一直努力增强大模型的推理能力,但大部分训练数据更偏向演绎推理,例如“解释这段代码的含义”或“写一个程序找出列表中的最大和最小数”。相比之下,归纳推理任务的数据相对稀缺,如“假设有 func(1) = 6,func(2) = 7,func(3) = 8,func(4) = 9,请解释这个函数”或“给定输入与输出 john Smith -> Smith, John;frank lee -> Lee, Frank;Laura Jane Jones -> Jones, Laura,请编写程序将输入转换为输出”。
这种数据不平衡使得大语言模型(LLMs)在归纳推理学习上面临挑战,且缺乏有效评估其归纳能力的标准。为了解决这一问题,复旦大学提出了Case2Code挑战,模拟了现实工作中一项常见的场景:根据一些输入输出示例编写代码。熟悉此类题目的读者一定不陌生。
此外,本文还提出了一种高效获取大规模、多样化Case2Code训练数据的方法。经过使用1.3M规模的合成数据训练,7B小模型在Case2Code评估集上的准确率显著提升,最高增幅达18.9%,甚至超过了LLaMA3-70B和GPT-3.5,且与GPT-4的表现相当。
论文标题:
Case2Code: Learning Inductive Reasoning with Synthetic Data
论文链接:
https://arxiv.org/pdf/2407.12504
代码链接:
https://github.com/choosewhatulike/case2code
方法
本文首先构建了大规模的合成数据用于代码的归纳推理。合成数据生成框架旨在自动生成多样化的Case2Code数据,其步骤如下所示:
首先,从大规模数据集中收集多样化的程序,并通过基于规则的过滤器进行筛选。接着,利用LLM生成多样的示例输入,并通过代码解释器计算其对应的输出。最后,筛除低质量程序,并将获得的三元组(程序、输入、输出)转换为用于代码领域归纳推理的Case2Code数据。
简单来说,就是基于已有的题解(程序),使用LLM生成输入输出示例,以构建包含(程序、输入、输出)三元组的Case2Code数据。
1. 收集程序
为了提高数据的多样性和质量,作者从The Stack中抽样有效的Python函数程序。使用抽象语法树(AST)解析工具解析The Stack中的每个文件,以获取Python函数,并确保满足以下条件:(1)通过语法检查;(2)具有一个或多个输入参数和返回值;(3)不依赖于第三方包或外部I/O操作。经过过滤后,使用代码解释器进行验证,从而获得多样化的Case2Code数据。
2. 生成输入
作者指导LLMs为每个函数编写输入参数,下表是一个简单的示例:
生成合适的输入参数时,LLM首先需分析函数的实现,推断输入参数的可能类型及范围,最终提出正确的输入参数。
作者指出,这一步并不需要LLMs具备强大的能力,一些小型LLMs也能高效完成,从而降低生成过程的成本。
3. 获得输出
作者利用代码解释器执行函数并处理输入,以获取对应的输出。考虑到LLM生成的输入样例可能存在错误,当函数的输出不因输入变化而变动(例如恒定输出或抛出异常)时,该函数将被视为无效并被剔除。
同时,为避免生成的Case2Code数据超出LLM的上下文窗口限制,将产生异常冗长输出值的函数排除在外。然而,不会过滤导致异常或运行时错误的输入,失败的调用尝试同样可以为归纳推理提供有价值的信息,以重建函数。
4. 后处理
最后,将获得的函数及其对应的输入输出对转换为Case2Code风格的数据。具体而言,对于给定函数及其测试用例,随机选择多个示例作为观察集。生成的提示数据有助于LLM在观察集中进行归纳推理,从而重建函数。转换后的训练示例如下表所示:
实验设置
合成数据规模
作者从The Stack预训练数据集中随机抽取了约2.3万个函数,经过去重和过滤后,使用InternLM2-7B生成输入示例,经过Python执行环境生成输出,最终获得了1.3M包含输入-输出-函数三元组的数据集。其中保留500个样本用于评估,剩余样本用于训练。
训练设置
为了展示训练数据的泛化性和有效性,作者在InternLM2-7B和LLaMA3-8B上分别进行了三种变体的Case2Code训练:直接微调、混合预训练和混合微调。
评估设置
评估基准使用HumanEval和MBPP,评估训练后的LLM编码能力,同时引入EvalPlus——这两个基准的扩展版本,包含大量额外测试案例,以确保评估的严格性。
对于非指令调优模型,采用zero-shot提示和four-shot提示在HumanEval和MBPP上进行测试。对指令对齐的LLM,则统一采用zero-shot提示在所有基准上进行评估。
为探究LLM在代码归纳推理方面的能力,还进一步测试了它们在Case2Code任务上的表现,采用zero-shot提示。
结果分析
zero-shot性能评估
作者汇总了不同代表性LLM在zero-shot Case2Code任务中的表现及其编程性能:
分析结果显示,这些模型在Case2Code任务中的表现与其程序合成能力密切相关。在其他基准上获得高分的模型在Case2Code中同样表现出色,而规模较大的模型普遍优于小模型。这表明Case2Code是一个有效的基准,能够反映LLM的代码推理能力。
但总体得分较低,也就是说大模型尚未达到根据示例编写完全准确代码的水平。这可能是由于大模型在训练时接触的编程示例虽然众多,但像Case2Code这样需要通过观察行为来归纳程序的任务较少,类似于“逆诅咒”现象所揭示的规律。
Case2Code的泛化能力
合成数据的一个基本问题是其泛化能力。因此,作者使用合成Case2Code数据集在不同设置下训练不同的LLM,以探索其对LLM代码推理学习的影响,结果如下表所示:
直接微调
直接在Case2Code推理样本上训练的LLM能够有效学习基于案例的编码方法。如上表所示,通过直接微调,InternLM2-7B和LLaMA3-8B在Case2Code评估集上的准确率分别提升至44.5%和42.0%,最高增幅达18.9%,这一表现甚至超过了LLaMA3-70B和GPT-3.5,与GPT-4相当。
通过Case2Code样本的训练,不仅能强化LLM的归纳推理能力,还能提升其整体编码能力。
预训练阶段混合
在预训练阶段融入Case2Code数据,有效促进模型将执行状态与函数实现相结合,从而显著增强LLM的程序合成能力。相比于仅在Case2Code数据集上微调,此策略有助于更广泛地迁移通过Case2Code任务习得的代码状态归纳推理能力,实现更好的泛化效果。
指令微调阶段混合
在进行instruction-following数据集训练时,融入Case2Code数据显著提升了LLM在基于指令编程任务上的表现。整合Case2Code数据后,各LLM在代码生成任务上的表现均有所提升。以InternLM2-7B为例,其在HumanEval上的准确率提升超过10%,达到64.6%。同样,LLaMA3-8B在HumanEval、HumanEval+及MBPP上的准确率也分别提升至64.6%、57.9%和71.2%,较其SFT版本有明显进步。这充分证明了学习Case2Code数据的有效性,并突显了在LLM训练中纳入归纳推理数据的重要性。
消融实验
提示的多样性
由于Case2Code训练数据源自(程序、输入、输出)三元组的转换,提示模板在构建过程中至关重要。作者对比了单一模板与多模板风格提示对合成数据效果的影响,结果如下:
尽管在Case2Code领域的性能受提示多样性影响较小,但LLM在其他程序合成任务上的准确性显著提升,这揭示了多样性在LLM学习中的潜在关键作用。
输入生成LLM的影响
在合成Case2Code数据时,核心环节之一是引导LLM为各程序创建多个输入样例。输入与程序共同执行后产生的输出,共同构成了构建训练数据的关键上下文。
为探究LLM生成输入示例的能力对数据质量的影响,作者将LLM从InternLM2-7B更换为更强大的LLaMA3-70B,并生成了规模减半的新数据集。两者的成本比较如下图所示:
使用这一版成本更高的Case2Code数据在InternLM2-7B上进行了指令微调测试,结果如下:
LLaMA3-70B编写的输入样本质量更高,使得训练后的LLM在数据减少的情况下仍展现出相当的代码推理能力。这凸显了输入生成步骤对数据质量的重要性,建议在资源允许时采用更强大的LLM。
不过,低成本版本InternLM2-7B也取得了与LLaMA3-70B相当的效果,成为一个性价比更高的选择!
模型规模
为了探究小模型生成的Case2Code数据是否仍能有效提升大模型的性能,并深入分析模型规模对学习过程的影响,作者使用InternLM2-7B生成的Case2Code数据,对不同大小的InternLM2系列模型进行训练,实验结果如下表所示:
可以看到,无论学生模型规模如何,即使学生模型的规模几乎是数据合成模型的三倍,合成数据仍显著增强了其代码推理能力。这一发现揭示了在大规模代码任务中,弱监督到强监督转换的可行性与潜力。
结论
本文构建了一个新的基准——Case2Code,用于评估LLMs在代码领域的归纳推理能力,并提出了一个数据合成框架,仅使用小型LLM和代码解释器便能自动高效地从预训练代码文本中收集高质量的Case2Code训练数据。通过在不同设置下训练各种LLM,本文证明了Case2Code不仅能提升LLM的归纳推理能力,还能提高其整体编码能力。期待在未来,当真实数据用尽时,合成的Case2Code能够持续为改进LLM生成高质量的数据提供支持。