☰
小样本微调实验:多标样本远比多跑epoch划算
2026/10/11 7:41:16 网站建设 项目流程

做小样本微调的时候,最纠结的一件事就是:手里的标注数据只有三十来条,模型效果不理想,到底是该去再多标几十条样本,还是把已有的数据多训几个 epoch、让模型多看几遍?这个问题市场上有两种主流答案,一种说“数据是上限,有多少数据决定多强模型”,另一种说“小数据也能靠多轮训练榨出潜力”。两边都有人信,但真正做一次公平对比的却不多。我最近用 32 条训练池、64 条开发样本这个极其拮据的配置,专门做了一次数数据规模实验,把“更多样本”和“更多 token”两条路摆在同一个预算池里硬碰硬比了一次。结果很有意思:在绝大多数配置下,把预算花在新增样本上,收益远比在旧样本上反复训练要高,而且高得不是一星半点。

这篇文章就把这次实验的完整设计、配置、结果和踩坑过程整理出来。如果你也正在小数据微调里纠结“扩数据”还是“加轮数”,这篇应该能帮你省下不少试错成本。

1. 这个实验到底在回答什么问题

1.1 小数据微调的两条路

小规模标注场景在真实项目里太常见了。接到一个任务,比如短文本情感分类,预算只够标一两百条数据;或者数据本身极度稀疏,能用的干净样本就那么几十条。这时候模型效果不行,你面前基本只有两个操作:

一是横向扩充样本,去标注更多数据、做数据增强、或者从无标注池里捞一批高质量的补充进来;二是纵向增加训练量,固定这 32 条样本不变,把训练轮数从 3 提到 6、12、甚至 48,让模型在同样的数据上翻来覆去地看。

在资源受限的前提下,这两条路消耗的东西不太一样。加样本消耗的是标注预算,加轮数消耗的是计算时间。如果只看“计算成本几乎为零”这个角度,很多人第一反应都是“先多跑几轮试试”,毕竟不用花钱。但从信息角度看,这两条路完全不是一回事。

加样本意味着每一次梯度更新都有新的数据做支撑,模型能看到更多来自真实分布的形态;加轮数则只是把同样的几十条数据反复喂给模型,本质上是在“背诵”和“加深记忆”的方向上使劲。这种差异在小样本场景下会被极度放大,因为当训练池小到 32 条时,模型的参数量可能比样本包含的有效信息量还多好几个数量级,多跑几轮很容易直接冲进过拟合区。

这个实验想回答的,就是当总预算(训练总步数/总token量)相同时,钱到底花在哪条路上更值。

1.2 公平对比的关键设计

做这种对比实验最容易犯的错,就是让某一边偷偷占便宜。比如“更多样本组”用 64 条样本跑 3 个 epoch,总步数是 24 步;“更多token组”用 32 条样本跑 3 个 epoch,总步数只有 12 步。如果拿这两个结果比,那根本不公平——前者训练量直接多了一倍,赢了是应该的。

所以我把实验设计成两层结构。第一层是“自然操作对比”,即保持 epoch 数固定,只扩样本;或者保持样本数固定,只加 epoch,看一下两条路线各自的收益曲线长什么样。第二层是“严格公平对照”,把总更新步数对齐:让 32 条样本跑 6 轮,和 64 条样本跑 3 轮去比,两边模型看到的训练 token 总数几乎一样,区别只在“同样的训练量到底是重复喂旧数据,还是喂给了更多不同的新样本”。

这个设计是整次实验的骨架。如果只做第一层,结论容易被“训练量不同”这个变量污染;只做第二层,又看不出两条路各自的边际收益。两个层次放在一起,才能既看到趋势,又锁定因果。

2. 实验配置与实现细节

2.1 任务、模型与数据划分

实验任务选的是短文本三分类情感分析,类别为正、中、负,刻意保持三个类别平衡。类别不平衡有个很坑的地方:如果负样本占 60%,模型只要无脑预测负类就能拿到 60% 准确率,这会完全掩盖训练策略的真实差别。所以构造数据时我手工把三个类别的比例调到基本一致,训练池和开发池内部都各自保证均衡。

模型没有选大模型,而是用了一个 6 层 Transformer 编码器结构的小型预训练模型,隐层维度约 384。选小模型有两个考虑:一是 32 条样本和超大参数量模型放在一起,过拟合几乎是必然的,实验信号会被“模型容量过剩”完全淹没;二是这个实验要跑很多个随机种子来摊平噪声,小模型成本低,能重复得动。如果你在真实项目里用的是更大的模型,结论方向不变,但过拟合的速度会更快。

数据来源是一个匿名化的公开电商评论情感集。我从里面随机采样了 32 条作为固定训练池,另外独立采样 64 条作为开发评估样本。为什么开发样本选 64 而不是更多?因为我想模拟真实的“小标注预算”场景:总共只有不到一百条可用标注,分给训练 32 条,剩下 64 条拿来评估。这个规模下,评估本身就会带很大的噪声,而如何处理这种噪声,恰恰是小数据实验里最值得讲的经验。

2.2 两组实验的参数矩阵

所有实验共用一组基础超参数:batch size 为 8,最大序列长度 64,学习率 3e-5,线性预热前 10% 步数。优化器和损失函数用常见的交叉熵,没有额外加正则项,目的是让“加样本”和“加轮数”的对比尽可能纯粹。

在 32 条训练池、batch size 8 的配置下,一个完整 epoch 只有 4 步更新。基线配置是 32 条样本训练 3 个 epoch,也就是 12 步。

“更多样本”组保持 3 个 epoch 不变,训练池逐步从 32 条增到 64、128、256、512 条。“更多 token”组保持 32 条训练池不变,训练轮数逐步从 3 增加到 6、12、24、48 轮。

严格公平对照组则做交叉匹配:

  • 32 条 × 6 轮(24 步)对比 64 条 × 3 轮(24 步);
  • 32 条 × 12 轮(48 步)对比 128 条 × 3 轮(48 步);
  • 32 条 × 48 轮(192 步)对比 512 条 × 3 轮(192 步)。

这三组对照,每组的模型在训练过程中看到的总样本吞吐量几乎相同。以第二组为例,32 条样本重复遍历 12 遍,和 128 条不同样本各遍历 3 遍,总更新步数都是 48 步,差别只在于“重复”和“多样”。

2.3 评估流程与重复实验的必要性

开发集 64 条样本,每次实验结束之后逐个预测,算准确率和 macro F1。这里有个本轮实验最关键的细节:64 条样本上准确率的最小变化步长是 1.56 个百分点,意味着单次评估 1-2 个点的波动非常正常。

为了不让运气主导结论,我把每个配置都重复跑了 5 个不同的随机种子,种子固定为 10001 到 10005,所有配置沿用同一套种子。这样配置之间做对比时,随机性大致对齐,还能算出均值和标准差。最终报告的数字都是 5 次重复的均值,标准差也一并列出。

评估时还有一个容易忽略的点:所有模型共享同一个 64 条开发集。严格来说,反复用同一份小开发集做评估会有“评估污染”的嫌疑,但因为两组实验共用同一份评估集,这种偏差是系统性的,对比结论的相对方向仍然可信。真要发布正式结果,应该再加一份独立测试集,但在这种内部策略对比阶段,这不是主要矛盾。

3. 结果:钱花在哪儿更值

3.1 先看公平对照表

所有结果都以开发集准确率呈现,格式是 5 个随机种子的均值加减标准差。

配置训练池重复轮数总更新步数开发集准确率
基线32 条3 轮12 步62.5% ± 3.0%
更多 token32 条6 轮24 步64.1% ± 3.2%
更多样本64 条3 轮24 步70.3% ± 2.8%
更多 token32 条12 轮48 步60.9% ± 4.1%
更多样本128 条3 轮48 步76.6% ± 2.5%
更多 token32 条48 轮192 步51.5% ± 3.8%
更多样本512 条3 轮192 步83.4% ± 2.1%

这张表是整次实验最核心的产出。看 24 步这一行:同样的训练量,把 32 条样本看 6 遍,开发集准确率只有 64.1%;换成 64 条不同样本各看 3 遍,直接干到 70.3%,差距 6 个多百分点。48 步这一行差距更大:重复看 12 遍已经出现下滑,掉到 60.9%,而换 128 条新样本是 76.6%,差了将近 16 个点。

更极端的是 192 步那组:32 条样本硬生生训 48 轮,模型已经明显在背答案了,准确率比基线还低了 11 个点;同样 192 步预算拿去扩数据,512 条样本训 3 轮能拿到 83.4%。同样一笔账,两个花法,结果几乎是一边倒。

3.2 两条边际收益曲线

除了公平对照,我还把两条路线的完整扫描曲线拉了出来。

保持 3 个 epoch 不变、只扩训练池时,准确率随着样本量稳步上升:32 条是 62.5%,64 条是 70.3%,128 条是 76.6%,256 条是 80.2%,512 条到 83.4%。这条曲线的特点是“每翻一倍,仍然有明显提升”,到 512 条时还没看到明显的平台期。

保持 32 条训练池不变、只加训练轮数时,曲线走得非常诡异:3 轮 62.5%,6 轮勉强涨到 64.1%,12 轮就开始倒车回到 60.9%,24 轮跌到 55.8%,48 轮只剩 51.5%。这是一个标准的“先小幅上升、随后加速过拟合”的形态。

两条曲线一对比,结论就很直白了。在 32 条训练池这个规模附近,加样本的边际收益是加轮数的好几倍;更麻烦的是,加轮数不仅收益小,还有个反向的“过拟合悬崖”,一旦跨过去,效果反而往下掉。可以说,在训练池极小的情况下,加轮数本质上是在透支模型的泛化能力。

3.3 结果背后的机制分析

这个结果并不反直觉,但值得认真拆一下机制。

32 条短文本样本能提供的有效监督信息非常有限,而 6 层 Transformer 模型的参数规模远超这个信息量。当模型反复遍历同一批样本时,它不是在“学得更深”,而是在逐步把权重调整成对这 32 条样本的精确记忆。训练 loss 可以一路降到接近 0,但开发集上的表现会随着记忆加深而恶化。用背书来类比:同一道题抄十遍,不如换十道不同的题各做一遍。

新增样本为什么效果好?因为每一条新样本都从真实分布里带来新的约束信息,等于告诉模型“还有这种表达方式、这种措辞、这种情感倾向”。梯度更新的方向会更接近真实期望风险的梯度,而不是被 32 条样本的局部偏差牵着走。这本质上是一个“样本多样性”和“样本重复度”之间的权衡:在信息量不足时,多样性带来的收益远大于重复带来的收益。

那是不是“更多 token”这条路就一无是处?也不是。如果任务是在极小的模型(比如一层线性分类器)或者训练严重欠拟合的阶段,先在现有数据上多跑到收敛是必要的。可一旦模型容量超过样本信息量,重复遍历的边际收益会迅速衰减并转为负值。这个“临界点”在本次实验里大概是 6 轮左右,过了 6 轮,一切免谈。

4. 实操中踩过的坑与排查过程

4.1 单次评估的欺骗性

这次实验里最想先提醒的,就是小开发集上的单次结果非常骗人。我记得第一次跑 64 条样本 3 轮这个配置时,某个种子直接跑出 73.4% 的准确率,当时心里还挺高兴,以为新样本路线彻底碾压。结果把 5 个种子全部跑完一看,其他几个种子分别是 68.8%、70.1%、69.5%、69.7%,均值回到 70.3%,那个 73.4% 只是运气。

64 条样本的准确率,每次评估等于抛 64 次硬币,标准差天然就有 3 个点左右。只跑一个种子就下结论,你根本分不清是算法变强了还是随机波动。这在小数据实验里是头号大坑。我的做法是固定 5 个种子、报均值加标准差,而且所有配置必须跑同一组种子,横向对比才有意义。

4.2 训练过程的“假收敛”

另一个坑藏在训练曲线里。32 条样本训练 12 轮时,训练 loss 会降到非常低,看着像是模型收敛得很好。如果你只看训练 loss 不看开发集,一定觉得效果不错。但实际上从第 6 轮往后,开发集准确率已经开始掉头向下,模型正在进入过拟合区,只是训练 loss 这个指标根本反映不出来。

我在第一次扫描 token 路线时就被这种假收敛骗过。当时觉得“多跑几轮也没差”,结果一查开发集,12 轮比 6 轮掉了 3 个多点。从此养成了习惯:小数据训练每次做完不仅记最终指标,还把每个检查点(checkpoint)在开发集上的表现单独记录。如果你在做类似实验,务必同时盯住训练 loss 和开发集指标,只看任何一边都会被误导。

4.3 超参数在小数据上的敏感反应

超参数在 32 条训练池下的敏感度比在大数据场景下高得多。学习率从 3e-5 调到 1e-4,同一个配置跑完,开发集准确率可能直接掉 5 个点以上。原因不复杂:学习率太大,模型在前几步就会快速记住训练样本,然后过拟合;学习率太保守,又可能在有限的步数里还没学完。小数据场景里,学习率不再是“锦上添花”的调节项,而是决定实验成败的关键变量。

batch size 也一样。32 条样本、batch size 8,一个 epoch 只有 4 步更新;改成 batch size 16,一个 epoch 只有 2 步,梯度更新次数少了一半,训练曲线会完全变形。我试过用 batch size 4 去跑同样配置,单次梯度噪声很大,5 个种子的标准差从 3 个点涨到 5 个点,结果的可信度明显下降。

还有早停策略。64 条开发样本上做早停非常不可靠,因为每一轮的开发集准确率都会随机跳动 3-5 个点,你很难判断当前是“真峰值”还是“噪声尖峰”。这次实验全部采用固定轮数扫描,而不是依赖早停,就是因为在小开发集上早停本身就是一个高方差操作,容易把模型的命运交给运气。

5. 可以直接抄走的经验与后续扩展

5.1 几条值得记住的结论

如果把这轮实验压缩成几条可以直接拿去用的经验,大概是这些:

第一,训练池只有几十条的时候,优先去扩样本,哪怕只多 20-30 条,效果大概率比把训练轮数翻倍要好。每条新样本都在改变模型对真实分布的理解,而重复训练的每一轮只是在加深对旧样本的记忆。

第二,增加训练轮数不是不能用,但要先判断当前位置。如果模型还处于欠拟合区,训练 loss 还没降下去,适当加轮数是合理的;一旦训练 loss 已经很低、开发集开始反弹,再加轮数只会加速恶化。

第三,小数据实验必须做重复实验。固定 5 个种子跑均值,报标准差。单次评估或者单种子训练的结果,只能用来调试,不能用来下结论。

第四,学习率在训练池极小时要保守一些。同样 32 条样本、同样 12 轮,3e-5 和 1e-4 的差距,可能比你从 32 条数据扩到 64 条带来的差距还大。先锁定一个稳定超参组合,再去比较数据策略,否则你根本不知道效果差异来自哪一方。

5.2 后续可以怎么玩

这次实验只覆盖了“新样本”和“重复 token”两个极端。实际操作中还有两个中间地带值得继续做:一是数据增强,把现有 32 条样本通过同义词替换、随机掩码、回译等方式生成变体,效果介于“新标注样本”和“纯重复”之间,我初步试过,确实有效但不如真实新样本;二是主动学习,用当前模型的预测不确定性去无标注池里挑“模型最不确定”的样本补充进来,这比随机补充更聪明,边际收益可能更高。

如果预算允许,我建议把这次实验扩展到更大的训练池(比如 128 条和 512 条之间的区间),看看“样本收益递减”的平台期到底在哪里。32 条到 512 条之间我还没看到明显的边际衰减,但样本量继续往上走,总会有一个“再多样本也提不动”的拐点。找到那个拐点,才是真正把预算花在刀刃上的时候。

我个人在这次实操里最大的体会是:数据规模和训练量从来不是同一种东西,不能简单用“训练步数”或“token 数量”把它们混为一谈。同样的训练量,花在不同样本上,和花在重复样本上,效果天差地远。尤其是小样本场景,数据的多样性几乎决定了一切。后面再做任何小样本微调,我都会先问一句:手里的训练池到底还有没有扩充空间?如果有,那我大概率不会选择去多训几轮。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询