最近在折腾用LoRA微调Llama3.1 8B做特定框架的代码补全。训练集是自己爬的几千条仓库代码,清洗后大概2万条样本,学习率用的2e-4,rank=16,跑了3个epoch。训练时loss从1.8降到了0.9,看着挺正常的。但eval的时候发现,模型生成的代码经常出现重复片段,甚至偶尔会输出完全无关的注释或者不闭合的括号。反而基座模型虽然不按我的格式来,但语法上是稳的。我怀疑是不是数据里噪声太多,或者学习率调大了导致灾难性遗忘?另外,我用的是QLoRA,是不是量化精度影响了生成稳定性?有没有大佬遇到过类似情况?求指点一下排查方向。
微调Llama3.1 8B做代码生成,loss降了但生成质量反而变差,咋回事?
全部回复
共 68 条这现象我太熟了,八成不是量化精度的问题,QLoRA在8B上做代码生成我试过,nf4基本不影响语法稳定性,你那个重复片段和括号不闭合更像是典型的过拟合到训练集局部模式了。你想想,2万条样本对LoRA来说其实不少了,跑3个epoch加上2e-4这种偏高的学习率,模型很容易把训练数据里的噪声当成规律死记硬背,尤其是代码补全这种任务,一旦记住了某些仓库的缩进风格或注释习惯,生成时就会机械复读。我建议你先看看验证集上的loss曲线,如果验证loss在某个epoch后开始回升,那就是过拟合没跑了,赶紧降到1个epoch或者把学习率调成1e-4试试。另外你说数据爬下来清洗过,但有没有做过去重和过滤?代码里那些重复的import片段、空函数体、或者格式错乱的注释都是重灾区,我上次就是没过滤干净,模型愣是学会了连续输出十几个空行。还有个排查方向是看生成时的采样参数,temperature调低到0.1或者0.2,top_p也收紧点,能明显减少重复输出,基座模型语法稳是因为它没见过你的特定格式,反而不会陷入局部模式。先别急着怀疑量化,把数据质量搞干净,训练轮数砍半,大概率能解决。
这情况多半是数据重复度高或者没清洗干净,LoRA学到的是表面模式。建议先查下训练集里相似代码块的占比,另外把学习率降到5e-5试试。
这情况我遇到过,八成是数据重复片段太多,LoRA把噪声模式学进去了,先清洗下数据试试。
我之前跑类似任务也踩过这个坑,loss降了真不一定代表生成质量好,尤其代码这种结构化输出,重复片段和括号不闭合更像是模型学到了表面模式但没抓住语法约束。建议先查下数据清洗,2万条里如果噪声比例高,LoRA很容易被带偏。另外2e-4配rank16对8B来说可能偏激进,试试降到1e-4或者把epoch减到1,看eval曲线有没有变化。QLoRA的量化精度一般不会直接导致这种结构性错误,除非你用了特别低的bit配置,现在4bit正常来说够用。可以先拿基座模型在你那2万条上做个perplexity对比,如果基座反而更好,那大概率是训练策略问题,不是数据本身。
我之前跑代码模型也踩过类似的坑,loss降了但生成重复片段大概率不是量化的问题,更像是数据清洗不够干净,比如注释和代码混在一起没处理好,模型学到的是片段拼接而不是逻辑。可以试试把训练集里重复率高的行过滤掉,或者把样本长度截断到512以内再试一轮。另外2e-4对LoRA其实偏高,我降到8e-5之后稳定性明显改善,灾难性遗忘会轻很多。建议先不换量化,直接拿基座生成几条对比下,确认是不是数据分布带偏了。
你这个现象挺典型的,loss降了不代表生成质量好,尤其代码任务里loss对格式错误和重复惩罚不敏感。我建议先拿基座模型跑几个eval样本对比下,确认是不是LoRA把原本的语法分布带偏了。QLoRA的量化噪声在低rank下确实可能放大,但更可疑的是2万条样本对特定框架来说太少,而且爬的代码如果没去重或过滤,重复片段会被模型学成惯性。试试把学习率降到5e-5,rank提到32,再只跑1个epoch看下;另外检查下数据里有没有不闭合的括号或注释残留,这种噪声很容易让模型学到坏模式。
loss降到0.9不代表模型学到了你想要的结构,我怀疑是数据里重复模式太多,LoRA把那些高频噪声当成特征死记了,代码补全里常见的重复片段就是这么来的。建议先做一下去重和清洗,特别是删除那些只改个变量名就重复的样本,顺便看看eval时是不是用了teacher forcing,如果是自回归生成那问题可能更明显。QLoRA的量化确实会让输出抖动,但一般不会导致括号不闭合这种低级错误,我更倾向于认为你学习率开高了,2e-4对8B来说偏激进,试着降到1e-4或5e-5跑一个epoch对比下。另外可以拿几个训练集里的样本做插值测试,如果模型能完美复述但泛化差,那基本就是过拟合到数据噪声了。
2万条样本对代码生成还是太少了,LoRA学到的模式固化导致重复,建议先加数据再调lr。