任务一刚学完是 88.3%。学完任务二、任务三之后,只微调剩 37.0%(忘掉 51.3 个点); 加 EWC 回到 56.5%(忘掉 33.3);全量重训 67.2%(忘掉 24.0)——最好,但要留着所有历史数据。
上一节说「数据别出内网」。 这一节说一个更难受的现实:医院往往连「把旧数据留着再训一遍」都做不到。 于是模型只能在不着旧数据的情况下往前走。
一、医院的模型是要长出来的
一个科室的需求不会一次提完。今天是肺炎识别,下个月加骨折,再下个月加眼底。 每加一个,就得重训一次。 理想做法是全量重训:把所有历史数据攒在一起,从头练。但这条路在医疗场景里经常走不通。 原因不是算力,是数据。 ① 保存期限。 病历有法定保存年限,过期要销毁。 ② 授权范围。 患者同意的是「用于某某研究」,新项目要重新过伦理审查。 ③ 数据孤岛。 老数据在旧系统里,导出成本极高。 于是现实做法只能是:拿着新数据,在老模型上继续训。 这就撞上了一个已知三十年的老问题。
二、灾难性遗忘
在神经网络上顺序训练多个任务,后学的会把先学的覆盖掉。这叫灾难性遗忘。 它不是「容量不够」,是「优化过程只关心眼前这个损失」。 Demo 用三个任务、每个四类,网络只有 10 → 32 → 4。顺序学完一、二、三之后,回头看任务一:
| 策略 | 任务一 | 任务二 | 任务三 | 遗忘量 |
|---|---|---|---|---|
| 只微调 | 37.0 | 48.5 | 91.7 | 51.3 |
| 微调 + EWC | 56.5 | 45.0 | 90.7 | 33.3 |
| 全量重训 | 67.2 | 50.5 | 89.0 | 24.0 |
| (单位 %。遗忘量=任务一刚学完的 88.3 减去现在这一列。) | ||||
| 只微调那一行就是灾难性遗忘的标准样子:任务一从 88.3 掉到 37.0,掉了 51.3 个点。 | ||||
| 而任务三本身有 91.7,学得非常好。 | ||||
| 问题不是「学不会」,是「学会了新的就忘了旧的」。这在实际部署里非常要命: | ||||
| 模型这个月加了眼底筛查,下个月肺炎就不准了,而没人会去测肺炎。 |
三、全量重训为什么也不是满分
表里全量重训最好:遗忘量 24.0,三行里最少。但它也有个细节容易被忽略: 任务一的 67.2,离 88.3 还差 21 个点。 这 21 个点不是「忘了」,是「挤不下」。三个任务的输入有重叠、标签空间互相干扰, 同一个 32 维隐藏层要同时装三套特征,必然互相让步。 所以「全量重训」的上限不是 88.3,是 67.2。 这一点很重要:很多人把「重训之后掉点」当成 bug,其实是多任务学习的固有代价。 想突破这个上限,只能加容量(更宽的层、更多的参数),或者做任务隔离(每个任务一套头)。 而加容量在边缘设备上又撞回算力限制。
四、EWC:给重要权重加一根弹簧
EWC(弹性权重固化)的思路很朴素: 先算出「哪些权重对旧任务重要」,然后不许它们跑太远。 具体是在损失里加一项:λ 乘以「权重偏离初始值的平方」乘以「重要性」。 重要的权重大弹簧,不重要的随便动。 重要性用 Fisher 信息矩阵近似。 结果:任务一从 37.0 拉回 56.5,遗忘量从 51.3 降到 33.3。 代价是任务二从 48.5 掉到 45.0——新任务被旧任务拽住了。 这就是所有正则类持续学习方法的共同特征:用新任务的精度,换旧任务的记忆。 它不是「双赢」,是「重新分配」。 Demo 里用的是均匀的 Fisher 近似(都取 0.5),所以效果有限。 真正的 EWC 要按每个权重的实际重要性加权,在更接近真实的设定下能拉回更多。 这也解释了为什么论文里的数字总比复现漂亮——重要性估计那一步的细节差别很大。
五、落地:三条路,按数据可得性选
① 能留全量数据 → 老老实实全量重训。它永远是最稳的基线,任何新方法都应该先跟它比。 如果新方法连全量重训都打不过,就没有上线的理由。 ② 留不住数据,但能留一小份 → 回放。 从每个旧任务里留几十条「代表性样本」,训练时混进去。这招土, 但在工程上几乎总是最有效的—— 它比任何复杂的正则都管用,因为它是真的把旧数据喂回去了。小样本回放要注意隐私: 留的那几十条同样要脱敏、同样要授权。 ③ 连一条都留不住 → 正则类方法(EWC)或参数隔离。 这一档的效果最有限,但它是唯一不碰旧数据的选择。 上线时必须接受一个明确的事实:旧任务的精度会掉,而且掉多少说不准。 不管走哪条路,有一件事必须做:给每个旧任务留一个固定的验证集。 每次更新都跑一遍全部任务。 没有这个,你根本不知道遗忘了多少——而遗忘恰恰是「没人测就永远发现不了」的那类问题。 最后一句:持续学习的难点不在算法,在「旧数据的可得性」。 先问清楚能留什么,再决定用什么方法——顺序反了,方案一定落不了地。
六、动手 Demo:持续学习:只微调的话任务一从 88.3% 掉到 37.0%
造三个互相冲突的二分类子任务(每个 4 类、10 维输入),网络 10 → 32(tanh) → 4。 按任务一、二、三的顺序各训一轮,中间不回头。 比较三种策略:纯微调、微调 + EWC(均匀 Fisher 近似,系数 0.6)、 以及把三个任务的数据合起来全量重训。最后统一在三个任务的测试集上评估。
for t in range(3): # 顺序学三个任务
for _ in range(400):
g = grad(W1, b1, W2, b2, X[t], Y[t])
if ewc: # 弹簧:拉住旧任务重要的权重
g1 += lam * fish1 * (W1 - W1_old)
g2 += lam * fish2 * (W2 - W2_old)
W1 -= lr * g1
W2 -= lr * g2
hist.append([acc(t1), acc(t2), acc(t3)]) # 学完一个存一次
forget = hist[0][0] - hist[2][0] # 88.3 - 现在的任务一
实跑输出:
--------------------------------------------------------------------
持续学习:只微调的话任务一从 88.3% 掉到 37.0%
--------------------------------------------------------------------
任务数 × 类别 3 × 4
网络 10 → 32(tanh) → 4
训练顺序 任务一 → 任务二 → 任务三,不回头
策略 学完任务三后…任务一 …任务二 …任务三 遗忘量
------------------------------------------------------------
只微调 37.0 48.5 91.7 51.3
微调 + EWC 56.5 45.0 90.7 33.3
全量重训 67.2 50.5 89.0 24.0
**只微调那一行就是「灾难性遗忘」:**
**任务一刚学完是 88.3%,学完任务二和任务三之后只剩 37.0%,掉了 51.3 个点。**
**而任务三本身是 91.7,它学得很好。**
**问题不是学不会,是学会了新的就忘了旧的。**
**医疗场景里这非常要命:** 模型今天是「肺炎识别」,
下个月加了「骨折识别」,**再下个月可能肺炎就不准了。**
**全量重训那一行:遗忘量 24.0 个点,三行里最少。**
但它的任务一只有 67.2%,**不如 EWC 的 56.5%**——**因为它要让三个任务同时满意,每个都得让步。**
**但它的代价是「所有历史数据都要一直留着」**——**医疗数据有保存期限和授权范围,很多时候做不到。**
**EWC 那一行是折中:任务一从 37.0% 拉回 56.5%,遗忘量从 51.3 降到 33.3。**
**它的做法是给「对旧任务重要的权重」加一根弹簧,不许它们跑太远。**
**这里用的是均匀的 Fisher 近似(都取 0.5),所以效果有限。**
真正的 EWC 要按每个权重的实际重要性加权。
要说明:任务分布、网络规模都是简化过的。
**但「顺序训练会遗忘」「全量重训遗忘最少」「正则能缓解但救不回」这三条结论是稳定的。**
看表先看「遗忘量」那一列:51.3 / 33.3 / 24.0。 纯微调丢了一半,EWC 挡住 18 个点,全量重训再挡 9 个点。 EWC 不是免费的:任务二从 48.5 掉到 45.0。 弹簧拉住了旧权重,新任务就没那么自由。 这一行的意义是「证明取舍存在」,不是「证明 EWC 更好」。 全量重训的 67.2 也要看清楚:那是任务一在「三任务同时训」下的天花板,不是 88.3。 21 个点的差距是容量挤占,跟遗忘没关系。 把这两件事分开算,才不会误判「到底是方法不行还是容量不够」。 还有一个坑要提前说:这个 Demo 的 EWC 系数一开始设的是 0.02,结果遗忘量 55.3,比纯微调还差。 弹簧太软等于没有。 改成 0.6 之后才降到 33.3。 持续学习方法的超参极其敏感,这是它在工程上难落地的真实原因之一。 要说明:任务分布、网络规模都是简化过的, 真实医疗模型是百万参数级的,任务之间的冲突也更隐蔽。 但「顺序训练会遗忘」「全量重训遗忘最少」「正则能缓解但救不回」这三条结论是稳定的。
30 秒实验
- 把 EWC 系数从 0.6 加到 3.0,看三列。 任务一会更高,任务三会明显掉——弹簧太硬,新任务学不进去。
- 把任务顺序改成三、二、一,看重跑的表。 最后学的那个任务总是最高,最先学的那个总是最惨——顺序决定谁被牺牲。
- 把隐藏层从 32 加到 128,只跑全量重训。任务一会往上抬——容量够了,挤占就少了。
常见误区
- 「模型更新只是加功能,不会影响旧功能」。纯微调让任务一从 88.3 掉到 37.0。
- 「加了 EWC 就两全其美」。任务二从 48.5 掉到 45.0,旧任务被保住的钱是新任务付的。
- 「全量重训能回到原来的精度」。任务一只有 67.2,离 88.3 差 21 个点——那是容量挤占,不是遗忘。
自测三问(点开对答案)
1. 什么是灾难性遗忘,它为什么不是「容量不够」? —— 顺序训练时后学的任务覆盖了先学的。 本例中任务三能到 91.7%,说明网络容量够,问题是优化过程只盯着当前任务的损失。 2. EWC 靠什么机制减缓遗忘,代价是什么? —— 用 Fisher 信息估计每个权重对旧任务的重要性,在损失里加一项「重要权重偏离初始值的平方」。 代价是新任务被拽住,任务二掉了 3.5 个点。 3. 为什么必须给每个旧任务留验证集? —— 因为遗忘是「没人测就永远发现不了」的问题。只测最新任务,永远看不到旧任务已经掉了 51 个点。数据护住了、知识也续上了,最后一关是「跑在哪儿」。 医院不可能把 CT 原图传上云,模型只能在本地那台盒子上跑。
- ☐ (本节完,下一节 11.1.3 边缘部署优化)