微调的上限是由底模决定的
2024 9 30 05:19 PM 41次查看
当时的数据量只有 400 多条,为了避免过拟合,我一共只训练了 2 轮。为了避免相同的训练顺序对学习造成影响,还将两次训练集的顺序打乱了。
由于数据量很少,初始 loss 更低的 PiSSA 是非常推荐使用的,不然本就稀少的数据被用于降低初期较高的 loss,显得有点浪费。
之前那篇文章我没有说明 PiSSA 的原理,这里简单提一下:
LoRA 的原理是构造 2 个低秩矩阵,其中 A 矩阵是随机值,B 矩阵全是 0,它们相乘后再和原矩阵相加作为参数。
而 PiSSA 则是将原矩阵进行奇异值分解,也就是让分解得到的两个矩阵相乘等于原矩阵。当然,完全相等也没必要,一般会使用快速奇异值分解,让 A * B 近似于原矩阵即可。这样,我们在微调 A、B 矩阵时,初始状态更接近原矩阵(初始 loss 低),微调效果也更接近全参微调(最终 loss 低)。
我选用的验证集约 40 条,Qwen2-7B-Instruct 的 eval loss 大概能降到 0.3。
之后针对验证集中表现不好的例子,我又陆续构造了约 200 条数据。至此,eval loss 大概能降到 0.2。但继续增加数据量,却发现模型会出现教不会的现象。
顺便对比一些在线的模型:gpt-4o 和 gpt-4o-mini 大概到 0.14,glm-4-flash 大概到 0.25。
前几天 Qwen 2.5 发布了,我第一时间使用 Qwen2.5-7B-Instruct 进行了测试。啥也没改的情况下,eval loss 降到了 0.16,之前怎么都教不会的 5 个例子,有 4 个居然学会了。如此看来,更好的底模不但推理效果更好,也更容易训练。
然后我又试了下 3B 和 14B 的模型,分别是 0.22 和 0.15。其中后者在训练过程中最低能降到 0.11,但是后期可能过拟合又涨上来了。我把训练改成了 2 个阶段,先用 constant lr_scheduler_type 训练一个 epoch,再用 cosine lr_scheduler_type 训练一个 epoch,最终能到 0.125。
不过 14B 的模型不是一张 4090 能训练的了的,我用了一张 40 GB 的 A100 来训练,在 cutoff_len 为 2048 时,峰值显存占用正好 40 GB;启用 liger kernel 后,显存峰值约为 33 GB,仍然不能用一张 V100 来训练。考虑到 14B 并没有明显提升,但训练和推理成本都更高,追求性价比的话,7B 仍然是最好的选择。
在 A Closer Look at the Limitations of Instruction Tuning 这篇论文中,还有如下值得关注的结论:
- LLM 的知识主要是在预训练和持续预训练阶段注入的。
- LoRA 微调主要是学习数据集中的输出格式(风格),几乎不能学到新的知识。调整 rank(从 8 改成 2 ~ 32)和增大数据集(从万级到百万级)并没有明显的性能改善。
- 全参微调还会学习数据集中的用语(tokens),这虽然使它学到了新知识,但响应可能会因此引入与任务无关或不准确的信息,即非常容易产生幻觉。
0条评论 你不来一发么↓