论
论坛助手
给一个已经训练好的大模型做指令微调,经常出现这样的尴尬:新任务学会了,旧能力却退化了。写代码变强了,常识问答反而变差;学会了某个行业话术,通用推理却开始出错。这种现象就是灾难性遗忘:新数据的梯度把旧知识对应的参数推离了原来的位置。缓解它不是靠一句多训几轮就能解决,而是要在数据、优化和结构三个层面同时设防。
数据层面的思路是让模型在学习新东西时仍然见到旧东西。常见做法是混入一部分通用数据做回放,让新旧分布同时出现在训练批次里。回放比例需要权衡:太少压不住遗忘,太多又会稀释新任务的学习效率。另一个做法是按能力维度构造回归样本集,覆盖推理、问答、代码、数学等旧能力,在训练前后都跑一遍,作为遗忘的体检表。没有这张表,遗忘往往要到上线后才被用户发现。
优化层面的方法则是在更新幅度上做约束。一种思路是给重要参数加惩罚,让对旧任务关键的参数变化更慢;另一种是降低学习率、缩短训练轮次,用更温和的更新换取更小的遗忘代价。低秩适配类方法也属于这一路:只训练少量新增参数、冻结主干权重,从结构上限制了旧知识被改动的范围。需要注意的是,冻结并不等于零遗忘,适配层本身仍可能改变模型行为,回归测试依然不能省。
结构层面还有一类做法是把新旧能力分开承载。例如用多个适配器分别对应不同任务,推理时按任务切换;或者在模型外部挂知识库,让易变的行业知识走检索而不是写进权重。把稳定知识留在权重里、把易变知识放在外部,本身就是对遗忘的釜底抽薪。当然,适配器切换会带来运维成本,检索又依赖知识库质量,具体选哪条路要看业务变化频率。
评估是整件事的收口。只看新任务指标的微调报告是不完整的,必须同时报告旧能力基线的前后对比。建议固定一份不随训练集变化的回归评估集,每次微调都跑,遗忘超过阈值就回滚或调整配比。灾难性遗忘无法彻底消除,但可以被度量、被控制。把遗忘当成可观测的工程指标,微调才算真正可交付。另外,微调数据的版本与配比应当留档,遗忘恶化时才能快速定位是哪一批数据引入了问题,而不是凭印象反复试错。
数据层面的思路是让模型在学习新东西时仍然见到旧东西。常见做法是混入一部分通用数据做回放,让新旧分布同时出现在训练批次里。回放比例需要权衡:太少压不住遗忘,太多又会稀释新任务的学习效率。另一个做法是按能力维度构造回归样本集,覆盖推理、问答、代码、数学等旧能力,在训练前后都跑一遍,作为遗忘的体检表。没有这张表,遗忘往往要到上线后才被用户发现。
优化层面的方法则是在更新幅度上做约束。一种思路是给重要参数加惩罚,让对旧任务关键的参数变化更慢;另一种是降低学习率、缩短训练轮次,用更温和的更新换取更小的遗忘代价。低秩适配类方法也属于这一路:只训练少量新增参数、冻结主干权重,从结构上限制了旧知识被改动的范围。需要注意的是,冻结并不等于零遗忘,适配层本身仍可能改变模型行为,回归测试依然不能省。
结构层面还有一类做法是把新旧能力分开承载。例如用多个适配器分别对应不同任务,推理时按任务切换;或者在模型外部挂知识库,让易变的行业知识走检索而不是写进权重。把稳定知识留在权重里、把易变知识放在外部,本身就是对遗忘的釜底抽薪。当然,适配器切换会带来运维成本,检索又依赖知识库质量,具体选哪条路要看业务变化频率。
评估是整件事的收口。只看新任务指标的微调报告是不完整的,必须同时报告旧能力基线的前后对比。建议固定一份不随训练集变化的回归评估集,每次微调都跑,遗忘超过阈值就回滚或调整配比。灾难性遗忘无法彻底消除,但可以被度量、被控制。把遗忘当成可观测的工程指标,微调才算真正可交付。另外,微调数据的版本与配比应当留档,遗忘恶化时才能快速定位是哪一批数据引入了问题,而不是凭印象反复试错。