最近在拿Llama3-8B做中文情感分析微调,用的QLoRA,数据集大概1万条电商评论,二分类(正向/负向)。训练时loss从2.1降到0.8,看着挺正常,但验证的时候发现模型几乎把所有句子都预测成“正向”。我检查了数据,正负样本大概是平衡的(5.5:4.5),也试过调学习率(从2e-4降到1e-5)和增加epoch,结果差不多。我怀疑是不是prompt格式的问题?我用的模板是“评论:xxx 情感:”,但模型好像没理解任务。另外,我用的LoRA rank=8,alpha=16,target_modules只改了q_proj和v_proj,是不是需要改全连接层?有没有大佬遇到过类似情况?想知道是数据的问题还是我哪里设置得不对,求指点,谢谢。
微调Llama3做中文情感分析,loss降了但预测全是一个标签,怎么回事?
全部回复
共 30 条我之前跑类似任务也翻过车,最后发现是prompt里少了明确的指令性描述,模型根本不知道“情感:”后面该接啥,你试试把模板改成“请判断以下评论的情感倾向,只输出正向或负向:xxx”。另外QLoRA只改q和v确实可能欠拟合,把gate_proj和up_proj也加上会稳很多,尤其中文任务对MLP层的依赖比想象中大。还有个坑是验证集如果和你训练时的分布不一致,比如混入了大量中性样本,也会导致模型摆烂全选多数类,建议抽几十条人工看下预测概率分布,别只看标签。
我之前做类似任务也踩过这个坑,loss降了不代表模型真学会了任务,很可能是在学“频率捷径”。你正负样本虽然平衡,但如果训练时模型发现输出“正向”的loss更低,它就会无脑选性价比高的那个。建议你直接看训练集上的预测分布,如果训练集也全正,那就是模型欠拟合或指令没对齐,可以试试把模板改成更明确的“以下是评论,请判断情感是正向还是负向”这种完整指令。另外target_modules只改q和v确实可能不够,加上gate_proj和down_proj试试,我上次加了之后效果变化挺明显的。还有个土办法,拿几条训练样本跑推理,打印logits看看正向和负向的分数差距,能帮定位是不是输出层偏置了。
遇到过类似的情况,当时我也差点被loss骗了。你loss降到0.8其实说明模型在拟合训练集,但验证时全预测正向,大概率是模型没真正学会“判断情感”这个指令,而是在瞎猜高频类别。你数据平衡5.5:4.5,但模型可能发现全输出正向的loss也不高,因为负向样本只占45%,牺牲这部分换训练集的低loss也划算。
我觉得问题很可能出在prompt设计上,你那个“评论:xxx 情感:”的模板太简单了。我试过给Llama3做中文任务,它本身对中文指令的理解就偏弱,最好在系统提示里明确写清楚“你是情感分析助手,只输出正向或负向”,并且few-shot给几个例子,哪怕给2-3个都行,模型才知道你要它干什么。
另外target_modules只改q_proj和v_proj确实可能不够,我经验里至少要加上gate_proj和up_proj,甚至把全部linear层都改了效果才稳。LoRA rank=8可能也偏低,尤其对8B模型,试下rank=16或32。
还有个坑是数据顺序,你有没有shuffle?如果负向样本总在batch末尾,模型可能没充分学过。建议用sklearn的train_test_split做stratify,然后训练时shuffle=True。
最后验证下你评估方式,是不是用了模型生成的token来映射标签?有时候模型会输出“正向”但带个换行或空格,你解析时没处理好,导致所有预测都落到默认值。建议打印几条验证集原始输出看看。
这情况我也踩过坑,八成是数据里正向样本的措辞特征太明显,模型偷懒直接学偏了,试试把负样本里加些“虽然但”这类转折句式。
另外你只调了q和v,建议把gate和up也加上,我之前这么改后分类准了不少。
我之前跑类似任务也翻过车,问题多半出在数据没洗干净,比如标签噪声大或者有隐藏的文本模式,模型学了个捷径直接吐正向。建议抽50条预测错误的样本看看输入输出,大概率能发现规律。
另外你只改了q和v确实可能欠拟合,LoRA最好把gate_proj和up_proj也加上,尤其分类任务对FFN层敏感。还有,QLoRA下先冻结tokenizer试试,中文分词有时候会干扰指令理解。
最后怀疑一下模板,我原来用“评论:xxx情感:”也死活学不会,后来改成“用户说:xxx\n该评论情感倾向是:”立马正常了,你换个带标点或换行的格式看看?
我之前跑类似任务也翻过车,问题多半出在数据标签噪声上,你查查有没有大量“正向”样本其实很中性,模型学到的是默认输出。另外QLoRA只改q和v确实可能欠拟合,建议把gate_proj和up_proj也加上试试,rank提到16。还有个小坑:中文分词后label和text之间别用空格,直接“评论:xxx\n情感:”可能更稳,你可以拿几条训练集喂进去看看生成概率。
我之前也踩过类似的坑,loss降得漂亮但输出单一,大概率是模型在“摆烂”学捷径。你试试把标签放在输入前面,比如“情感:正向。评论:xxx”,或者加一句“请判断以下评论情感”的任务描述,效果会差很多。另外target_modules只改q_proj和v_proj确实可能不够,建议把gate_proj和down_proj也加上,LoRA的表达能力会强不少。还有个小细节,检查下验证集里有没有大量重复或模板化的句子,有时候数据泄漏也会导致这种假象。
我之前也踩过类似的坑,loss降了但输出单一,大概率不是数据平衡的问题,而是模型压根没学会指令跟随。你试试把prompt改成更明确的中文指令,比如“判断这条评论的情感倾向,回答正向或负向”,别用简短的填空式模板,Llama3对任务描述不敏感时容易偷懒。
另外target_modules只改q和v确实可能不够,建议加上gate_proj和down_proj,LoRA的容量大了模型才有多样性输出的空间。还有个细节,检查下你的验证集是不是在生成时设了do_sample=False,贪婪解码如果概率分布偏向正向就会全选它,可以看看预测概率的分布情况。
我之前也碰到过一模一样的情况,loss降得好看但预测全偏向一边。后来发现是数据里虽然正负比例接近,但“中性”或者模糊样本被强行标成负向,模型其实学的是表面词汇分布而不是情感逻辑。你可以试着抽几条预测错的样本看看输入输出,确认是不是prompt里“情感:”后面没给明确约束,模型默认生成概率高的正向词。另外target_modules只改q和v确实可能欠拟合,建议把gate_proj和up_proj也加上试试,我加了之后效果有明显变化。
试试把target_modules加上gate_proj和up_proj,只调q、v太保守了,我上次也这样全预测一个类。