从灾难性遗忘到持续学习:模型可持续更新实战解析
持续学习Continual Learning最近两年在AI从业者圈子里被反复提起但它并不是什么新概念。核心问题其实很朴素一个已经训练好的模型在部署之后遇到新任务、新数据能不能在不彻底重训、不丢失旧知识的前提下持续更新。直接微调会灾难性遗忘全部重训又成本太高、数据可能根本拿不到。这篇文章我会从问题根源、三大技术路线、评测协议、真实业务落地、复现踩坑几个维度完整过一遍把我自己实验和工程落地中验证过的东西、踩过的坑一起写出来希望能给刚入门持续学习或者正在考虑把模型改造成“可持续更新”的团队一些真正能用的参考。1. 灾难性遗忘持续学习要解决的第一个硬问题1.1 先复现一次“惨案”微调模型忘了旧任务我入坑持续学习是因为一次非常真实的翻车。当时团队做的是一个图片分类服务已经在老数据集上训练好了效果不错。后来新业务来了我们手头有一批新类别的图片按常规思路直接在原模型上继续微调。训练过程很顺利新类别的准确率也确实高但一上线就发现老类别的召回率从92%掉到了70%出头。业务方直接找上门你们是不是把老模型改坏了这就是持续学习领域最经典的现象灾难性遗忘Catastrophic Forgetting。模型的参数是共享的新任务的梯度更新会覆盖掉对旧任务重要的参数状态。你在新数据上学得越认真旧知识被冲刷得越干净。上世纪80年代末McCloskey和Cohen就描述过这个问题但到今天它依然是部署智能系统的主要障碍。如果想在本地快速复现最省事的方式是用MNIST先用数字0到4训练一个分类器冻结相关评估逻辑再用数字5到9去微调整个网络最后回到0到4的测试集上看准确率。很多新手会惊讶地发现准确率可能直接从99%跌到50%上下。这个现象不需要复杂的trick几行PyTorch代码就能看到。1.2 持续学习和迁移学习、多任务学习到底有什么不一样很多人在一开始会把持续学习和迁移学习搞混我当年也绕了弯路。迁移学习的典型场景是“借力”先用大规模数据预训练然后到目标任务上微调它不要求模型在微调后依然保持原来预训练任务的能力。多任务学习则是所有任务的数据都在训练时一次性给齐模型可以同时看到全部信息不存在“先学A再学B”的顺序约束。持续学习夹在两者中间既要求模型按顺序学习多个任务又要求在学习新任务时不明显退化旧任务的能力而且往往伴随着存储限制旧数据不可能完整保留。换句话说持续学习关心的是模型在整个生命周期里的表现而不是某一个阶段的表现。这个区别决定了它的评测方式、算法设计都和前面两种学习范式有本质差异。这也能解释为什么持续学习特别适合数据即取即用的场景新数据来了就学学完还得把旧能力保住。现实业务里绝大多数情况其实都符合这个定义只是以前很多团队用“定期全量重训”来绕开问题。一旦数据规模变大、数据源不断产生新分布全量重训的成本就撑不住了。1.3 为什么现在越来越绕不开模型更新成了常态而非特例以前模型的更新节奏是按月、按季度甚至按年。现在大量系统依赖实时信号推荐系统每天有新品、新用户行为风控模型每天要面对新欺诈模式语音助手每个月要新增技能。模型更新不再是产品发布时的一次性动作而是日常运营的一部分。这个时候“只学新忘记旧”就不再只是学术问题而是直接影响业务指标的工程问题。我在推荐场景里体会特别深。新品类上线时模型如果不对新品类做任何微调新品曝光就会很差一旦用新品数据重训老品类的兴趣预测又可能被带偏。持续学习在这里给了一个思路新旧知识要共存而不是用新知识覆盖旧知识。理解了这个大背景后面讲技术路线和工程方案时你就知道每个方法到底在解决哪一环。2. 三大技术路线正则化、回放、动态架构持续学习的方法论基本可以归成三大类正则化方法、回放方法、动态架构方法。还有少量工作走的是元学习或者记忆增强的路线但后两者往往可以嵌入到三大类中理解。2.1 正则化路线给参数打上“重要程度”标签正则化方法的思路最直观既然灾难性遗忘来自参数被新任务覆盖那就想办法告诉优化器“哪些参数对旧任务很重要别动它们”。最出名的是EWCElastic Weight Consolidation。它用Fisher信息矩阵给每个参数估计一个重要度训练新任务时在损失函数里加一个惩罚项重要度高的参数如果偏离原来的值就要付很大的代价。你可以把它理解成给模型里“老员工”的工位上了锁新人可以随便用空着的工位但别去动老员工的椅子。我在实际复现EWC时有一个体会Fisher矩阵的估计质量直接影响结果。标准做法是从旧任务的数据里采样计算梯度平方的期望。但如果采样的数据不够、采样分布有偏Fisher矩阵就不可靠惩罚项甚至可能起反作用。所以正则化方法看起来轻量其实对数据处理的要求并不小。同一路线里还有SISynaptic Intelligence它在训练过程中追踪每个参数对loss变化的路径积分相当于动态统计每个参数累计的重要性不像EWC需要额外的Fisher估计步骤实现上更平滑。另外LwFLearning without Forgetting走的是知识蒸馏路线训练新任务时让模型的旧任务输出保持稳定不直接限制参数而是限制输出分布。它的效果和蒸馏温度关系很大温度太低约束太弱太高又会影响新任务的学习能力。正则化方法的优点是模型结构不变、内存开销小、不需要存旧数据。缺点是当任务数量很多时累积的惩罚约束会让模型参数越来越僵硬新任务的拟合能力会变差。它适合任务数量不多、数据隐私要求严格的场景。2.2 回放路线让模型“偶尔重温”旧数据回放方法可能是所有持续学习方法里性价比最高的也是最容易被低估的。它的思路简单得让人怀疑训练新任务时顺手把旧任务的一小部分样本混进来一起训练。就是这么朴素的操作在很多评测上效果都超过了花哨的正则化方法。最简单的baseline就是Experience ReplayER维护一个固定大小的缓冲区里面存一部分旧任务样本每个batch里混合新数据和旧数据一起更新。别看不起这个baseline它在多个持续学习基准上的表现都相当能打。我自己的经验是任何新方法出来先拿ER做对照至少能过滤掉一半“我们效果比baseline好”的虚假结论。在ER之上还有GEM和A-GEM。GEM把旧样本的梯度作为约束条件要求新任务的参数更新不能增加旧样本的loss本质是一个带不等式约束的优化问题。A-GEM则做了简化只有当新任务梯度和旧任务梯度冲突时才做梯度投影。这两种方法的有效性其实很依赖旧样本缓冲区里的样本质量。边界模糊、类别不平衡时约束方向本身就有偏效果也不稳。再进阶一点是DERDark Experience Replay。它把知识蒸馏和回放结合起来不仅在缓冲区里存旧样本还存模型在旧样本上的logits输出。训练新任务时要求模型在当前样本上的输出尽量接近存下来的历史logits。这个“暗经验”相当于把旧模型的决策边界信息也保存下来了效果比单纯存标签好很多。但它对两个超参数α和β比较敏感调参成本不低。回放方法的优势是稳定、直观、可控性强也是工业落地时最常被选用的路线。硬伤在于存储和隐私旧样本要么占存储要么因为数据合规要求根本不能保存。为了绕开这个限制有工作提出了生成式回放用生成模型如GAN、扩散模型在训练新任务时合成旧样本。但合成数据分布和真实分布之间有偏差长期累积之后偏差会放大这是一个需要专门解决的工程细节。2.3 动态架构路线请新的“员工”而不是改造老员工动态架构方法走的是另一条路既然改老参数容易出错我干脆为每个新任务分配独立的参数空间任务之间尽量不共享参数。Progressive Neural NetworksPNN是这类工作的代表。每学一个新任务就新加一列网络层同时建立从旧列到新列的侧向连接把旧任务提取过的特征传给新任务。这样旧任务参数完全不动不会遗忘新任务还能借用旧知识。问题也很明显模型体积随任务数量线性增长推理时要跑多个分支成本和复杂度都比较高。PackNet的做法更节省空间它先训练完整网络然后通过剪枝把不重要的参数置零最后用掩码固定这些位置腾出参数空间给下一个任务。相比PNNPackNet让模型容量增长更可控但剪枝比例和每阶段能容纳多少新知识需要精细设计否则新任务的容量会很快耗尽。近几年在大模型背景下动态架构的思路换了新形态最有代表性的是基于Prompt的持续学习比如L2P、DualPrompt。它利用预训练Transformer强大的特征表示为每个任务学习一组轻量的可学习prompt新任务只学新prompt冻结主干模型。这样遗忘问题天然被绕开而且每个新任务的额外参数很小。这类方法在视觉、NLP的连续学习基准上都有不错表现但它极度依赖预训练模型的表示质量如果下游任务和预训练分布差异太大效果会打折扣。换句话说它是“站在预训练的肩膀上”绕过灾难性遗忘并没有真正解决基础模型从头学起时的遗忘问题。动态架构的优点是几乎不遗忘任务边界明确时效果最好。缺点是参数量增长、推理链路变复杂、工程化成本高。它最适合的是任务数量可控、任务边界清晰的场景比如给一个对话系统按模块增加新技能。2.4 三类方法怎么选一个来自工程实践的快速对比如果项目要选型我会先看三个约束能不能存旧数据、任务边界清不清楚、模型体积容不容忍增长。这里给一个我用于内部快速决策的对比表。对比维度正则化方法回放方法动态架构是否存储旧数据不需要需要不需要额外内存开销低中缓冲区高参数扩展任务边界假设弱弱强遗忘控制能力中高很高实现复杂度低中高典型代表EWC、SI、LwFER、A-GEM、DERPNN、PackNet、L2P适合场景隐私严格、任务少数据可存、追求稳定任务边界清晰、硬件充裕我个人的默认建议是如果没有任何特殊限制先用ER或者带蒸馏的回放方法把准确率和遗忘率跑出来做基线再决定要不要上更复杂的方案。很多团队一上来就用EWC或者L2P结果发现调参成本和存储成本还不如老老实实做回放。真实场景里“简单有效”比“论文惊艳”重要得多。3. 评测基准与评估协议论文千千万结果怎么比持续学习论文看起来很热闹但复现之后常常发现不同工作之间的结果没有可比性。这个问题不是细节而是评测协议和基准设置不统一导致的。3.1 常用数据集和拆分方式持续学习最常用的是MNIST、CIFAR-10、CIFAR-100、ImageNet这类视觉数据集再通过不同的拆分方式构造任务序列。Permuted-MNIST是最简单的对每个任务对MNIST图像做不同的固定像素置换让网络面对同分布但完全不同输入的任务。它主要测试模型在输入分布变化下的适应能力难度偏低。Split-MNIST则是把MNIST的10个类别切分成五个二分类任务依次学习。这种设定更接近真实场景因为任务是按类别划分的。Split-CIFAR-100把100类分成10个任务或者20个任务难度比MNIST高不少是目前比较通行的Class-IL评测设计。如果追求更接近真实世界的评测还有CORe50包含50个类别、多个不同采集场景、DomainNet跨域分类、持续机器学习的流式基准CLOC等。我建议入门时先从Split-MNIST和Split-CIFAR-100入手把问题机制弄清楚再上更复杂的数据集。不要一上来就选太难的数据集否则你很难判断算法效果差到底是因为方法不行还是因为某个评测坑没绕开。3.2 Task-IL、Domain-IL、Class-IL三种协议别搞混评测协议不统一是持续学习领域最容易被忽略的点。van de Ven和Tolias在2019年的工作把主流评测方式归纳为三种场景Task-ILTask Incremental Learning里训练和测试时都提供任务ID模型只要解决当前任务即可测试时需要知道属于哪个任务。这种场景最简单比如Permuted-MNIST就给每个任务一个明确标识模型甚至可以按ID走不同的输出头。Domain-ILDomain Incremental Learning里任务ID不提供输入分布会变化但输出标签集合不变。比如对不同画风做同一组类别分类。模型必须从输入里推断当前域难度中等。Class-ILClass Incremental Learning是现实挑战最大的协议新任务引入的是新类别测试时也不知道类别属于哪个旧任务。模型必须在所有见过的类别里做统一分类。这种设置下最终分类器的决策边界会面临严重的新旧类别不平衡问题算法性能下降也最明显。这个区别很重要因为某些方法在Task-IL下表现极好到Class-IL下就露馅。我看到不少论文会在Task-IL下做主要实验再顺带报告Class-IL结果。读论文时如果只盯着“准确率95%”这种数字而不去看协议很容易被误导。评测协议测试时是否给任务ID输出标签集合难度典型数据集Task-IL给每个任务独立低Permuted-MNISTDomain-IL不给不变中Rotated-MNISTClass-IL不给不断扩展高Split-CIFAR-1003.3 核心指标平均准确率、后向迁移、前向迁移持续学习最基础的指标是平均准确率ACC即在学完所有任务后对所有已见任务的测试准确率求平均。不同论文可能报告“平均增量准确率”或者“最终平均准确率”前者会包含学习过程中间状态的累计平均值后者只看最终模型两者数字差异可能很大。除了准确率常用的还有后向迁移Backward TransferBWT和前向迁移Forward TransferFWT。BWT衡量学习新任务后旧任务性能的变化负值越大说明遗忘越严重。FWT衡量学新任务对还没学的任务有没有帮助。很多论文会先报ACC再报BWT我建议看持续学习效果时重点看BWT因为遗忘才是持续学习的核心矛盾。另外有一个容易被忽略的坑任务序列的顺序会影响结果。A任务先学B任务后学和顺序反过来同一套算法表现可能差不少。评估一个持续学习算法时最好在多个随机任务顺序下跑多次取平均和方差而不是只报一个固定顺序下的结果。我在自己的实验里发现这个方差往往比不同算法之间的差距还要大。没有方差报告的结果你看得再认真也很难判断真假。4. 持续学习在真实业务里的样子持续学习论文里常出现的benchmark毕竟是玩具真实业务里会遇到更残酷的约束。这里总结几个我见过、做过的真实场景以及持续学习在其中扮演的角色。4.1 模型要一直学新知识又不能把老客户忘了我在推荐和广告场景里看到的持续学习需求最集中。推荐模型的训练数据是用户行为日志用户的兴趣会随着时间、季节、热点事件变化同时不断有新的内容品类和商品池进来。如果模型不做更新新品冷启动会越来越差如果频繁微调容易对上一天的短期兴趣过度拟合长期兴趣反而被遗忘。一个比较成熟的落地方式是维护一个回放缓冲区里面保存不同时间段、不同关键品类的代表性样本训练时混合实时样本和缓冲样本一起更新。这本质上就是ER的思路但工程实现时要处理标签偏移、样本权重、样本过期等问题。比如某个爆品的样本权重如果太大一不小心就会把模型的注意力全部带走。风控场景更有意思。欺诈模式是不断翻新的昨天有效的规则今天可能就失效了但旧的风险类型也不能忽略。持续学习在这里被用来让模型在识别新型欺诈的同时不掉旧类型。隐私和合规压力很大旧样本往往不能保存太久所以很多团队会优先考虑正则化方法或者用蒸馏式的回放替代原始样本存储。4.2 边缘设备和机器人算力和存储都有限边缘设备是持续学习另一个典型场景因为它们天然只能看到流式数据而且全量重训不太现实。机器人要在新环境里学会操作新物体但又不能忘了在家里已经学会的技能。自动驾驶在进入新城市、新季节、新天气时也需要增量适应同时旧区域的表现不能崩。这类场景的难点在于设备存储和算力都受限制回放缓冲区不可能太大动态架构又可能让模型体积超限。我在嵌入式环境里见过一个做法在设备上只保留轻量的EWC惩罚项定期在云端做一次全量重训再压缩回设备。这相当于把持续学习和联邦训练、模型压缩组合起来用。组合方案往往比单一方法更符合真实硬件约束这也是工程和论文最大的区别。4.3 NLP与对话系统插件式技能更新NLP领域持续学习通常叫lifelong learning。对话系统是一个很典型的场景产品会不断新增技能比如查天气、订餐、闲聊每个技能可以看成一个任务模型要保证新增技能时不破坏已上线的对话能力。大模型时代持续学习的概念有了一些变化。预训练语言模型的强表示能力让很多持续学习任务可以通过轻量适配模块或prompt完成新技能变成新增少量参数遗忘问题大大缓解。但大模型持续学习要处理的是另一种遗忘指令微调阶段学新指令任务时会遗忘掉预训练阶段积累的通用知识和指令跟随能力。这个问题甚至在训练业界最强模型时也会遇到很多团队会用“在预训练数据里混入一部分指令数据”来做平衡这本质上也是一种回放只不过回放的是通用语料。4.4 工程落地时真正要付出的额外代价持续学习不是银弹工程落地时它带来的额外成本往往被忽视。首先是版本管理变复杂。模型不再是一个静态产物而是不断在线上演进的实体。每次更新后你都需要评估旧任务表现这意味着你要长期保存一套覆盖历史任务分布的评估集。做持续学习的团队评估成本往往比训练成本还高。其次是监控体系必须跟上。如果没有数据分布漂移检测你很难判断“该学新任务了”还是“该停止更新了”。我见过不止一个团队因为没做漂移监控让模型在新分布异常时持续学习结果把线上模型越学越偏。第三是回滚机制。持续更新意味着每次更新都可能引入未知问题模型回滚能力必须和算法一起设计。回滚不仅仅是恢复旧版本参数还要考虑旧版本是否真的能处理当前线上分布有时候旧版本比持续更新后的版本更适合当前环境。5. 复现持续学习算法时的踩坑记录这一章写一点点真实的复现经验。持续学习论文看起来简单真正动手做坑比想象中多。5.1 评测设置不统一带来的“假结果”我第一次复现EWC时按照论文给的超参设置跑Permuted-MNIST效果一直上不去。后来发现是Fisher矩阵的采样样本数差了一个数量级。论文里常用的Fisher样本数范围可能是几百到几千如果我用很少的样本去估计结果就会很不稳定。这个参数论文很容易一笔带过但实际影响非常大。另外一个坑是任务顺序。Permuted-MNIST如果某个置换恰好把两张图映射得非常像模型在相邻任务之间的迁移效果就会变化。复现时如果只跑一个固定顺序很难判断结果到底来自算法还是运气。现在我养成的习惯是固定多个随机种子、多个任务顺序把均值和标准差一起报告否则只看一个数字很容易下错误结论。5.2 超参数比算法本身更敏感持续学习算法普遍对超参数敏感其中回放缓冲区大小、正则化系数、蒸馏温度最影响结果。比如EWC的正则化系数λ。λ太小惩罚不起作用模型照样遗忘λ太大新任务学不进去准确率上不来。这个范围往往跨越好几个数量级不做网格搜索很难找到合适的点。DER的α和β超参调节更是磨人。α控制分类cross-entropy的权重β控制蒸馏loss的权重两者比例不对模型要么遗忘得厉害要么新任务学不进去。这也是为什么我说任何新方法都要先和ER、EWC这样的简单baseline做对照如果你调的复杂算法性能只是勉强超过ER那说明它带来的不稳定收益很可能不值得工程上的额外复杂度。5.3 从玩具benchmark到真实数据差了多远玩具benchmark和真实数据之间存在三个明显的断层。第一个断层是数据分布漂移的方式。benchmark里的任务边界清清楚楚每个任务内部是独立同分布的。真实数据往往是渐变式漂移旧分布不会彻底消失新分布也不会一夜之间全部出现。算法在任务边界分明的测试集上表现好不等于在渐变漂移数据上也有用。第二个断层是类别平衡。Split-CIFAR-100每个任务内部类别是均衡的真实数据基本都是长尾分布新类别往往一开始样本极少后面又爆发性增长。这种样本波动对持续学习算法的稳定性要求很高。第三个断层是标签噪声。benchmark的标签干净真实业务里标签经常是弱监督或者自动生成的本身包含错误。持续学习系统如果在可信度不高的标签上学习错误知识会被固化甚至放大。所以我在真实项目中做持续学习时会先把不确定样本过滤出来定期人工复核而不是全部进模型。6. 下一步方向哪些趋势值得关注持续学习这几年变化很快信息量很大我给你整理几个我认为值得投入注意力的方向。6.1 生成式回放与数据合成严格控制数据隐私的行业对生成式回放一直有很强的需求。早期用GAN生成旧任务样本最大的问题是生成质量不够样本分布一旦失真回放效果就会退化。扩散模型成熟后合成样本质量大幅提升生成的旧样本甚至可以在一些情况下代替真实样本用于回放。但这不代表可以无脑用。我建议如果要走生成式回放路线先验证生成的样本在旧任务上的分布距离再决定要不要替换真实样本。很多团队第一步就翻车是因为生成器本身需要训练才能达到足够的质量而这个训练过程在持续学习框架里会有额外的时间成本和工程复杂度。6.2 Prompt持续学习与大模型预训练模型加可学习prompt的方法本质上是用预训练模型的通用表征绕开了灾难性遗忘。它的一个重要优点是可以无痛扩展到很多下游任务新任务只加一组prompt参数成本很低。这个方向的适用条件也很明确你得有一个足够强的预训练模型能够覆盖你所有任务的特征分布。如果你做的任务离预训练分布太远prompt方法就会很吃力。我在实际项目中用prompt做多语种分类的增量效果很好但换成非常垂直的医学图像任务效果就一般了。所以选技术路线时不要因为某个方法在论文里看着高级就直接套用。6.3 评估体系规范化的呼声持续学习领域现在最大的问题不是缺方法而是缺可信的对比方法。很多论文各自用不同的数据集、不同的任务顺序、不同的评测协议导致读者无法判断新方法到底是真改进还是在特定设置下“刷分”。近两年社区已经在推动更统一的基准要求报告多次运行的平均值和方差要求同时报告传统指标和遗忘指标。我个人的态度是团队在选择持续学习算法时不要只看论文的表最好自己搭一套标准化评测把自己候选的算法、基线、真实数据分布都放上去跑。这比追逐热门算法更可靠。6.4 我对持续学习落地优先级的一点个人建议如果让我给正在考虑做持续学习的团队排优先级我会这样建议。先问自己是不是真的需要持续学习。如果业务节奏允许定期全量重训那就不要为了技术潮流增加复杂度。全量重训配合良好的数据管线在很多场景下依然是最稳定、最可控的方案。如果确实需要持续更新先从回放类的简单方案开始。一个ER加合理的数据分布监控已经能覆盖很多实际场景。论文里看起来性能很强的复杂算法往往伴随着调参难、工程复杂、收益不稳定等问题不是首选。再往后如果产品对模型体积和成本敏感再考虑正则化路线如果任务边界清晰且需要严格的数据隐私保护动态架构路线可能是更好的选择。持续学习这个概念虽然听起来高大上但实际上它解决的是工程里非常朴素的问题模型如何在不断变化的世界里长期保持有用。先把问题定义清楚再选择匹配的算法比直接套用某个模型更关键。