最近想把手上的一个内部工单分类任务做一下,数据大概几千条,用的Qwen2.5-7B。一开始直接用了Lora,跑完一个epoch之后,效果还行,但发现一个很奇怪的问题:模型在推理时几乎不输出“其他”这个类别,哪怕测试集里其他类的占比高达30%。我怀疑是不是数据不平衡导致,尝试过过采样,也把loss改成过focal,但效果还是差不多。现在又试了全参数微调,跑了两天,结果更离谱了,模型开始疯狂输出换行符和重复的“好的,根据您的描述”。请问是学习率太大导致灾难性遗忘,还是说我的数据格式(用的是sharegpt格式)有问题?有类似经验的兄弟能指点一下吗?
微调Qwen2.5-7B之后,模型只会输出了,求大佬们看看哪里不对
全部回复
共 73 条我之前微调别的模型也遇到过类似只输出固定类别的问题,后来发现是数据里“其他”类的样本虽然数量够,但文本特征太杂,模型反而学不到统一模式。你试试把“其他”类单独做下聚类或者筛选一些代表样本,别一股脑全塞进去。全参数微调那个疯狂输出换行符的情况,大概率是学习率太高了,降到1e-5以下再看看,另外检查下数据格式里有没有空的system字段,我之前就是这坑。
全参数微调遇到输出崩坏大概率是lr太高了,试试降到1e-6以下,另外输出重复可能是SFT数据里“其他”类样例太少导致的。
看到你这个情况我太有共鸣了,之前调一个意图分类模型也遇到过类似的鬼打墙。全参数微调跑两天出来疯狂吐换行符和"好的,根据您的描述",这个我熟,大概率不是学习率的问题,而是数据格式里对话模板和response字段没对齐,Qwen对sharegpt里的system和user拼接特别敏感,你试着把模板换成它官方推荐的chatml格式看看。另外你说focal loss和过采样都没用,我怀疑问题不在类别不平衡,而在"其他"这个类的样本本身语义太散,模型学不到一个紧凑的决策边界,你试试把其他类的样本按关键词聚类后再拆成几个子类,或者干脆在训练时把其他类的loss权重单独调高到3倍以上。还有个坑,你检查下推理时的采样参数,temperature太高或者top_p太小会让模型倾向输出高频token,而"其他"这个词如果训练时在标签里出现频率低,生成时很容易被吞掉,建议推理时直接禁用采样或者用greedy解码。最后补一句,几千条数据全参微调7B确实容易过拟合,我后来是冻结前12层只训后面几层才稳住,你可以试试。
遇到过类似情况,多半不是数据格式的锅,sharegpt格式本身没问题。你全参数微调那个输出重复文本的现象,基本可以确定是学习率太高了,试试降到1e-5以下,或者直接用LoRA但把rank调大点,比如64,同时加个early stopping。至于“其他”类不输出,光过采样可能不够,建议把这类样本在训练时单独加权,或者干脆在推理时调整temperature和top_p,让输出分布更均匀些。另外确认下你的“其他”类样本是不是本身文本特征太杂,模型学不到有效模式,这种时候可以适当合并一些相似小类。
我之前也踩过类似的坑,全参数微调两天那个情况大概率是lr太高了,Qwen系列对lr特别敏感,你试试降到1e-5甚至5e-6,然后加个warmup和梯度裁剪,一般能救回来。不过你那个“只输出其他”的问题,我怀疑不单是数据不平衡,更可能是你sharegpt格式里system prompt或者instruction写得不够明确,模型没理解“其他”是一个需要主动选择的类别。我自己做分类任务时,会在用户消息里明确列出所有类别选项,比如“请从以下类别中选择:工单类型A/B/C/其他”,这样模型会更容易对齐。还有一点,几千条数据用LoRA其实够用,但你可能要检查一下是否所有类别在训练集里都有足够多的代表样本,过采样如果只是简单复制,模型容易过拟合到重复样本,反而学不到泛化特征。focal loss我也试过,但alpha和gamma要调,默认参数经常没用。你不如先做一次类别分布的可视化,看看是不是有些标签本身就带噪声,比如“其他”类里的文本和其他类别语义重叠很严重,那样模型学起来会非常困惑。
你这个问题我之前在别的模型上也踩过坑,全参微调跑太久很容易把底座能力冲掉,Qwen这种7B尤其敏感,疯狂输出重复和换行大概率是lr太高或者epoch多了,建议先降到1e-5以下试试,甚至用cosine衰减。至于“其他”类不输出,我怀疑不是单纯类别不平衡,你那30%的占比不算低,可能是标签定义太模糊,模型学到的是“其他”=“不确定”,所以倾向不选,可以试试把“其他”改成一个更具体的虚拟标签比如“其他-无法归类”,然后在system提示里加一句“当无法确定时输出其他”。另外sharegpt格式本身没问题,但几千条数据用全参微调确实容易过拟合,我建议还是回到LoRA,把rank加到64或者128,然后只训2-3个epoch,中间加个early stopping看验证集loss。还有一个细节,你推理的时候temperature是不是调太高了?如果大于0.8,模型很容易生成废话,建议固定成0.1再测一轮。如果还不行,可以看看是不是tokenizer对中文标点处理有问题,导致模型学到换行符作为分隔模式,这个我之前在别的模型上遇到过,改下padding策略就好了。
我遇到过类似的,全参数微调崩掉大概率是学习率太大了,Qwen系列用1e-5都算偏高,你可以试试降到2e-6或者1e-6,另外把max_length设成512以下,不然空白符会被疯狂放大。至于“其他”类不输出,光改loss没用,我后来是把这类样本的system prompt里显式加了“如果无法归类请输出其他”,再配合随机丢弃一些多数类,效果才正常。你那个sharegpt格式本身没问题,但可以检查下是不是“其他”类的回复文本和其他类别长度差异太大,模型学到的是长度偏好而不是内容。
类别不均衡不是主因,试试把“其他”类样本在训练时重复几遍,或者调下生成参数里的repetition penalty。
全参数微调两天出这种情况大概率是lr太高了,7B全参一般得跑到3e-6以下,你试试把lr降到1e-5再配个warmup,另外观察下loss曲线是不是在震荡。数据格式倒不太像主因,但sharegpt里角色标签别搞混了,系统提示词里最好明确写死“其他”类别的判定规则。还有个思路,你可以在推理时把“其他”类别的logit bias调高一点,或者干脆在训练数据里把其他类的样本权重再加大两倍看看。
我之前也遇到过类似情况,模型学偏了之后特别容易盯住某个高频输出不放。你换全参微调后疯狂输出换行和固定话术,八成是学习率太大把原始能力冲掉了,建议先降到1e-5以下试试,另外epoch别贪多,两三个就够。数据格式sharegpt应该没问题,但工单分类这种任务,建议把“其他”类样本单独做一下增强,或者干脆在系统提示里强调一下可输出类别,让它别老想着复读。还有,你可以看看是不是tokenizer把换行当成了特殊标记,有时候这个小细节很坑。
跑全参前先查下数据里“其他”类的标签在模板里是不是被截断了,我之前也栽在这上面。
我之前也踩过类似的坑,全参微调跑太久特别容易崩,输出乱码和重复基本就是lr太大或者数据没mask对,建议先降到1e-5试试。另外“其他”类不输出这事儿,光靠过采样和focal不一定管用,可以看看是不是prompt里给“其他”的定义太模糊,模型学不到边界,试着在训练样本里把“其他”类的描述写得再具体点,比如加几个典型子类的例子进去。还有ShareGPT格式本身没问题,但要注意system和user的role别搞混,不然模型容易把指令当生成内容。
这现象挺典型的,先查下是不是评估时把其他类别的标签弄丢了,我之前也栽过这坑。
之前调分类模型也遇到过类似情况,尤其是“其他”这种低频但占比不低的类别,光靠过采样和focal有时候真压不住。你试试在loss里对“其他”单独加权重,或者用温度缩放调整输出概率,可能比改loss更直接。全参微调那个疯狂换行的问题,大概率是学习率太大或者数据里混了太多padding,把学习率降到1e-5以下,顺便检查下模板里的特殊token是不是被模型学到了。另外sharegpt格式本身没问题,但你可以确认下角色标签是不是全对上了,有时候模型会把“其他”当成指令词给过滤掉。
我之前也踩过类似的坑,尤其是“其他”类不输出这个现象。你试试看推理的时候把温度调到0.1或者干脆用贪心解码,有时候是采样策略的问题,模型其实学到了这个类别,只是概率分布偏平,采样时容易被别的类压过去。另外你提到全参数微调后疯狂输出换行和重复话,这基本就是学习率太大了,7B模型全参微调一般建议1e-5起步,你如果用了2e-5以上很容易崩,特别是数据量才几千条。还有数据格式,sharegpt格式本身没问题,但得确认你的system prompt里有没有明确告诉模型“只能从给定类别中选择”,如果没有,模型就会自由发挥。你可以先拿测试集里“其他”类的样本单独喂给原始模型看看,如果原始模型能正常分类,那就是微调过程中把这类样本的特征给冲掉了。另外focal loss对这类问题帮助有限,它主要解决难易样本不平衡,不是类别先验偏差,你可以试试在loss里给“其他”类加个权重系数。最后建议你把全参数微调的checkpoint加载回去,只训lora,但把lora的rank调高一点到64,epoch别超过3个,观察一下验证集loss是否在第二epoch后回升。
遇到过类似的,全参微调疯狂输出重复内容大概率是学习率太大,试试降到1e-5甚至5e-6,另外max_seq_len别太长,不然模型容易飘。关于“其他”类不输出,建议检查下sharegpt格式里system提示词是不是把类别定义写得太死了,我换成自然语言描述分类标准后改善挺明显,过采样和focal其实对这类问题帮助有限。
之前跑分类任务也遇到过类似输出塌陷的情况,全参微调那种重复输出大概率是lr太高加数据量不够,7B模型两天确实容易崩,建议先降到1e-5试试。另外“其他”类不输出不一定是loss函数问题,检查下模板里是不是把“其他”写成了特殊token,或者推理时采样参数温度调太低导致概率被压没了。我上次用sharegpt格式也出过问题,后来改成alpaca加system提示指定输出范围就好了,你可以对比下两种格式在验证集上的logits分布。
全参数微调两天那个输出换行符和“好的”,大概率就是lr太大把预训练权重冲没了,我遇到过类似的,建议先降到1e-5以下试试。另外“其他”类不输出,除了数据不平衡,也可能是这个类别在模板里的表述和别的类差异不够大,模型学到的是表面模式,可以试试把“其他”类的指令描述写得更具体一点,比如加个“无法归入以下类别时”。还有sharegpt格式本身没问题,但我之前用alpaca格式效果反而稳一些,你可以对照着排查下数据里有没有空轮次或者角色标签错乱。
全参数微调两天出现疯狂重复输出,大概率是学习率太高直接把原始能力冲垮了,建议先降到1e-5以下试试,或者干脆回到LoRA调优。另外“其他”类不输出不一定是数据不平衡,也可能是你构造的指令里对“其他”的定义不够明确,模型学不到这个边界。我之前做分类任务时,把“其他”类样本在system prompt里单独强调一下,再配合一点数据增强,效果比换loss明显。你用的是sharegpt格式的话,可以检查下有没有把标签放在assistant回复里,有些格式不一致会导致模型学串。
数据格式大概率没问题,但全参微调两天还复读,八成是学习率飙了,建议降到2e-5以下试试。