【Lifelong learning】Achieving Forgetting Prevention and Knowledge Transfer in Continual Learning

本文探讨了连续学习中的遗忘问题(catastrophic forgetting)和知识转移(knowledge transfer),重点关注如何在预训练模型如BERT中解决这些问题。提出了一种名为CTR(Capsules and Transfer Routing for continual learning)的算法,它通过添加持续学习插件(CL-plugin)到BERT,利用胶囊网络和转移路由机制防止遗忘并促进知识迁移。CL-plugin包含任务胶囊层(TK-Layer)和转移胶囊层(TR-Layer),其中TR-Layer的转移路由算法能识别并跨任务转移知识。实验是在Task-CL设置下进行,CTR算法通过端到端训练,保护任务特定知识,以适应连续学习的挑战。
摘要由CSDN通过智能技术生成

链接:https://link.zhihu.com/?target=https%3A//arxiv.org/abs/2112.02706

简介

本文专注于连续学习的两个方面:

  1. 连续学习(或终身学习)主要面临问题有catastrophic forgetting (CF,学了后面忘了前面)和knowledge transfer (KT,学了前面要对后面任务有帮助)。大部分工作只关注于CF,却忽视了KT。本文专注于如何鼓励知识迁移,因为大量NLP任务之间有很多相似、共同之处。
  2. 预训练模型(如BERT)通常不在连续学习中使用,原因是会导致CF。本文就不信这个邪,硬是探索了一下预训练模型在连续学习的使用,并提出了一个CTR算法

顺便提一下连续学习的两种setting:

  1. Task-CL:训练和测试时都提供每个任务的id,让模型知道这个任务是啥
  2. class continual learning: 训练时提供id,测试时不提供id。

本文处理的是Task-CL情况。

为什么预训练-微调在连续学习不起作用呢?

  • 预训练是没问题的。对特征提取器的预训练可以显著提高持续学习性能。
  • 微调出问题了。比如说我们用BERT,当我们针对某个任务的微调BERT时,我们做的调整是非常特定于任务的,而这对其他任务可能毫无作用,甚至会产生倒退,从而导致严重的CF。

那么怎么办呢?本文提出了CTR算法(Capsules and Transfer Routing for continual learning连续学习的胶囊与转移路由)。

简单来讲,CTR算法是一种对BERT的改进:他在BERT身上装了两个持续学习插件(CL-plugin)模块,每个CL-plugin是一个完整的CL网络,它可以利用预训练模型,处理CF和知识转移。
具体地说,CL-plugin使用一个胶囊(capsule)来表示每个任务,并使用一个转移路由(transfer routing)算法来识别和跨任务转移知识,以达到提高准确性。
CL-plugin进一步学习和使用任务掩码来保护特定于任务的知识,以避免遗忘。

CTR算法有些类似于Adapter-BERT,但不完全一样:

  • Adapter-BERT给每个任务加了一个适应器(Adapter),然后根据遇到的任务类型,选择相应的适应器。
  • CTR算法从头至尾只用2个CL-plugin学习所有任务,更加高效。

大体框架

再次重申,本文的CTR算法是基于BERT一种改进。
实际上,CTR算法可以运用于大部分预训练模型。但简单起见,本文使用BERT进行表述。

给BERT安装CL-plugins

之前说,CTR将2个CL-plugin插入BERT,那插在哪里呢?插在BERT的每个Transformer层。
其实,在一个位置只插入一个CL-plugin也行,但是次优的。
下图给出了CTR架构,我们可以看到2个CL-plugin被添加到BERT中。
训练时,只有2个CL-plugin和分类头被训练,其他的BERT的组成部分是固定的。
在这里插入图片描述

持续学习插件(CL-plugin)

CL-plugin的架构类似于一个胶囊网络(CapsNet)。
在经典神经网络中,神经元输出标量的、实数的激活作为特征检测器。而CapsNets用一个矢量输出胶囊代替了它,以保留额外的信息。
一个简单的CapsNet由两个胶囊层组成:第1层存储低级特征图,第2层生成分类概率,每个胶囊对应一个类。
CapsNet使用动态路由算法使每个低层胶囊将其输出发送到类似的(或“同意的”,由点积计算)高层胶囊。这一特性已经可以用于将相似的任务及其共享特征分组,从而产生一个CL系统。
CL-plugin的一个关键思想(见图2(A))是一个带有新的传输路由(transfer routing)算法的传输胶囊层,该算法可以显式地识别从以前的任务转移到新任务的可转移特性/知识。
此外,传输路由算法还可以对动态路由的迭代次数进行自动调整,也就是说,不用调参了!
在这里插入图片描述

具体细节

CL-plugin的架构如上图所示。
CL-plugin接受两个输入:

  • (1)来自Transformer层内部的前馈层的hidden state h ( t ) h^{(t)} h(t)
  • (2)任务ID t t t。我们做持续学习需要知道现在是哪个任务。

输出的hidden state具有适合于第 t t t个分类任务的特征。

在CL-plugin内部,有两个模块:

  • (1)知识共享模块(KSM),可以从之前类似的任务中识别可共享的知识,并将其转移到新任务 t t t
  • (2)任务特定模块(TSM),可以学习任务特定的神经元及其掩码(从而保护神经元免受被未来的更新任务处理,导致CF)。

由于TSM是可微分的,整个系统CTR可以端到端进行训练。

知识共享模块(KSM)

KSM通过任务胶囊层(TK-Layer)、转移胶囊层(TR-Layer)和转移路由机制,实现知识迁移。

任务胶囊层(TK-Layer)

TK-Layer中的每个胶囊代表一个任务,每个胶囊表示每个任务的低级特性(图2(a))。因此,每个新任务都将一个胶囊添加到TK-Layer中。
在这里插入图片描述

这些胶囊是离散的,不共享参数。此外,每个胶囊由一个简单的2层全连接网络与少量的参数组成。
h ( t ) ∈ R d t × d e h(t)∈R^{d_t×d_e} h(t)Rdt×de为CL-plugin的输入,其中 d t d_t dt为token数, d e d_e de为维数, t t t为当前任务。在TK-Layer中,每个任务都有一个胶囊。
假设到目前为止我们已经学习了 t t t项任务。第 i ( i ≤ t ) i (i≤t) i(it)项任务的胶囊为:
在这里插入图片描述
其中, f i ( ⋅ )

Lifelong Embedding Learning(终身嵌入学习)是一种机器学习技术,它允许模型在面对新任务或数据分布变化时持续学习和适应,同时保持之前知识的稳定性。这种学习方法通常涉及到以下几个步骤: 1. **知识表示**:模型会在每个任务开始时学习到一个新的嵌入空间,用于捕获任务相关的特征。这通常是通过神经网络完成,比如预训练的词向量(如Word2Vec、BERT等)。 2. **迁移更新**:当面临新任务时,模型会利用先前任务学到的知识初始化新的嵌入层,而不是从头开始。这意味着旧的任务特征可以在新任务中有一定的基础。 3. **动态更新**:模型会对新任务的数据进行增量式训练,仅更新与新任务相关的部分,同时使用正则化或其他机制来防止过度拟合并维护已有知识的稳定。 4. **记忆管理**:为了存储历史任务的相关信息,可能会引入在线学习策略或者定期回顾已学过的任务,以便在需要时可以访问。 以下是使用PyTorch实现简单版本的Lifelong Embedding Learning的一个示例代码片段: ```python import torch.nn as nn from torch.optim import Adam class TaskEmbedding(nn.Module): def __init__(self, shared_embedding_size, task_specific_size): super(TaskEmbedding, self).__init__() self.shared = nn.Embedding(num_embeddings=num_tasks, embedding_dim=shared_embedding_size) self.task Specific = nn.Linear(shared_embedding_size, task_specific_size) class LifelongModel(nn.Module): def __init__(self, num_tasks, embedding_size, hidden_size): super(LifelongModel, self).__init__() self.embeddings = nn.ModuleList([TaskEmbedding(embedding_size, hidden_size) for _ in range(num_tasks)]) def forward(self, inputs, task_id): shared_embedding = self.embeddings[task_id].shared(inputs) task_specific_output = self.embeddings[task_id].task_specific(shared_embedding) return task_specific_output # 示例用法 optimizer = Adam(model.parameters(), lr=0.001) for t in range(num_tasks): model.train() optimizer.zero_grad() output = model(inputs, t) loss = F.cross_entropy(output, labels) # 假设labels是对应任务的真实标签 loss.backward() optimizer.step() # 当有新任务时,只需添加新的TaskEmbedding实例,并在适当位置集成进来即可 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值