今天这一篇是ICML2022的很有想法的一篇文章,具体链接点这里
一. 介绍
目前,神经网络在应对不断到来的数据/任务时会出现严重的灾难性遗忘,与此形成鲜明对比的是,随着时间的推移,动物擅长学习和记忆他们遇到的许多不同任务。至少到目前为止,大脑是在复杂环境中成功进行持续学习的唯一现有系统。这突出了审查大脑结构和功能基本事实的重要性,并建议设计神经激励机制来缓解持续学习中的遗忘问题。下面针对大脑的记忆方式进行分析。
- 稀疏连接性: 与DNN密集且高度纠缠的连接性容易受到干扰形成对比,大脑依赖于稀疏连接,其中只有少数神经元对任何给定刺激作出反应。换言之,大脑不会通过稀疏性来累积知识——相反,它会重新连接现有的神经元,以创建更有效的神经通路。这表明我们可以在DNN中转移的第一种机制:持续学习过程中的持续稀疏性。
- 功能和结构可塑性: 大脑通过两种形式的可塑性进行学习。首先,功能性可塑性调节突触传递的强度。功能可塑性的一个具体实例是Spike Timing Dependent plasticity(STDP),它根据相应神经元活动的相对时间控制突触的强度。第二,结构可塑性通过形成新的或移除现有的突触来改变大脑回路。这表明了我们可以转移到DNN的第二种机制:在学习新任务时,重新连接以创建网络中的新路径,并修剪现有路径。
- 避免遗忘的突触稳定性:大脑的一个显著特征是它能够在一生中吸收新信息,而不会破坏先前知识的稳定性。这表明了我们可以转移到DNN的第三种机制:禁用某些隐藏单元输入的梯度更新,以保留先前学习的知识。
- 不会进行大规模的神经元增加: 在一生中学习了越来越多的任务,大脑在神经元数量方面的能力基本保持不变。因此,创造新的神经元并不是大脑学习新任务的首选机制。这表明了我们可以转移到DNN的第四种机制:维护固定容量模型(固定层数和单元数),只是在重新布线时进行动态地改变。
- 不需要进行记忆重塑: 大脑不存储“原始”样本,此外,在学习新任务时,不需要对所有先前已知的任务进行周期性再培训。相反,主要是在睡眠期间,大脑会巩固对重要新经历的记忆,避免新旧记忆之间的干扰(Niethard等人,2017;Yang等人,2014)。这表明了我们可以转移到DNN的第五种机制:不依靠样本的重塑来训练而是在DNN的动态架构中嵌入新的知识。
这里做个简单的解释和总结,我们具体关心的是神经网络应该如何具备这些条件:首先是,在学习一个新的任务的时候不需要特别多的神经元以及所有的参数,只需要很少一部分即可。第二,在训练新任务时我们需要在某些神经元之间额外地添加连接(也就是参数),为了防止无限制添加因此还需要对以前的连接进行修剪。第三,为了防止遗忘,需要冻结住某些参数,防止这些参数改变影响之前的任务。第四,整个模型大小保持不变,并且不需要存储过去的样本。
二. 方法描述
2.1 问题定义
在持续学习中,我们有
T
T
T个序列的任务,对于每个任务我们都有训练集
D
t
D_t
Dt以及验证集
V
t
V_t
Vt。在模型中每一层
l
∈
{
1
,
…
,
L
}
l \in\{1, \ldots, L\}
l∈{1,…,L}有
N
l
N_l
Nl个神经元(unit),我们使用
n
i
l
(
i
∈
{
1
,
…
,
N
l
}
)
n_i^l\left(i \in\left\{1, \ldots, N_l\right\}\right)
nil(i∈{1,…,Nl})表示在
l
l
l层地第
i
i
i个单元,
θ
i
,
j
l
\theta^{l}_{i,j}
θi,jl表示从
n
j
l
−
1
n_j^{l-1}
njl−1传到
n
i
l
n_i^l
nil的参数。定义每个单元的激活函数为
a
n
i
l
(
x
)
a_{n_i^l}(x)
anil(x),并且整个层的激活函数为
a
l
(
x
)
a_l(x)
al(x),这些激活函数包括了所有的单元,这里使用ReLU进行激活。
为了方便大家理解这些东西,我画了个图帮助大家理解,着重注意区别参数和神经元(unit)的区别。
2.2 稳定可塑性单元
想要改变单元 n i l n_i^l nil的值有两种:一是直接改变传入他的参数大小,二是改变之前层的参数,间接地改变。NISPA确保稳定单元仅接收来自其他稳定单元的输入,并且重新添加或修剪连接。此外,在两个任务之间的边界处,它将连接冻结为新的稳定单元,以稳定这些单元,也就是说,它不允许相应的权重在该点之后发生变化。
2.3 选择候选的稳定单元
在
l
l
l层,所有的单元
U
l
U^l
Ul包括三部分:
S
c
l
,
S
l
,
P
l
S^l_c,S^l,P^l
Scl,Sl,Pl,对应于候选稳定单元,稳定单元以及可塑性单元。在学习每个任务的时候,NISPA将一部分
P
l
P^l
Pl变为
S
c
l
S^l_c
Scl,在训练完所有的之后,将这些
S
c
l
S_c^l
Scl变为
S
c
S_c
Sc。
选择过程如下,首先计算整层的平均激活大小:
A
l
=
∑
x
∈
D
t
a
l
(
x
)
=
∑
x
∈
D
t
∑
i
=
1
N
l
a
n
i
l
(
x
)
A_l=\sum_{x \in D_t} a_l(x)=\sum_{x \in D_t} \sum_{i=1}^{N_l} a_{n_i^l}(x)
Al=x∈Dt∑al(x)=x∈Dt∑i=1∑Nlanil(x)
之后,根据如下条件进行选择:
min
S
c
l
⊆
P
l
∣
S
c
l
∣
subject to
∑
x
∈
D
t
∑
n
i
l
∈
S
c
l
∪
S
l
a
n
i
l
(
x
)
≥
τ
A
l
\min _{S_c^l \subseteq P^l}\left|S_c^l\right| \text { subject to } \sum_{x \in D_t} \sum_{n_i^l \in S_c^l \cup S^l} a_{n_i^l}(x) \geq \tau A_l
Scl⊆Plmin∣
∣Scl∣
∣ subject to x∈Dt∑nil∈Scl∪Sl∑anil(x)≥τAl
也就是在一层中,按照每个单元的激活程度进行排序,按照从大到小进行排序依次拿出,直到满足条件。
2.4 计算 τ \tau τ
可以发现,在一开始我们希望有更多的候选稳定单元,也就代表一开始
τ
\tau
τ要尽可能大,而到后面慢慢减少,这里直接给出作者的计算公式:
τ
p
=
1
2
(
1
+
cos
(
p
×
π
k
)
)
\tau_p=\frac{1}{2}\left(1+\cos \left(\frac{p \times \pi}{k}\right)\right)
τp=21(1+cos(kp×π))
其中
p
p
p表示训练的次数,
k
k
k为一个超参数一般在30到40之间。
(原论文3.5,3.6主要是介绍上述的合理性,大家可以去看看论文,这里简单说一下,也就是希望保留尽可能多的可塑的单元,因此每次选择最少的一部分形成候选单元)。
2.5 连接的重写
根据上述的发现,需要对单元中的连接进行修改:
- 首先,移除塑形单元到稳定单元之间的连接,保证稳定单元不受到塑形单元的改变而改变。也就是 n i l ∈ S l ∪ S c l n_i^l \in S^l \cup S_c^l nil∈Sl∪Scl and n j l − 1 ∈ P l − 1 n_j^{l-1} \in P^{l-1} njl−1∈Pl−1将会被删除。
- 从层 l l l删除一些连接后,在层 l l l中增加相同数量的新连接,以保持每层的密度。只要新连接不构成稳定单元的新输入,则随机选择新连接(例如: θ i , j l \theta_{i, j}^l θi,jl 被添加,其中 n i l ∈ P l n_i^l \in P^l nil∈Pl and n j l − 1 ∈ U l − 1 n_j^{l-1} \in U^{l-1} njl−1∈Ul−1)。
NISPA只会增加可塑单元之间的连接以及稳定单元到可塑单元之间的连接。
2.6 停止标准
阶段数不是固定的。相反,NISPA在验证数据集
V
t
V_t
Vt上跟踪迄今为止达到的最高精度。在每个阶段结束时,如果新精度低于最佳精度,我们将停止训练,并将模型恢复到前一阶段的末尾。换言之,我们在阶段级别执行早期停止。在训练中,可塑单元从上一个任务的训练开始就有偏差,这阻碍了学习新任务。因此,在开始新任务的训练之前,将会重新初始化所有非冻结连接的权重。
具体的算法如下:
三. 代码解析
代码链接点这里
首先我们看一下网络的构成:
可以发现其实就是用到了掩码
m
a
s
k
mask
mask来确保连接的修剪和添加。
整个训练过程如下,其中第一个if是进行恢复,第二个则是正常情况进行的修剪。
我们主要关注候选单元的选择和修剪连接,如下:
可以发现,首先先计算每一层的平均梯度,计算结果为存到:activation_before_drop,具体如下:
然后,根据每一层的平均进行候选单元的选择:
可以发现就是从最大的依次排序然后选择直到满足。
修剪的部分其实就是将相应的掩码变为0,而添加则改为1,这里代码比较长但逻辑很简单因此就不贴出来啦。