ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

合成数据不是越多越好:12.7B小模型越级挑战的实战指南

合成数据不是越多越好:12.7B小模型越级挑战的实战指南

大模型训练这几年,我最深的体会是:很多人都把合成数据当成廉价又无限的燃料,越多越好。但真实情况完全反过来——把合成数据量翻一倍,模型能力反而可能明显倒退。有次我亲手把一个训练项目的合成数据从100B提到200B,结果模型在数学推理上的准确率掉了快3个点。同组的老工程师看完曲线撂了句话:“你不是在喂数据,是在喂毒药。”

这句话后来越想越有道理。今天这篇文章不聊虚的,就拆两件事:第一,为什么更大的合成数据反而有害,背后的机制是什么;第二,一个12.7B的小体量模型,是怎么靠数据策略在特定推理任务上干过更大规模的顶流闭源模型(下文统一用GPT-5.1作为代号,不指向任何具体产品)。文章适合正在训练自有基座模型、做领域微调、或者想在有限算力下把模型榨出性价比的团队参考,内容里有大量可以直接抄走的配置和经验。

1. 合成数据的双刃剑:为什么更大的合成数据反而有害

先说结论:更多合成数据不等于更多信息。当数据量超过某个临界点,新增的绝大部分内容都是在重复强化已有模式,甚至是在放大生成器自己的偏好和错误。你喂得越多,模型就越深地陷入生成器那套自洽但偏离真实世界的分布里,之后在真实任务上越来越难泛化。听起来有点像“越努力越不幸”,但这就是不少训练项目翻车背后的核心原因。

1.1 先搞清楚一个反直觉的现象:数据量翻倍,能力却衰减

我做过一组很简单的对照实验:同一个底座模型,分别用相同真实数据加不同规模的合成数据来训练。A组合成数据50B,B组合成数据100B,训练预算和步数保持一致。结果有点反直觉:B组在代码生成和数学推理上全面低于A组,但在“句子读起来够不够顺”这类风格指标上显得更自然——因为它把生成器那套表达习惯学得更彻底了。

这不是个例,很多复现实验都得出一致结论。合成数据给模型带来的收益高度集中在早期阶段,越过那个拐点之后,边际收益就开始变成负数。更麻烦的是,这种“负收益”不是显性报错,它藏在模型内部,表现为泛化能力悄悄变差、难题解决率下降、甚至出现“看着训练集说得头头是道,换到测试集就胡言乱语”的割裂状态。

这里要澄清一点,我说的“有害”不是指随机噪声造成的有害,而是一种隐蔽的系统性偏置。合成数据生成器本身有偏,再强的模型也有自己的口吻偏好、解题套路和思维盲区。如果你的合成数据只来自同一个生成器,训练出来的模型会表现出典型的“单老师效应”——能做老师会的题,也一定会犯老师犯的错。

1.2 三个核心机制:分布坍缩、多样性陷阱、信噪比失衡

把“有害”拆开细看,主要有三个机制在同时起作用。

第一个机制是分布坍缩。合成数据的分布是生成器拟合出来的,和真实数据分布之间一定存在系统性偏差。当合成数据在训练集中占比过高时,模型学的就不再是“世界的规律”,而是“生成器的规律”。最经典的表现是:训练集里所有数学题都集中在代数领域,几乎没有几何题,那模型对几何题的泛化能力几乎为零。这个现象在图像生成那边叫mode collapse,在大模型的数据工程里同样存在,只不过大家更习惯叫它“分布坍缩”。

第二个机制是多样性陷阱。你以为自己造了1000万条独立样本,去重之后真正独立的可能只有50万条。很多数据流水线用同一个prompt模板批量产出,生成的句子结构高度雷同,n-gram重复率惊人。模型在这种数据上训练,收敛曲线非常漂亮,但实际只学会了一个狭窄领域里的几种固定套路。一旦遇到稍长一点的上下文或没见过的新题型,掉点速度会让你怀疑人生。

第三个机制是信噪比失衡。合成数据的“噪声”不是均匀散布的,而是与生成器的偏好强相关。比如生成器遇到复杂推理时总喜欢省略中间步骤,那模型也会学到“跳过关键推导”这个坏习惯。数据越多,坏习惯被强化得越狠。哪怕你做了过滤,只要过滤规则本身没有专门针对这类错误,问题依然会持续累积。

这三个机制往往同时出现,肉眼极难分辨。如果你发现模型“越训越傻”,第一反应别去调超参数,先回去查数据分布。

维度真实数据合成数据
覆盖真实分布高,但获取成本大有偏,取决于生成器质量
多样性天然多样容易出现重复模板,需要精心设计
错误分布随机、稀疏与生成器偏好相关,可能系统性出现
扩大规模收益通常为正超过临界点后收益递减甚至为负
最适合的角色基座主体、领域锚点补充长尾、难度递进、结构化产出

1.3 什么时候合成数据“必死无疑”

有几种场景下,合成数据不是没用,而是直接拖垮训练,需要格外警惕。

第一种是生成器与目标领域错位。比如目标任务是代码生成,结果你用一个通用对话模型批量生成代码样本。模型产出的代码经常格式对、逻辑错,看起来像模像样,实际根本跑不通。把这种数据喂进去,等于系统性地教模型“代码可以随便编”。

第二种是过滤规则依赖LLM打分,但打分模型本身对目标任务不擅长。比如用对话模型去给数学题质量打分,它更关注句子是否通顺,而不是推导是否正确,大量低质量样本就这么被放进了训练集。

第三种是训练迭代过程中反复使用同一批合成数据,每轮都不重新生成、不重采样。相当于拿着同一个错误答案反复学习,模型当然越学越偏。

第四种尤其隐蔽:合成数据恰好覆盖了目标任务的关键困难分布,但因为过滤时用了“困惑度越高质量越差”这类错误假设,把最有价值的困难样本全部筛掉了。

这类问题一旦成型,通常不是调参能救回来的。我见过不少项目在训练后期试图用增加真实数据来对冲,但效果有限,因为这个时候模型的内部分布已经彻底偏向合成数据了。

2. 12.7B越级挑战的秘诀:密度、课程与反向蒸馏

有人会问:12.7B这种体量,凭什么越级挑战?这里先把口径说清楚,不是全面碾压,而是在一组特定难度较高的推理任务上,用更小的模型、更低的推理成本拿到更好分数。这种“刺穿式超越”在工业界完全可复现,核心是数据策略设计得足够极端。

2.1 目标定位:不要全面碾压,要精准刺穿

小模型最忌讳的目标是“在所有评测上超过大模型”,那几乎不可能。真正可行的目标是:选定一个或少数几个关键能力维度,把该维度的数据密度推到极致,让12.7B在长尾场景里表现得像更大体量的模型。实现路径分两层:

第一层,找到与目标能力最匹配的数据源,确保训练数据里该能力的占比显著高于常规水平。第二层,用课程式策略让模型在该能力维度上越钻越深,而不是平均用力。

我印象很深的一个案例:某团队要做面向数学老师的问答模型,他们把训练数据里数学推理相关样本的占比从10%提到45%,同时把合成数据的难度曲线做成一阶一阶向上爬的阶梯,最后小模型在数学竞赛类题目上的得分明显超过了他们调用的顶流闭源模型。外人看是奇迹,内行看是数据配比和难度策略的胜利。

2.2 合成数据不是用来“凑量”,而是用来“控分布”

很多人把合成数据当燃料,越多越好;但真正做过数据工程的人会告诉你,合成数据的核心价值在于“控分布”。真实数据的长尾分布你很难完全控制,但合成数据可以。你能精确控制主题占比、难度分布、输出格式、上下文长度,甚至能构造真实世界几乎不会天然出现的边界样本。

实操中最有价值的组合是“真实数据锚定 + 合成数据扩散”。合成数据占比建议控制在10%到25%之间,具体根据生成器质量和任务难度跨度调整。我常用的一组参考配比是:

  • 领域微调阶段:合成数据占比5%-10%,主要用来补足长尾知识。
  • 推理能力提升阶段:占比15%-25%,用高难度合成样本做难度递进。
  • 对齐阶段:占比1%-5%,用偏好数据让输出更符合人类品味。

合成数据的核心价值不是替代真实数据,而是精确补足真实数据中最稀缺的那部分分布。这也是对“大合成数据有害”的完整破解思路:不是不用合成数据,而是每一份都要用在刀刃上。

2.3 难度课程的设计:让模型一阶一阶往上爬

合成数据相比真实数据还有一个巨大优势——难度完全可控。你可以让生成器专门生成难度系数1的简单题,也可以生成难度系数5的竞赛题。训练时把它们按顺序排成课程,模型先从简单样本里学规律,再逐步接触复杂样本,收敛速度和最终上限都会明显提升。

我项目中常采用的课程设计是:

  1. 把合成数据按难度自动标注,分成5个等级。
  2. 训练前80%的步数使用难度1-3的样本,保证主干能力稳定。
  3. 训练后20%的步数加入难度4-5的样本,逼模型进入“解决难题模式”。
  4. 最后用极少数难度5的硬样本做冲刺微调,数量控制在训练集的2%-5%。

这个策略的难点在于难度标注是否准确。如果你只按题目字数分难度,那等于没分。更靠谱的做法是用多个不同能力的模型在同一批数据上做推理验证,把“大模型能做对但小模型做错”的样本自动标记为高难度。这个思路在复现时非常有效,也能避开人工打标的主观偏差。

难度等级样本特征训练阶段占比建议
1单步推理、常见模式前期约20%
2多步推理、少量干扰前期约25%
3长上下文、多条件约束中前期约25%
4跨领域组合、陷阱条件后期约20%
5竞赛级、非常规解法冲刺阶段约10%

2.4 反向蒸馏与偏好对齐:不是模仿,而是提取

小模型挑战大模型,常规思路是蒸馏——让大模型生成答案来训练小模型。但我更推荐一种做法:反向蒸馏。不是让小模型模仿大模型的完整输出,只让它模仿大模型在关键决策点上的解题路径、思考方向和纠错过程。这样小模型不需要复制大模型的全部行为风格,只需要提取其中真正能提升任务能力的部分。

具体分三步实现:

第一步,用大模型生成带中间推导的样本,但只保留关键决策轨迹,删掉冗长解释。第二步,用这些精炼轨迹做SFT,目标不是让模型背答案,而是学会“遇到某类问题先做哪件事”。第三步,用偏好对齐阶段(DPO这类方法)强化小模型真正做对的行为。

这样组合下来,一个小模型在特定推理任务上的表现,可以逼近甚至超过当初用来生成数据的那个大模型。再次提醒,这是特定任务上的超越,不是全面碾压。你要是拿它当通用助手,各种评测综合下来大概率还是打不过更大模型,但你的目标场景已经赢了。

3. 一套可复用的合成数据流水线:生成、清洗、训练的关键配置

前面讲了不少原理,这章直接给可落地的配置。假设你已经有一个底座模型,可能已经在经过人工清洗的语料上完成预训练。现在要做的,是给“目标能力提升”这件事搭一条数据流水线。

3.1 数据生成环节的关键参数

合成数据生成不是“打开模型写个prompt,攒够几个文件”就完事。真正决定数据质量的是你对生成过程的控制程度。我的参考配置如下:

  • 生成模型:直接用你能拿到的最强模型,哪怕是调用商业API也可以。生成器越强,合成数据的天花板越高。
  • 温度:多数场景设在0.7到0.9之间。温度太低,样本千篇一律;温度太高,样本失真严重。我常用0.8,配合top_p=0.9。
  • prompt模板多样性:不要只用一个模板。至少准备20-30个不同指令模板,覆盖改写、提问、补全、约束描述、示例引导等方式。模板本身就是数据增强参数。
  • 难度标签写入prompt:直接要求生成器生成某个难度等级下的问题,远比生成后再过滤更高效。

生成总量怎么定?我的建议是先做一小批,比如1万条,评估通过后再放量到50万到200万。不要一上来就生成500万条,你的过滤和去重能力大概率跟不上,最后只能眼睁睁看着低质量样本混进训练集。

3.2 数据清洗与去重:按顺序执行的四个步骤

样本生成之后,第一件正事是把无效数据清掉。我固定使用的清洗流程如下,按顺序执行:

第一步,规则过滤。长度异常短、输出被截断、重复字符比例过高、空白样本全部删掉。这类样本特征明显,用正则就能处理掉大部分。

第二步,嵌入去重。把每条样本编码成embedding,计算两两相似度,相似度超过0.85的只保留一条。注意阈值不能太宽松,否则好不容易造出来的边界样本容易被误杀。

第三步,困惑度校准。用一个与目标任务无关的通用模型计算困惑度。困惑度异常低的样本,往往来自生成器的高频偏好,要重点怀疑;困惑度异常高的大概率是噪声。

第四步,任务级校验。能程序判定就程序判定。代码数据直接实际编译或运行一次,数学题用符号计算重新推导一遍。这是成本最高但收益最大的过滤手段。

在清洗环节我踩过最大的坑,是拿“困惑度越低越好”当过滤标准。那是完全错误的直觉。低困惑度意味着模型已经能轻松预测这些内容,说明样本没有新增信息,基本是生成器的套话。真正有价值的是困惑度分布中间偏上的那一部分,在曲线上往往呈现一个驼峰,你要保留的是峰值区域而不是最低点。

3.3 训练阶段怎么用:配比、轮数与单调停止

数据准备好了,训练阶段的组合方式同样决定成败。下面这套组合我在多个项目里复用过,整体表现很稳:

  • 基础配比:真实数据70%-80%,合成数据20%-30%,这个区间能保证分布不坍缩。
  • 训练轮数:合成数据不要循环超过2个epoch。循环多了,模型会把生成器的风格学成本能。
  • 难度加权采样:训练时对样本按难度权重做采样,让少量高难度样本有更高概率被抽到。实现起来很直接,把难度权重写进采样器即可,我用的是多项式分布按难度权重做不放回采样。
  • 停止条件:在验证集上观察目标能力指标随步数的变化。如果连续2000步没有提升,果断停止,继续训练只是在过拟合合成数据。

一个小脚本示意难度加权采样:

import numpy as np # samples:样本列表,每个元素携带 difficulty 字段(1-5) # weights:按难度等级给定的权重,难度越高权重越大 weights = {1: 1.0, 2: 1.2, 3: 1.5, 4: 2.0, 5: 3.0} sample_weights = np.array([weights[s["difficulty"]] for s in samples]) sample_weights = sample_weights / sample_weights.sum() # 不放回采样,每 epoch 抽取 batch selected_idx = np.random.choice( len(samples), size=batch_size, replace=False, p=sample_weights ) batch = [samples[i] for i in selected_idx]

这套配方在数学推理、代码生成、逻辑问答几个场景下都比较可靠。

4. 翻车现场实录:典型问题与排查技巧

再好的策略,落地时也一定会遇到意外。这一章把我在多次实操中碰到的高频问题整理成速查式梳理,每个问题都附上我认为最有效的应对方式。

4.1 模型写出来的东西“AI味”很重怎么办

现象:模型说的话通顺,但就是不自然,动不动就“首先、其次、综上所述”,还爱列清单。

这大概率不是模型能力问题,而是合成数据里某一种口吻占比过高。生成器最爱输出这类“助手腔”“论文腔”文本。排查方法很直接:把训练集里文本的n-gram分布和你手里的真实用户语料做对照,找出被过度表达的句式,然后定向降采样。

4.2 训练loss降得很漂亮,但评测毫无提升

现象:loss一路向下,训练集上表现近乎完美,评测集上完全没动静。

这种情况几乎可以锁定是过拟合了合成数据。我建议先做一次数据影响力分析:随机去掉20%的合成数据,重新训练一个小步数的模型,看评测变化。如果去掉之后评测反而提升,说明数据配比里合成数据太多,或者生成器的风格已经绑架了模型的判断规则。按前面给的配比重新配一轮数据,通常能救回来。

4.3 小模型在大合成数据上崩了,怎么救

现象:小模型加入大量合成数据后,基础能力退化,连之前已经学会的常识都丢了。

这种崩法往往不是合成数据本身有问题,而是比例失衡导致模型被单分布洗脑。救援思路不是把合成数据删到0,而是做回放式增强:把模型早期训练时的优质真实样本挑出一部分,混进下一轮训练,让模型重新吸收真实分布之后再面对合成任务。经验上,真实样本占比提到50%以上,模型通常两三个epoch就能恢复。

4.4 怎么判断“该停止加数据”了

这个判断很关键。我的标准操作是做一个新鲜度测试:每向训练集加入一批新合成数据,就在固定评测集上跑一次增量训练。如果新数据带不来评测提升,说明当前合成数据已经饱和。再往上堆,就是进入“更大反而有害”的区间了。把这个步骤固化到团队流程里,能省下大量无效算力。

另外还有一个经验规律:当合成数据的去重率从最初的5%一路涨到30%以上,说明你正在反复生成相似的样本。这时不要继续扩大生成规模,应该去调整prompt模板或生成温度,去挖更偏门的样本。

5. 一些个人体会

最后说点容易被忽略的东西。合成数据的本质,不是一个“无限供给的燃料桶”,而是一个“可以被精准调节的旋钮”。真正拉开模型差距的,不是谁合成得多,而是谁更清楚该在什么地方用它、不该在什么地方用它。

我在几次项目里最有获得感的一刻,不是模型刷新了某个评测榜,而是发现通过数据切片和难度调序,就能让一个小模型在真实业务场景里站稳脚跟。这个行业已经被“多就是好”的直觉带偏过太多次,希望这篇指南能帮你避开那个最贵的坑。下次再有人说“合成数据越多越好”,你可以拿这篇文章里的对照组逻辑跟他聊两句。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进