高三学生小林最近很苦恼:学校为了让他冲刺高考,新增了不少选修单元;每学完一个新单元,再翻回上一个单元,原本熟悉的公式却变得陌生。这不是记性差,而是他总在一本笔记本上不停写新内容,新墨水把旧字迹层层盖住。AI 模型也有同样的问题,叫灾难性遗忘。为了保证大模型在持续学习新知识的同时不忘旧本领,工程师们发展出三条经典思路:经验回放像错题本,参数隔离像分科笔记本,正则化约束像荧光标签;到了大模型落地时,又用 LoRA 便利贴轻量更新。最后还要用全年级统考式的评估体系,检查模型是不是真的“没忘”。

岗位关联

持续学习是让大模型可持续进化的基础设施能力。掌握防遗忘策略,你就能在业务模型反复迭代时稳住知识底线,成为真正懂落地的算法工程师。

目录
  1. 可视化演示
  2. 遗忘根源
  3. 经验回放
  4. 参数隔离
  5. 正则化约束
  6. 大模型落地
  7. 场景评估
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

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

遗忘根源

小林决定把物理和化学记在同一本笔记本上。物理笔记还没翻熟,化学新内容就呼呼地写上来,等他想复习物理时,发现原来的公式都被新墨水压花了。这种现象放在神经网络里,就是持续学习最著名的敌人——灾难性遗忘。模型没有“橡皮擦”,但参数更新时,新任务的梯度会不自觉地覆盖旧任务学到的决策边界。

为什么会覆盖?神经网络的记忆分布在权重里。训练新任务时,梯度更新让权重向新任务的“山谷”移动;可旧任务的最优解往往不在同一方向。沿着新任务梯度走一步,旧任务权重就被推向“悬崖”,旧任务的准确率随之崩塌。这背后正是“稳定-塑性两难”:模型太稳定学不进新东西,太可塑又容易忘掉旧东西。

为了把“遗忘”变成可以测量的数字,持续学习引入遗忘率。假设旧任务 $t$ 刚学完时准确率是初始值,学完若干新任务后再测,准确率变成当前值。遗忘率公式显示的是旧任务成绩的相对跌幅。

小林恍然大悟:不换方法,物理成绩迟早清零。于是他开始了第一项改造——准备一个错题本。

ForgetRate=Acctinit−AcctafterAcctinit×100%\displaystyle \text{ForgetRate} = \frac{\text{Acc}_t^{\text{init}} - \text{Acc}_t^{\text{after}}}{\text{Acc}_t^{\text{init}}} \times 100\%
遗忘率相当于“旧笔记被新墨水覆盖的比例”,0% 是没忘,100% 是彻底清空。
  1. 旧任务编号$t$ 表示已学过的任务编号,比如高三上学期的物理单元。
    t∈{1,2,…,T}t \in \{1, 2, \ldots, T\}
  2. 初始准确率$\text{Acc}_t^{\text{init}}$ 是刚学完任务 $t$ 时的评测分数,代表“记忆基线”。
    Acctinit\text{Acc}_t^{\text{init}}
  3. 当前准确率$\text{Acc}_t^{\text{after}}$ 是学了若干新任务后,再次评测旧任务 $t$ 的分数,反映残留记忆。
    Acctafter\text{Acc}_t^{\text{after}}
  4. 遗忘程度分子是成绩下降量,除以初始成绩得到相对下降比例,再乘 $100\%$ 方便阅读。
    Acctinit−AcctafterAcctinit\frac{\text{Acc}_t^{\text{init}} - \text{Acc}_t^{\text{after}}}{\text{Acc}_t^{\text{init}}}
  5. 结果解读$100\%$ 表示旧知识完全清零,$0\%$ 表示一点没忘。
    ForgetRate→0%\text{ForgetRate} \to 0\%

经验回放

错题本不用多解释:每次学习化学前,小林会花十分钟重做物理错题。模型的“错题本”叫记忆缓冲区,里面存着旧任务挑选出来的样本。训练新任务时,每次梯度更新都会混入这些旧样本,让梯度同时兼顾新旧两边。

直觉上,这不就是把两个数据集拼起来训练吗?不完全一样。经验回放并不等于简单合并,它强调新任务为主、旧样本为辅,用一个平衡系数 $\lambda$ 控制复习力度。更高级的回放还会做重要性采样,或按任务难度动态分配缓冲区空间,避免某些旧任务被“冷落”。

损失函数由两项构成:新任务损失和旧样本重放损失。这样模型既要理解新知识,也要维持旧知识的决策边界。

错题本有效,但小林发现物理错题越来越多,本子越来越重;而且有些错题涉及隐私,不能随便拿给别人看。于是他又想到:干脆分科记笔记。

Ltotal=E(x,y)∼Dnew[ℓ(fθ(x),y)]+λ E(x,y)∼B[ℓ(fθ(x),y)]\displaystyle \mathcal{L}_{\text{total}} = \mathbb{E}_{(x,y)\sim \mathcal{D}_{\text{new}}}\left[\ell(f_\theta(x),y)\right] + \lambda\,\mathbb{E}_{(x,y)\sim \mathcal{B}}\left[\ell(f_\theta(x),y)\right]
这个公式可以理解成“化学作业 + λ 倍的物理错题复习”,λ 越大,复习旧知识的优先级越高。
  1. 新任务数据分布$\mathcal{D}_{\text{new}}$ 表示当前正在学习的新单元,模型首先要在这批数据上降低损失。
    (x,y)∼Dnew(x,y)\sim \mathcal{D}_{\text{new}}
  2. 旧样本集合$\mathcal{B}$ 是记忆缓冲区,存储过去任务挑出来的代表样本,相当于错题本。
    (x,y)∼B(x,y)\sim \mathcal{B}
  3. 损失函数$\ell(\cdot)$ 计算模型预测 $f_\theta(x)$ 与真实标签 $y$ 的差距,越小越好。
    ℓ(fθ(x),y)\ell(f_\theta(x), y)
  4. 平衡系数$\lambda$ 控制“复习”力度,太小防不住遗忘,太大会拖慢新知识吸收。
    λ∈[0,+∞)\lambda \in [0, +\infty)
  5. 联合最小化$+$ 号让模型同时对新旧数据负责,阻止梯度只朝新任务方向跑。
    Lnew+λLreplay\mathcal{L}_{\text{new}} + \lambda \mathcal{L}_{\text{replay}}

参数隔离

分科笔记本这招很绝:物理一本、化学一本、数学一本,封面写上“互不串写”。模型训练中,参数隔离就是为每个任务划出独立的参数区域,或者给任务关键路径上锁,新任务只能更新没有锁的区域。这里既可以直接冻结旧参数,也可以为每个任务准备专属参数,还可以用门控机制做稀疏更新,甚至动态扩充网络结构。

数学上,用冻结集合 $\mathcal{F}$ 标记不能动的参数。对于每个权重 $w_i$,如果它在 $\mathcal{F}$ 里,就保持原值;不在 $\mathcal{F}$ 里,才执行梯度下降。这就像在笔记本上贴了“此处勿写”的便签。

完全隔离虽然保护了旧任务,但每个任务都要占一块地盘;小林的书包撑不下。于是他想用更省空间的柔性办法:给重点公式贴荧光标签。

wi(k)={wi(k−1)−η∂L∂wi,i∉Fwi(k−1),i∈F\displaystyle w_i^{(k)} = \begin{cases} w_i^{(k-1)} - \eta \frac{\partial \mathcal{L}}{\partial w_i}, & i \notin \mathcal{F} \\ w_i^{(k-1)}, & i \in \mathcal{F} \end{cases}
公式读作:没被冻结的参数按梯度下降正常更新,被冻结的参数原封不动,相当于翻页时绕过旧笔记区域。
  1. 参数编号$i$ 代表网络里其中一个权重,比如一条神经元连接线的强度。
    wiw_i
  2. 冻结集合$\mathcal{F}$ 是需要保护的任务关键参数清单,相当于“禁止涂写”的页面列表。
    i∈Fi \in \mathcal{F}
  3. 普通更新$i \notin \mathcal{F}$ 表示未被冻结的参数,用梯度下降正常学习新任务。
    wi(k−1)−η∂L∂wiw_i^{(k-1)} - \eta \frac{\partial \mathcal{L}}{\partial w_i}
  4. 保序不变$i \in \mathcal{F}$ 的参数保持原来的值 $w_i^{(k-1)}$,旧知识点不被改动。
    wi(k)=wi(k−1)w_i^{(k)} = w_i^{(k-1)}
  5. 学习率$\eta$ 控制每一步参数调整幅度,对冻结参数相当于乘以 0,即不更新。
    η>0\eta > 0

正则化约束

荧光标签不重写笔记,只标记重点。EWC(弹性权重巩固)正是这样:它用 Fisher 信息矩阵给每个参数计算“重要性分数”,重要的参数即使更新,也会被惩罚拉回原位,不重要的参数则自由活动。另一些正则化思路还包括用知识蒸馏约束新模型输出,或直接抑制与旧任务相关的激活路径。

于是损失函数变成两项:新任务损失加上一个惩罚项。惩罚项度量当前参数与旧任务最优参数之间的距离,并用重要性加权。

柔性约束平衡了新旧任务,小林不再怕写化学时蹭花物理公式。但大模型时代,全量参数算一遍 Fisher 信息太昂贵,直接给上百亿参数“贴标签”不现实。

Ltotal=Lnew+β2∑iFi(θi−θi∗)2\displaystyle \mathcal{L}_{\text{total}} = \mathcal{L}_{\text{new}} + \frac{\beta}{2} \sum_{i} F_i (\theta_i - \theta_i^*)^2
这就像在重点公式上贴荧光标签后,写新内容时虽然可以触碰纸张,但一旦偏离重点太远,就会有一种“弹性拉力”把它拽回原位。
  1. 新任务损失$\mathcal{L}_{\text{new}}$ 是模型在当前任务上的错误程度,需要降低。
    Lnew\mathcal{L}_{\text{new}}
  2. 旧参数锚点$\theta_i^*$ 是学完旧任务后参数 $i$ 的值,相当于荧光标签所在位置。
    θi∗\theta_i^*
  3. 重要性权重$F_i$ 是 Fisher 信息,表示该参数对旧任务有多关键,越关键数值越大。
    FiF_i
  4. 平方惩罚$(\theta_i - \theta_i^*)^2$ 让参数偏离旧值越大,受到的惩罚越强,不许乱跑。
    (θi−θi∗)2(\theta_i - \theta_i^*)^2
  5. 强度系数$\beta$ 控制整体“守旧”程度,太小容易忘,太大新知识学不进去。
    β2>0\frac{\beta}{2} > 0

大模型落地

大学霸小林的升级版——他已经是全校最顶尖的学霸。面对新知识,他不会重写整本笔记本,而是贴一张黄色便利贴。大模型里的“便利贴”,就是 LoRA。它冻结原始参数 $W_0$,只训练两个很小的低秩矩阵 $A$ 和 $B$。

前向计算时,新增的 $BA$ 乘上缩放系数加到原始输出上。这等于在原始笔记本的空白处加上新内容,原有文字一个字母都不动。训练时只更新便利贴,因此旧知识被天然保护。落地时,还会配合数据混训配比、知识编辑联动和安全护栏验证,一旦旧任务指标跌破阈值就自动回滚。

LoRA 的便利贴既能学新任务,又不会与旧任务冲突。但它并不是银弹,最终效果需要放进统一的考场验证。

h=W0x+αrBAx\displaystyle h = W_0 x + \frac{\alpha}{r} B A x
公式意思是:原始大模型照常输出,LoRA 便利贴在旁边补充一小块新知识,两者相加得到最终答案。
  1. 原始权重$W_0 x$ 是预训练大模型原本对输入 $x$ 的变换,类似大学霸已有知识。
    W0xW_0 x
  2. 低秩矩阵$A, B$ 是两个小矩阵,乘积 $BA$ 模拟权重增量,但参数量小得多。
    BABA
  3. 缩放系数$\alpha / r$ 控制新增模块的影响强度,$r$ 是秩,$r$ 越小越省参数。
    αr\frac{\alpha}{r}
  4. 并行加法新增部分与原始输出相加,等价于在原笔记上贴便利贴,不涂改原文。
    W0x+αrBAxW_0 x + \frac{\alpha}{r} B A x
  5. 训练目标仅优化 $A, B$,$W_0$ 冻结,所以旧知识天然不被破坏。
    min⁡A,BL\min_{A,B} \mathcal{L}

场景评估

小林担心自己只是“感觉没忘”,于是学校安排了全年级统考:既考新单元,又考旧单元。持续学习也必须有统一的考场,否则只看新任务分数,很容易被虚假繁荣欺骗。多任务迭代、领域增量适应、知识时效更新等场景,都需要一套测评基准来回答“到底忘了没有”。

后向迁移指标 BWT 就是这场统考的成绩单。它把所有旧任务在新任务训练后的成绩变化做平均。BWT 接近 0,说明模型既学到了新知识又守住了旧知识;明显为负,说明灾难性遗忘仍然存在。

有了 BWT 这座灯塔,持续学习工程化才成为可能。多任务迭代、领域增量、知识时效更新都可以先用 BWT 体检,再决定是否扩大回放、切换 LoRA 或触发回滚。

BWT=1T−1∑t=1T−1(RT,t−Rt,t)\displaystyle \text{BWT} = \frac{1}{T-1} \sum_{t=1}^{T-1}\left(R_{T,t} - R_{t,t}\right)
BWT 就像全年级统考里,把每个旧科目现在的平均分和刚学完时的平均分对比,负分越多说明遗忘越严重。
  1. 总任务数$T$ 是到目前为止学过的任务总数,比如 6 个单元。
    TT
  2. 历史任务编号$t$ 是之前学过的旧单元编号,从 1 到 $T-1$。
    t=1,2,…,T−1t = 1, 2, \ldots, T-1
  3. 初始成绩$R_{t,t}$ 是刚学完任务 $t$ 时的测试准确率,作为个人基线。
    Rt,tR_{t,t}
  4. 期末成绩$R_{T,t}$ 是学完最新任务 $T$ 后,再考旧单元 $t$ 的准确率。
    RT,tR_{T,t}
  5. 平均回退对所有旧单元求差分均值。若为负,说明出现遗忘;接近 0 表示稳定。
    1T−1∑t=1T−1(RT,t−Rt,t)\frac{1}{T-1} \sum_{t=1}^{T-1}\left(R_{T,t} - R_{t,t}\right)

AI 应用场景

电商大模型的持续品类迭代

阶段:模型持续训练与迭代

解决的问题:电商大模型每隔几周要吸收新品类知识,直接全量微调会导致老品类召回率直线下滑。经验回放通过把旧行为样本按比例注入新训练集,让模型同时保有老品认知和新增量化能力。

具体案例:某电商平台新品季使用含 15%-30% 旧样本的经验回放后,新品类转化率提升 11%,老品类召回下降幅度从 9% 收窄到 2%。

多业务线客服大模型的领域增量

阶段:领域增量适配

解决的问题:客服大模型需要为多个业务线学习不同话术,如果共用一套参数,业务线间会互相干扰。参数隔离/LoRA 让每个业务线拥有独立适配器,互不覆盖。

具体案例:银行客服团队为理财、信用卡、贷款三块业务分别训练 LoRA 适配器,更新贷款话术时信用卡业务效果不降反升。

代码大模型的新版本知识更新

阶段:知识更新与评价

解决的问题:模型学了新框架或新法规后,旧知识容易被覆盖,且难以发现。结合 BWT 评测体系做定期体检,发现退化立即回滚。

具体案例:开源代码模型引入新版本 API 时,持续监控旧 API 的生成正确率,BWT 跌破阈值就自动切回旧适配器。

Python 演示

python66 行
import numpy as np  def make_task(seed, angle):    rng = np.random.default_rng(seed)    x = rng.normal(size=(200, 2))    rot = np.array([[np.cos(angle), -np.sin(angle)],                    [np.sin(angle), np.cos(angle)]])    x = np.dot(x, rot)    y = np.where(x[:, 0] > 0, 1, -1)    return x, y  class LinearModel:    def __init__(self, dim=2):        self.w = np.zeros(dim)        self.b = 0.0     def predict(self, x):        return np.sign(np.dot(x, self.w) + self.b)     def accuracy(self, x, y):        return float(np.mean(self.predict(x) == y))     def train(self, x, y, lr=0.1, epochs=3):        for _ in range(epochs):            for xi, yi in zip(x, y):                if yi * (np.dot(xi, self.w) + self.b) <= 0:                    self.w += lr * yi * xi                    self.b += lr * yi  def evaluate_all(model):    tasks = [(0, 0.0), (1, 0.8), (2, 1.6)]    return [model.accuracy(*make_task(seed + 100, angle)) for seed, angle in tasks]  def train_continual(use_replay, replay_ratio=0.5):    model = LinearModel()    buffer = []    results = []    for task_id, (seed, angle) in enumerate([(0, 0.0), (1, 0.8), (2, 1.6)]):        x_train, y_train = make_task(seed, angle)        if use_replay and buffer:            rb_x = np.concatenate([mem[0] for mem in buffer])            rb_y = np.concatenate([mem[1] for mem in buffer])            n_replay = int(len(rb_x) * replay_ratio)            idx = np.random.default_rng(task_id).choice(len(rb_x), n_replay, replace=False)            x_train = np.concatenate([x_train, rb_x[idx]])            y_train = np.concatenate([y_train, rb_y[idx]])        model.train(x_train, y_train, lr=0.1, epochs=4)        acc = evaluate_all(model)        results.append(acc)        print("Task {} acc: {}".format(task_id + 1, acc))        buffer.append((x_train[:100], y_train[:100]))    return results  if __name__ == "__main__":    print("Without replay:")    no_replay = train_continual(False)    print("\nWith replay:")    with_replay = train_continual(True)    print("\nFirst task trend: no_replay vs replay")    for t in range(3):        print("Task{}: {:.3f} -> {:.3f}".format(t + 1, no_replay[t][0], with_replay[t][0]))
目的:用三个旋转角度的二分类任务模拟持续学习,对比“无回放”和“有回放”在旧任务上的表现差异。
  1. def make_task(seed, angle):产生一个由角度旋转的线性可分任务,模拟不同知识单元。
  2. if use_replay and buffer:只在启用回放且已有旧样本时,才从记忆缓冲区中抽样。
  3. x_train = np.concatenate([x_train, rb_x[idx]])将抽出的旧样本拼接到新任务批次,让梯度看到旧知识。
  4. self.w += lr * yi * xi感知机权重更新,新任务会带动决策边界偏移,这正是遗忘的来源。
  5. acc = evaluate_all(model)同时评估所有旧任务和新任务,观察回放带来的保护效果。

常见误区

误区我让大模型用新数据继续跑几个 epoch,不就已经学会新知识了吗?为什么还要研究防遗忘?

正解普通继续训练会触发灾难性遗忘:新任务梯度把旧任务参数推向不利区域。持续学习要求用回放、隔离、正则化等方法给旧知识留退路,而不是“多训一点”就能解决。

为何常见:预训练后继续训练和微调很常见,容易误以为“多训一点”只是增加数据。

误区经验回放那么有效,我直接把全部历史数据重新训练一遍,不就行了吗?

正解历史数据无限膨胀,训练成本不可控,且很多场景有数据隐私和合规限制。回放需要控制缓冲区大小、采样均衡并设置平衡系数,才能兼顾效果与开销。

为何常见:直观上觉得数据越多越好,忽略了存储、算力和数据权限的约束。

误区为了防止遗忘,我把模型所有参数都冻结,只训练最后的分类头,是不是最好?

正解冻结全部底层会限制新任务学习能力。参数隔离只冻结关键路径或旧任务相关参数,大模型落地更常用 LoRA 冻结主干、增量更新。

为何常见:“隔离”听起来像锁死,实际上是为了选择性保护而非全盘禁止。

误区这版本模型新知识准确率到了 95%,上线没问题了吧?

正解新任务高分可能以牺牲旧任务为代价。需要用 BWT 等指标同时观察旧任务回退,才能判断是否真的“持续”。

为何常见:业务指标常以新功能效果为核心,旧能力下降容易被忽略。

面试题

Q1. 灾难性遗忘的核心表现是什么?

单选题 · easy

  • A.模型参数量突然减少
  • B.学新任务后旧任务性能下降← 正确答案
  • C.新任务训练速度明显变慢
  • D.旧数据从训练集自动消失

答案:B。灾难性遗忘指模型学习新任务后,旧任务准确率大幅回退,因此选 B。A 参数不会凭空减少,C 描述的是学习速度,D 是数据管理问题。

Q2. 下列哪项属于经验回放的核心操作?

单选题 · easy

  • A.冻结所有旧任务参数
  • B.训练时混入旧任务样本← 正确答案
  • C.删除低重要度参数
  • D.增加模型隐藏层数量

答案:B。经验回放的标志性动作是从记忆缓冲区抽取旧样本,与新样本一起参与训练。A 是参数隔离,C 是剪枝,D 是改结构。

Q3. EWC 衡量参数重要程度使用哪类信息?

单选题 · easy

  • A.Fisher 信息矩阵← 正确答案
  • B.协方差矩阵
  • C.注意力权重
  • D.梯度范数直方图

答案:A。EWC 用 Fisher 信息矩阵对角元素作为参数重要性。协方差、注意力、梯度直方图都不是 EWC 的标准来源。

Q4. 在 LoRA 增量中,预训练权重应如何处理?

单选题 · mid

  • A.与新增矩阵同步更新
  • B.完全冻结只更新低秩矩阵← 正确答案
  • C.随机初始化后再次训练
  • D.量化压缩再参与更新

答案:B。LoRA 的核心是冻结 $W_0$,只优化低秩矩阵 A、B,这样参数高效且不改旧知识。同步更新、重新初始化、量化更新都不是 LoRA 的定位。

Q5. BWT 指标为负数说明什么?

单选题 · mid

  • A.新任务学习效果很差
  • B.旧任务出现明显回退← 正确答案
  • C.参数更新幅度太大
  • D.数据分布完全改变

答案:B。BWT 计算旧任务在学完新任务后的准确率与初始准确率之差,负值说明旧任务性能下降,即发生遗忘。A 关心新任务,C 和 D 是无关诱因。

Q6. 任务数量多且边界清晰时,首选哪类策略?

单选题 · mid

  • A.扩大经验回放缓冲
  • B.使用参数隔离技术← 正确答案
  • C.增强随机梯度裁剪
  • D.提高模型学习率

答案:B。任务边界清晰时,参数隔离能把不同任务分配到独立参数空间,避免相互覆盖。回放需要存储且仍可能遗忘,梯度裁剪和学习率不是主要手段。

Q7. 大模型落地持续学习优先选 LoRA 的主要原因?

单选题 · mid

  • A.只更新少量低秩增量参数← 正确答案
  • B.LoRA 完全不需要数据集
  • C.输出维度会自动变低
  • D.全量微调无法上 GPU

答案:A。LoRA 冻结原权重,只训练低秩增量,成本低且能保护旧知识。LoRA 仍然需要数据,输出维度不变,全量微调也能上 GPU 只是昂贵危险。

Q8. 下列哪些措施可缓解灾难性遗忘?

多选题 · easy

  • A.训练时重放旧样本← 正确答案
  • B.冻结任务关键参数← 正确答案
  • C.丢弃全部历史数据
  • D.对重要权重加惩罚← 正确答案

答案:ABD。重放旧样本、冻结关键参数、重要权重正则化都能保护旧知识。丢弃历史数据会让模型失去对旧任务的记忆,加剧遗忘。

Q9. 关于经验回放缓冲区,正确的说法有?

多选题 · mid

  • A.样本需尽量代表旧任务← 正确答案
  • B.回放比例越大效果越好
  • C.会额外占用存储算力← 正确答案
  • D.采样完全无需平衡

答案:AC。缓冲区应覆盖旧任务分布,过度增大回放比例会拖慢新任务学习,且占用存储算力,因此 A、C 正确,B、D 错误。

Q10. 持续学习测评体系应关注哪些指标?

多选题 · hard

  • A.新任务最终准确率← 正确答案
  • B.旧任务回退程度← 正确答案
  • C.前向迁移效果← 正确答案
  • D.模型参数量大小

答案:ABC。完整测评要同时看新任务效果(塑性)、旧任务保持(稳定性)和前向迁移能力。模型参数量与防遗忘效果无直接关系。