园丁老周有一本“种花手账”,上面密密麻麻记着每种花的习性:玫瑰喜酸土、茉莉怕暴晒、月季要勤剪……手账是特殊纸张,每页只能写新字、旧字会慢慢褪色,而且写得越满,新字落笔时旧字被擦得越快。老周要不断学习引进的新花种——兰花、蝴蝶兰、多肉——可他每次记住一种新花,就有一两种旧花的养法从纸上消失,花圃里的玫瑰开始黄叶、茉莉开始掉苞。这是老周的灾难,也是每一位 AI 工程师的灾难:我们把这种“模型学了新任务就忘旧任务”的现象,叫作灾难性遗忘(Catastrophic Forgetting)。 为什么忘得这么快?因为神经网络跟老周一样只有“一页纸”:所有任务共用同一套参数,学新任务时梯度只盯着新任务,旧参数被改写、旧知识被覆盖。好消息是,老周很快总结出三条防忘规条:经常翻旧笔记(经验重放 Replay)、给关键条目贴荧光胶带(弹性权重巩固 EWC)、请旧手账影印件当助教对照着写(无遗忘学习 LwF)。这三招,正是持续学习(Continual Learning)里最主流的三大缓解策略。读完本文,你也能让自家模型“学得进新、忘不掉旧”。

岗位关联

掌握这份“防忘三件套”,你就能让模型在数据标注持续交付、用户兴趣演化、多语言扩展等场景中安全增量更新,不再被全量重训的成本和丢失的旧能力拖累——这是数据工程师与算法工程师从“能训”走向“会训”的关键一跃。

目录
  1. 可视化演示
  2. 1. 遗忘的根源:灾难性遗忘与权重覆盖
  3. 2. 持续学习的赛场:三种设定与评估尺子
  4. 3. 老照片回放:经验重放(Replay)
  5. 4. 荧光笔标记:弹性权重巩固(EWC)
  6. 5. 旧手账当助教:无遗忘学习(LwF)
  7. 6. 工程实践:三招组合与训练流水线
  8. 7. 用武之地:在线标注与持续运营场景
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

交互展示持续学习中灾难性遗忘的三种缓解策略:知识漂移、正则化约束和数据回放,直观对比各方法如何保留旧知识同时学习新任务。

本节配有交互动效(进入视口后自动加载,约 3KB)。

知识漂移:LwF知识蒸馏 旧模型作为教师指导新模型学习 软标签保留旧任务的输出分布 L = L_new + α·L_distill 知识蒸馏实现新旧任务的平滑过渡

1. 遗忘的根源:灾难性遗忘与权重覆盖

老周盯着手账发呆:为什么记新花一定要擦旧花?他试着把字写小一点,可新条目一多,旧条目还是像被橡皮擦碰过一样模糊。他恍然明白——不是他不努力,是纸就这么多。神经网络也一样:不管接多少任务,可用的参数总量就那么多。新任务要“写字”就必须改动参数,而“动旧参数”,就是在擦除旧知识。

技术上的说法是:模型在任务 A 上收敛后,再在任务 B 上做梯度下降。此时梯度只包含任务 B 的信息,它不知道“参数怎么改会伤害任务 A”。于是那些对 A 至关重要的参数被一路推动、偏离了 A 的最优区域,A 的准确率断崖式下跌。这就是灾难性遗忘——注意“灾难”两个字:不是缓慢衰减,是雪崩。

这个问题只在“任务序列学习”中出现:数据以任务为单位一个接一个到达,旧数据往往因为存储或隐私原因不再保留,每一时刻只能看到当前任务。理想的模型必须同时满足两个互相矛盾的诉求:稳定地保留旧知识(stability),又足够可塑地吸收新知识(plasticity)。这就是持续学习最核心的稳定性-可塑性困境。

想通了根因,老周反而踏实了:既然是“写新字会擦旧字”,那就想办法让旧字擦不掉。他发明的三招,每一招都是对这个更新规则的局部反击。接下来我们逐一拆解。

θ←θ−η ∇θLB(θ)\displaystyle \theta \leftarrow \theta - \eta\, \nabla_{\theta} L_B(\theta)
这一条更新规则只由新任务 B 的损失驱动,旧任务被完全无视——它就是灾难性遗忘的“肇事现场”。
  1. 参数向量$\theta$ 表示网络的全部参数,相当于手账里的全部养花条目。
    θ\theta
  2. 更新动作$\leftarrow$ 表示把右边算出的新值写回参数,每写一次旧值就被覆盖一分。
    ←\leftarrow
  3. 学习率$\eta$ 是每次更新的步长,太大走飞、太小不动,它决定“涂改旧字”的力道。
    η\eta
  4. 梯度方向$\nabla_{\theta} L_B(\theta)$ 是新任务 B 的损失对参数的梯度,只由新任务数据决定——这就是旧条目无人保护的根源。
    ∇θLB(θ)\nabla_{\theta} L_B(\theta)

2. 持续学习的赛场:三种设定与评估尺子

老周把花园分成三种验收方式:第一种,每块花圃挂着牌子,答错了也知道是哪块地的花;第二种,大家种的是同一批花,只是今年土壤气候全变了;第三种最难——所有花混在一起采收,摘到一朵,你必须说清它叫什么、怎么养。三种验收方式,正好对应持续学习的三种设定。

持续学习通常分为三类:任务增量学习(Task-IL)——测试时知道任务编号,模型只要在对应的任务头上分类;领域增量学习(Domain-IL)——标签集合不变,但输入分布漂移;类别增量学习(Class-IL)——新任务不断带来新类别,测试时必须从所有见过的类别中判断。真实业务(比如在线数据标注)大多数是难度最高的 Class-IL。

有了赛场,还要有尺子。最常用的指标是平均准确率 A:学完最后一个任务后,把所有任务上的准确率取平均。它回答“模型现在整体还能打几分”。如果想专门看“忘得多狠”,还要用遗忘率 F,它统计每个旧任务从历史最高点跌了多少。A 越高、F 越低,说明持续学习策略越好。

老周把三种验收方式当成自己试招的考场:每学完一个新花种,就到旧花圃里转一圈,量量旧花的存活率。有了尺子,三招强弱立刻见分晓——接下来就看回放、加固、蒸馏谁最管用。

A=1T∑i=1TaT,i\displaystyle A = \frac{1}{T}\sum_{i=1}^{T} a_{T,i}
平均准确率把“新任务学得好不好”和“旧任务忘没忘”揉成一个数,是持续学习的体检报告。
  1. 任务总数$T$ 表示一共学了 T 个任务,对应老周引进的花种批次。
    TT
  2. 单个任务准确率$a_{T,i}$ 表示学完第 T 个任务后,模型在第 i 个旧任务测试集上的准确率。
    aT,ia_{T,i}
  3. 取平均$\frac{1}{T}\sum_{i=1}^{T}$ 把所有任务的表现平均起来,衡量“整体没忘多少”。
    1T∑i=1T\frac{1}{T}\sum_{i=1}^{T}

3. 老照片回放:经验重放(Replay)

老周的第一招最简单:他做了一本“小相册”,每页只贴一种旧花的照片和一句要点。学新花时,他先翻几页相册,再写新条目——新知识学一半、旧知识念一遍,两边都不耽误。

这就是经验重放(Replay / Experience Replay):维持一个只装少量旧样本的记忆缓冲池 M,训练新任务时,每个 batch 从 M 里采样部分旧样本,与新样本混合一起算损失。这样梯度方向不再是“只看新任务”,而是新旧两边平衡的合力。付出的代价是存储:M 越大效果越好,但存储和隐私成本越高。

为了省存储,研究者又发明了生成式重放:训练一个生成模型,让它“画”出旧样本的样子,再喂给主模型——相当于把纸质相册拍成电子版。无论直接存储还是生成,缓冲池里样本的代表性都很重要,工程上常用水库采样(Reservoir Sampling)保证每个历史样本被选中的概率近似相等。

老周的相册法立竿见影,可相册越攒越厚,花房都摆不下了。他开始琢磨:能不能不翻相册,就让旧知识不被擦掉?于是他发明了第二招。

L=LB(θ)+λ⋅1∣M∣∑(x,y)∈Mℓ(f(x;θ), y)\displaystyle L = L_B(\theta) + \lambda \cdot \frac{1}{|M|} \sum_{(x,y)\in M} \ell\big(f(x;\theta),\, y\big)
Replay 的损失是“新任务损失”加“旧样本平均损失”的加权和:学新任务的同时,让旧样本的预测也别太离谱。
  1. 新任务损失$L_B(\theta)$ 是当前新任务 B 的分类损失,保证新花也能学会。
    LB(θ)L_B(\theta)
  2. 记忆缓冲池$M$ 是存放旧样本的小缓冲区,$|M|$ 是它的样本总数。
    MM
  3. 旧样本平均损失$\frac{1}{|M|}\sum_{(x,y)\in M}\ell(\cdot)$ 是对缓冲区里旧样本的预测损失求平均,相当于“翻相册默写旧花养法时的评分”。
    1∣M∣∑(x,y)∈M\frac{1}{|M|}\sum_{(x,y)\in M}
  4. 平衡系数$\lambda$ 控制旧知识的回放强度,太大则新任务学不动,太小则防不住遗忘。
    λ\lambda

4. 荧光笔标记:弹性权重巩固(EWC)

老周的第二招,是找出手账里“最关键的几页”贴上荧光胶带:擦写时发现这几页被牢牢固定,只能改边角、不能动正文。问题是:怎么判断哪页关键?老周的直觉是——看这页被涂改后,多少旧知识会跟着消失。

弹性权重巩固(EWC, Elastic Weight Consolidation)把这种直觉变成了数学。学完任务 A 后,用 Fisher 信息矩阵的对角元 $F_i$ 给每个参数打分:$F_i$ 越大,说明参数 i 对任务 A 的预测影响越大,越关键。此后学任务 B 时,损失函数里加一个二次惩罚项:参数偏离旧任务最优值越远,罚得越重,而且 $F_i$ 大的参数罚得格外重。

注意:计算 Fisher 仍然需要一些旧任务样本(通常是旧数据的一部分或缓冲池里的样本)。在数据标注场景中,Fisher 常常直接复用 Replay 缓冲池的数据——两招联动,非常实用。与普通 L2 正则化的区别在于:L2 把所有参数平等地压向 0,EWC 则把参数“锚定”在旧任务最优值,并按重要性区别对待。λ 控制整体保护强度:λ 太小防不住遗忘,λ 太大新任务学不动。

荧光胶带法的确保住了旧花谱,可老周发现胶带贴得太死,新花学得越来越慢——这就是稳定性-可塑性困境的化身。他开始琢磨:有没有一种办法,不用旧数据、也不用胶带,就能让新旧知识“互相照应”?

L(θ)=LB(θ)+λ2∑iFi (θi−θA,i∗)2\displaystyle L(\theta) = L_B(\theta) + \frac{\lambda}{2} \sum_i F_i\,(\theta_i - \theta^{*}_{A,i})^2
EWC 的惩罚项像弹簧:每个参数都被一根“Fisher 粗细”的弹簧拴在旧任务最优值上,越重要拴得越紧。
  1. 旧任务最优参数$\theta^{*}_{A,i}$ 是只学任务 A 后参数 i 的值——荧光笔标注的“原文”。
    θA,i∗\theta^{*}_{A,i}
  2. 重要性度量$F_i$ 是 Fisher 信息矩阵的对角元,衡量参数 i 对旧任务有多关键。
    FiF_i
  3. 二次惩罚$(\theta_i - \theta^{*}_{A,i})^2$ 让参数离“原文”越远罚得越狠,再乘上 $F_i$ 决定这根弹簧有多硬。
    (θi−θA,i∗)2(\theta_i - \theta^{*}_{A,i})^2
  4. 保护强度$\frac{\lambda}{2}$ 是整体乘子,把全部弹簧的松紧统一缩放。
    λ2\frac{\lambda}{2}

5. 旧手账当助教:无遗忘学习(LwF)

老周的第三招颇有点“借力打力”:他把旧手账完整复印了一份胶片,平时不翻,只在写新条目时把胶片放在旁边——新条目怎么写,先问胶片“同样一盆花,旧手账会怎么记录它的特性?”,然后让新写法尽量不偏离旧看法。

LwF(Learning without Forgetting,无遗忘学习)正是这个思路。它不需要保存任何旧数据,只保存旧模型的参数快照(相当于胶片)。学新任务 B 时,把每个新样本同时送入旧模型和新模型,旧模型输出一个概率分布——这是“旧知识对新数据的看法”;训练时除了最小化新任务的分类损失,还要让新模型的输出分布与旧模型足够接近。这样,网络在调整参数迁就新任务时,也会“卖旧知识一个面子”。

为了让旧模型“看法”里的暗知识露出来,输出之前要除以一个温度参数 T(通常取 2~4)再做 softmax——温度越高分布越平滑,类别间“似曾相识”的关系越明显。两类分布的距离用 KL 散度衡量,得到蒸馏损失。一个明显的局限是:旧模型毕竟没见过新数据,如果新数据与旧数据差异太大,胶片的“看法”也不可靠,蒸馏信号会失真。

胶片法帮老周省下了相册的空间,也让他意识到:知识其实可以“参数化”地活在模型里,不一定非要存成数据。三招至此齐了——回放管数据、巩固管参数、蒸馏管行为。但真正到了花圃扩建的节骨眼上,老周发现单用哪一招都差点意思。

L=Lnew(θ)+λ⋅KL(softmax(zold/T) ∥ softmax(znew/T))\displaystyle L = L_{\text{new}}(\theta) + \lambda \cdot KL\Big( \mathrm{softmax}(z_{\text{old}}/T) \,\big\|\, \mathrm{softmax}(z_{\text{new}}/T) \Big)
LwF 的损失 = 新任务分类损失 + 蒸馏损失:既要学会新任务,又要在同一批输入上“模仿”旧模型的回答风格。
  1. 旧模型输出$z_{\text{old}}$ 是旧模型(胶片)对同一批新数据的 logits,代表旧知识的“看法”。
    zoldz_{\text{old}}
  2. 温度软化除以 $T$ 让概率分布更平滑,暴露出类别之间的相似关系,这是蒸馏的精华。
    softmax(zold/T)\mathrm{softmax}(z_{\text{old}}/T)
  3. 分布距离$KL(\cdot\|\cdot)$ 衡量新旧模型输出分布的差异,训练就是要让这个差异尽量小。
    KL(⋅∥⋅)KL(\cdot\|\cdot)
  4. 蒸馏强度$\lambda$ 平衡“学新任务”和“仿旧模型”两股力量。
    λ\lambda

6. 工程实践:三招组合与训练流水线

花圃越建越大,老周把三样工具摆了一桌子:相册(Replay)、荧光胶带(EWC)、胶片(LwF)。他很快发现,高手从不只靠一件工具:关键条目贴胶带,同时定期翻相册,再拿胶片对新数据对一遍“口径”。

三招完全可以组合进同一条更新流水线,因为它们作用在不同层面:Replay 在数据层补样本,EWC 在参数层加约束,LwF 在输出层保持行为一致。组合损失就是三者的加权和。工程实现上有一串要点:旧模型要冻结并设为 eval 模式;Fisher 只在旧任务阶段计算一次;Replay 缓冲池用双 DataLoader 按比例混合采样;每学完一个任务立刻在全部旧任务上评测并记录遗忘率。

超参数方面,EWC 的 λ 常在 0.1~400 之间调,LwF 的温度 T 常用 2~4,缓冲池大小与新旧样本混合比例(如 1:1 或 1:2)要看存储预算。落地点睛之笔是把它接进数据标注流水线:标注团队每交付一批新标签 → 从缓冲池抽样旧样本 → 增量训练一次 → 全量回归测试 → 达标则发布。这样,标注产能与模型迭代才能真正解耦。

老周把三件工具挂上墙,按需取用。他总结:旧数据还能留一点,就用 Replay;旧数据一点都留不下,就用 LwF;担心重要参数被带偏,就在两者之上再加一层 EWC。三招组合,花圃的四季花开不败。

Ltotal=Lnew+λ1 Lreplay+λ22∑iFi (θi−θi∗)2+λ3 KL(zold,znew)\displaystyle L_{\text{total}} = L_{\text{new}} + \lambda_1\, L_{\text{replay}} + \frac{\lambda_2}{2}\sum_i F_i\,(\theta_i - \theta^{*}_i)^2 + \lambda_3\, KL(z_{\text{old}}, z_{\text{new}})
这是“防忘全家桶”:第一项学新任务,第二项回放旧样本,第三项加固重要参数,第四项蒸馏旧模型行为——四股力量各司其职。
  1. 新任务损失$L_{\text{new}}$ 保证新批次数据能被学会,是所有更新的原动力。
    LnewL_{\text{new}}
  2. 回放项$\lambda_1 L_{\text{replay}}$ 对应 Replay,用缓冲池旧样本稳住优化方向。
    λ1Lreplay\lambda_1 L_{\text{replay}}
  3. 加固项$\frac{\lambda_2}{2}\sum_i F_i(\theta_i-\theta^{*}_i)^2$ 对应 EWC,保护重要参数不跑偏。
    λ22∑iFi(θi−θi∗)2\frac{\lambda_2}{2}\sum_i F_i(\theta_i-\theta^{*}_i)^2
  4. 蒸馏项$\lambda_3 KL(z_{\text{old}}, z_{\text{new}})$ 对应 LwF,让新旧模型输出行为保持一致。
    λ3KL(zold,znew)\lambda_3 KL(z_{\text{old}}, z_{\text{new}})

7. 用武之地:在线标注与持续运营场景

三招练成后,老周的花圃迎来最忙的春天:新品种每隔两周就引进一批,老品种还得保证市面上供应不断。他意识到,自己过去“全园换土重种”的做法(全量重训)已经撑不住节奏了,必须边进边学。

第一个用武之地是在线标注更新。标注团队每周交付新批次的标注数据,里面可能新增类别、也可能修正旧标签。全量重训成本高、周期长;不加防护的微调又忘得快。标准做法是:保留一个 Replay 缓存池(旧批次代表样本),用 EWC 加固关键权重,按批增量训练。这样新类别快速上线,旧类别不掉队。

第二个场景是推荐系统的兴趣演化:用户偏好随时间漂移,模型每天吸收新的正反馈,但不能把长期兴趣忘光,LwF 的蒸馏损失很擅长这种“边学边稳”。第三个场景是多语言/多领域模型更新:新增语言或领域时用 EWC 保住原有能力,是 NLP 工程中的常见配方。这些场景的共性都是:数据永远在追加、旧知识永远要保底——这正是持续学习的主场。衡量组合策略效果时,就要请出遗忘率这把尺子。

老周现在逢人就讲:别让模型当“学了新就忘旧”的金鱼。只要把 Replay、EWC、LwF 这三把钥匙用对场景,增量学习就能像他的花圃一样——新品一直在上,老品永远有货。

F=1T−1∑j=1T−1(max⁡t≤jat,j−aT,j)\displaystyle F = \frac{1}{T-1}\sum_{j=1}^{T-1}\Big( \max_{t \le j} a_{t,j} - a_{T,j} \Big)
遗忘率统计每个旧任务“从最好状态跌了多少”再取平均,数值越小说明防忘策略越成功。
  1. 历史峰值$\max_{t \le j} a_{t,j}$ 是任务 j 在历史上最好的准确率,对应老周花势最旺的那一季。
    max⁡t≤jat,j\max_{t \le j} a_{t,j}
  2. 当前水平$a_{T,j}$ 是学完所有任务后,任务 j 现在的准确率。
    aT,ja_{T,j}
  3. 求平均$\frac{1}{T-1}\sum_{j=1}^{T-1}$ 把所有旧任务的“跌幅”平均,得到整体遗忘程度。
    1T−1∑j=1T−1\frac{1}{T-1}\sum_{j=1}^{T-1}

AI 应用场景

在线标注数据增量更新流水线

阶段:数据标注与管理 / 模型迭代上线

解决的问题:传统做法是每收到一批新标注数据就全量重训,GPU 成本高、交付周期长;直接增量微调又会让旧类别断崖式遗忘。用 Replay 缓冲旧批次代表样本、EWC 加固关键权重,就可以“边收边学”。

具体案例:某自动驾驶公司每周新增 10 万张路况标注图,并新增“施工围挡”等类别。全量重训需 12 小时,改为 Replay + EWC 的增量更新后只需 1.5 小时,新类别指标达标,旧类别 mAP 仅下降约 0.8%。

推荐系统用户兴趣演化

阶段:模型持续学习 / 个性化推荐

解决的问题:用户兴趣随季节和热点漂移,模型既想快速吸收新兴趣,又不能丢掉长期稳定的偏好。LwF 蒸馏旧模型对新数据的软标签,让新旧兴趣共享表征。

具体案例:新闻推荐场景中,用户最近开始关注新能源车,但原有的体育偏好不能丢。用 LwF 做每日增量更新后,长期兴趣指标保持稳定,新兴趣点击率提升 23%。

多语言模型持续扩展

阶段:数据工程 / 模型发布

解决的问题:新语料或新方言到达时,直接微调会破坏已有语言的翻译质量。EWC + 小样本 Replay 是常见的“保护式更新”方案。

具体案例:多语言机器翻译系统新增希伯来语时,使用 EWC 保护旧参数,原有 10 种语言的 BLEU 平均下降从 3.1 降为 0.4,新语言质量达标。

Python 演示

python80 行
import copyimport torchimport torch.nn as nnimport torch.nn.functional as F torch.manual_seed(42)  def make_data(centers, n=200, sigma=0.4):    # centers: [(坐标, 标签), ...] 生成二维高斯簇    xs, ys = [], []    for c, y in centers:        xs.append(torch.randn(n, 2) * sigma + torch.tensor(c, dtype=torch.float32))        ys.append(torch.full((n,), y, dtype=torch.long))    return torch.cat(xs), torch.cat(ys)  def build_model():    # 输入 2 维坐标,输出 4 个类别的 logits    return nn.Sequential(nn.Linear(2, 32), nn.ReLU(), nn.Linear(32, 4))  def accuracy(model, x, y):    return (model(x).argmax(1) == y).float().mean().item()  def train(model, x, y, old_params=None, fisher=None, lam=2.0, steps=300):    opt = torch.optim.Adam(model.parameters(), lr=0.02)    for _ in range(steps):        opt.zero_grad()        logits = model(x)        loss = F.cross_entropy(logits, y)        if old_params is not None:  # EWC 二次惩罚            reg = sum((fisher[n] * (p - old_params[n]) ** 2).sum()                      for n, p in model.named_parameters())            loss = loss + lam * reg / 2.0        loss.backward()        opt.step()  def compute_fisher(model, x, y):    # 用蒙特卡洛采样逼近对角 Fisher 信息    model.eval()    total = {}    for i in range(len(y)):        logits = model(x[i:i + 1])        label = torch.multinomial(torch.softmax(logits, dim=1)[0], 1)        loss = F.cross_entropy(logits, label)        grads = torch.autograd.grad(loss, model.parameters())        for (n, _), g in zip(model.named_parameters(), grads):            total[n] = total.get(n, 0) + g.detach() ** 2 / len(y)    return total  def main():    # 任务A: 两类旧花; 任务B: 两类新花, 位置与A重叠制造"冲突"    task_a = make_data([((-2.0, 0.0), 0), ((2.0, 0.0), 1)])    task_b = make_data([((-2.0, 0.8), 2), ((2.0, -0.8), 3)])     base = build_model()    train(base, *task_a)    acc_a_before = accuracy(base, *task_a)    fisher = compute_fisher(base, *task_a)    old_params = {n: p.detach().clone() for n, p in base.named_parameters()}     vanilla = copy.deepcopy(base)    train(vanilla, *task_b)    acc_a_vanilla = accuracy(vanilla, *task_a)     ewc_model = copy.deepcopy(base)    train(ewc_model, *task_b, old_params, fisher, lam=2.0)    acc_a_ewc = accuracy(ewc_model, *task_a)     print("Task A acc before       : %.3f" % acc_a_before)    print("After B, vanilla A acc  : %.3f (forgetting!)" % acc_a_vanilla)    print("After B, EWC A acc      : %.3f (protected)" % acc_a_ewc)  if __name__ == "__main__":    main()
目的:用 PyTorch 复现“先学任务 A、再学任务 B”的持续学习小实验,对比普通微调与 EWC 在旧任务上的遗忘程度。
  1. torch.manual_seed(42)固定随机种子,保证每次运行结果可复现,方便对照实验。
  2. task_b = make_data([((-2.0, 0.8), 2), ((2.0, -0.8), 3)])让新任务的位置与旧任务重叠,人为制造“抢地盘”的冲突,使灾难性遗忘更明显。
  3. fisher = compute_fisher(base, *task_a)在学完任务 A 的模型上计算 Fisher 信息,给每个参数打“重要性分”。
  4. reg = sum((fisher[n] * (p - old_params[n]) ** 2).sum() for n, p in model.named_parameters())EWC 惩罚项:按 Fisher 加权,越重要的参数越不许乱动。
  5. vanilla = copy.deepcopy(base)从同一个“学完任务 A”的模型复制出两份,保证普通微调与 EWC 的起点完全公平。
  6. if __name__ == "__main__": main()标准可执行入口,直接运行即可看到两组对比数字。

常见误区

误区“EWC 不就是给损失加了一个平方项吗?那跟 L2 权重衰减差不多,直接把 weight decay 调大点不就行了?”

正解L2 把所有参数平等地压向 0;EWC 的惩罚是压向“旧任务学好的参数值”,并且按 Fisher 信息加权——重要的参数罚得重、不重要的几乎不罚。方向(往哪压)和力度(每根弹簧的劲)都不同,就像“给所有条目贴胶带”和“只给关键页贴胶带”是两码事。

为何常见:两者形式上都是二次项,初学者只看到平方结构,却忽略了“锚点是谁、权重是多少”这两个本质区别。

误区“把旧样本和新样本放一起训练,不就是对旧数据过拟合吗?费时费力还容易把新任务压制住。”

正解Replay 的关键是“少量、有代表性、按比例混合”。缓冲池一般只保留几百到几千个旧样本,作用是维持优化路径不被新任务完全拉偏,而不是把旧样本背下来。它本质上是“新旧经验的配额制”,让梯度方向同时照顾两头;合理设计后新任务的准确率几乎不损失。

为何常见:人们把“重复训练旧数据”和“均衡混训”混为一谈,忽视了比例与采样设计才是 Replay 的灵魂。

误区“不存旧数据怎么可能不忘旧知识?LwF 肯定偷偷用了旧任务的测试集。”

正解LwF 确实只用“新任务的数据”。它保存的是旧模型的参数快照,把新数据同时过旧模型得到软标签,再用蒸馏损失约束新旧模型在新数据上的行为一致。旧知识以“参数化记忆”的形式存在,不是以数据形式存在。它的真正局限在于:旧模型对没见过的数据可能给出不准的软标签。

为何常见:直觉上觉得知识必须依附于数据,忽略了参数本身就编码了知识。

误区“预训练模型这么强,直接在新任务上微调不就行了?它不会像小模型那样忘的。”

正解预训练模型同样会灾难性遗忘——只是遗忘的起始点更“博学”,但微调对下游旧任务的损害依然显著。缓解手段(LwF / EWC / Replay)对大模型依然有效,尤其 LoRA 等参数高效微调结合 Replay 是常见的工程组合。

为何常见:大模型的涌现能力让人以为它“过目不忘”,其实是因为评测重点放在新任务上,没去测旧任务。

误区“最好的策略应该让旧任务准确率保持 100%,一点不下降才算成功。”

正解完全不忘 = 完全不动参数 = 新任务学不进去,这就是稳定性-可塑性困境。实用的目标是在遗忘率可控(比如 5% 以内)的前提下尽可能学快学好,接受一定代价。EWC 的 λ 调得太大就是“过于稳定”的典型失败案例。

为何常见:直觉上“不忘”是理想,但忽略了模型容量有限、新旧任务权重互相竞争的现实。

面试题

Q1. 下列哪种训练方式最容易触发灾难性遗忘?

单选题 · easy

  • A.旧数据从头训练
  • B.新任务上继续微调← 正确答案
  • C.降低学习率再训练
  • D.新旧数据联合训练

答案:B。从头训练和联合训练都给了旧任务“同台竞技”的机会,不会突然覆盖;学习率调整不改变数据关系。灾难性遗忘的重灾区是“在旧模型上微调新任务”——梯度只看新任务,把旧参数一步步改写,正如老周写新花时擦掉旧花。正确答案是 B。

Q2. EWC 用什么指标来衡量某个参数对旧任务的重要程度?

单选题 · easy

  • A.参数自身的绝对值大小
  • B.Fisher 信息矩阵的对角元← 正确答案
  • C.学习率随训练的变化
  • D.权重衰减的惩罚系数

答案:B。参数绝对值大不代表重要;EWC 用 Fisher 信息矩阵的对角元衡量每个参数对旧任务预测的影响——F 越大越重要、惩罚越重。就好比手账里“划掉它会毁掉很多知识”的条目才值得贴荧光胶带。正确答案是 B。

Q3. 以下属于缓解灾难性遗忘主流思想的有哪些?

多选题 · mid

  • A.回放旧样本保持记忆← 正确答案
  • B.加固重要参数防覆盖← 正确答案
  • C.用旧模型输出做蒸馏← 正确答案
  • D.增大批次提升训练速度

答案:ABC。回放旧样本(Replay)、加固重要参数(EWC)、用旧模型输出做蒸馏(LwF)是三大主流思想;增大批次只影响训练速度,并不解决遗忘问题。正确答案为 A、B、C 三项。

Q4. 在 LwF 中,冻结的旧模型主要负责做什么?

单选题 · mid

  • A.对新数据输出软标签← 正确答案
  • B.增加总参数量上限
  • C.替新模型做数据增强
  • D.生成更多旧样本数据

答案:A。LwF 的旧模型被冻结,拿新数据当输入、输出软标签,代表“旧知识对新数据的看法”,蒸馏损失让新模型别偏离。它不增加参数量,也不做增强或生成。正确答案是 A。

Q5. EWC 损失中的 λ 增大会导致什么?

单选题 · easy

  • A.新任务学得更快更好
  • B.旧任务保住新任务变差← 正确答案
  • C.模型参数成倍上涨
  • D.训练数据自动增多

答案:B。λ 是 EWC 惩罚项的强度。λ 增大等于胶带贴得越黏,旧参数越不敢动,旧任务保住了,但新任务学得慢、效果变差。这正是稳定性-可塑性困境的直观体现。正确答案是 B。

Q6. 测试时看不到任务编号、必须从所有见过的类别中预测,属于哪种设定?

单选题 · hard

  • A.任务增量学习,测试有任务编号
  • B.领域增量学习,标签集合不变
  • C.类别增量学习,混合预测全部类别← 正确答案
  • D.多任务学习,所有数据同时训练

答案:C。Task-IL 测试时给出任务编号,只需在对应任务头上分类;Domain-IL 标签集合不变、只变输入分布;Class-IL 没有任务编号,所有见过的类别一起猜,最容易遗忘,也最贴近在线标注的现实。正确答案是 C。

Q7. 设计经验重放的缓冲池时,需要权衡的因素有哪些?

多选题 · hard

  • A.存储容量与隐私限制← 正确答案
  • B.所选样本的代表性← 正确答案
  • C.新旧样本的混合比例← 正确答案
  • D.网络隐藏层神经元数

答案:ABC。缓冲池要考虑容量与隐私(哪些数据能留存)、代表性(水库采样保证公平)、混合比例(新旧样本各占多少);隐藏层神经元数是网络结构问题,与缓冲池设计无关。正确答案为 A、B、C 三项。

Q8. 知识蒸馏中温度 T 的主要作用是什么?

单选题 · mid

  • A.放大类别间的相似信息← 正确答案
  • B.降低模型推理的延迟
  • C.缩小训练集的大小
  • D.成倍提高学习率上限

答案:A。温度 T 把输出分布变得平滑,暴露“哪些类别长得像哪些类别”的暗知识,让蒸馏信号更丰富。它不改变推理延迟、数据集大小或学习率。正确答案是 A。

Q9. 持续学习中常用的评估指标包括哪些?

多选题 · mid

  • A.所有任务的平均准确率← 正确答案
  • B.学完新任务的遗忘率← 正确答案
  • C.训练时使用的参数量
  • D.每次推理所需的时间

答案:AB。平均准确率看整体表现,遗忘率看旧任务跌了多少,两者结合才能全面评价持续学习策略;参数量和推理速度是工程指标,不是“忘没忘”的度量。正确答案为 A、B 两项。

Q10. 关于遗忘率的计算方式,下列描述正确的是?

单选题 · hard

  • A.旧任务较历史峰值的下降量← 正确答案
  • B.新旧任务准确率的比值
  • C.加策略前后参数量的差
  • D.新样本占总样本的比例

答案:A。遗忘率统计的是旧任务准确率相对历史峰值的下降量,数值越小说明防忘越好。比值、参数量差、样本数占比都与遗忘的定义无关。这就像老周量旧花“从最旺时跌了几成”,而不是看新花长得多高。正确答案是 A。