深度学习笔记之BERT------BERT精简变体:ALBERT
- 引言
-
- 回顾:ResNet对于反向传播的作用
- BERT的配置
- BERT的问题/缺陷
- ALBERT
- ALBERT的策略
- [BERT VS ALBERT](#BERT VS ALBERT)
引言
上一节从 Word2vec \text{Word2vec} Word2vec上下文信息的局限性角度出发,介绍了 BERT \text{BERT} BERT是如何优化这一问题的,以及 BERT \text{BERT} BERT的训练策略。本节将介绍 BERT \text{BERT} BERT的一种精简变体 : ALBERT \text{ALBERT} ALBERT。
回顾:ResNet对于反向传播的作用
在ResNet \text{ResNet} ResNet一节中,介绍了残差连接这一技巧的优势。其前馈计算过程可描述为:
x ′ = H ( x ) = F ( x ) + x x' = \mathcal H(x) = \mathcal F(x) + x x′=H(x)=F(x)+x
其中, x x x表示上一网络层模块的输出; F ( ⋅ ) \mathcal F(\cdot) F(⋅)即表示下一网络层模块。这种使用于网络层模块之间的技巧本质上解决一个核心问题:抑制梯度消失现象,使梯度信息在深度神经网络中能够传播得更远。
在常规 的深度神经网络中,不可避免的问题是反向传播过程中,随着神经网络层的加深产生的梯度消失现象。在反向传播的初期,梯度结果是清晰、明显的,例如初始梯度: ∂ L ∂ W N \begin{aligned}\frac{\partial \mathcal L}{\partial \mathcal W_{N}}\end{aligned} ∂WN∂L(这里 W N \mathcal W_{N} WN表示损失函数前的最后一个神经网络层的权重信息 );随着反向传播的加深,梯度消失的现象逐渐明显,模型传播的梯度会变得模糊、轻微:
∂ L ∂ W N ⋅ ∂ W N ∂ W N − 1 ⋅ ∂ W N − 1 ∂ W N − 2 ⋯ ∂ W 1 ∂ W 0 \frac{\partial \mathcal L}{\partial \mathcal W_{N}} \cdot \frac{\partial \mathcal W_{N}}{\partial \mathcal W_{N-1}} \cdot \frac{\partial W_{N-1}}{\partial W_{N-2}} \cdots \frac{\partial \mathcal W1}{\partial \mathcal W_0} ∂WN∂L⋅∂WN−1∂WN⋅∂WN−2∂WN−1⋯∂W0∂W1
而 ResNet \text{ResNet} ResNet使用一个技巧解决了 2 2 2件事情:
无论神经网络层数有多深,总会存在保底的梯度稳定传递回上一层;以一个常规网络层 x ′ = F [ G ( x ) ] x' = \mathcal F[\mathcal G(x)] x′=F[G(x)]与对应残差网络层 x ′ = F [ G ( x ) ] + G ( x ) x' = \mathcal F[\mathcal G(x)] + \mathcal G(x) x′=F[G(x)]+G(x)之间结果对比如以下:
这里
σ \sigma σ表示激活函数。
{ Normal: ∂ x ′ ∂ x = ∂ F [ G ( x ) ] ∂ G ( x ) ⋅ ∂ G ( x ) ∂ x = { σ ′ [ W T G ( x ) + b ] ⋅ W } ⋅ ∂ G ( x ) ∂ x ResNet: ∂ x ′ ∂ x = ∂ { F [ G ( x ) ] + G ( x ) } ∂ G ( x ) ⋅ ∂ G ( x ) ∂ x = { 1 + σ ′ [ W T G ( x ) + b ] ⋅ W } ⋅ ∂ G ( x ) ∂ x \begin{cases} \begin{aligned} & \text{Normal: }\frac{\partial x'}{\partial x} = \frac{\partial \mathcal F[\mathcal G(x)]}{\partial \mathcal G(x)} \cdot \frac{\partial \mathcal G(x)}{\partial x} = \left\{\sigma' \left[\mathcal W^T\mathcal G(x) + b \right] \cdot \mathcal W\right\} \cdot \frac{\partial \mathcal G(x)}{\partial x} \\ \quad \\ & \text{ResNet: } \frac{\partial x'}{\partial x} = \frac{\partial \{ \mathcal F[\mathcal G(x)] + \mathcal G(x)\}}{\partial \mathcal G(x)} \cdot \frac{\partial \mathcal G(x)}{\partial x} = \left\{1 + \sigma' \left[\mathcal W^T\mathcal G(x) + b \right] \cdot \mathcal W \right\} \cdot \frac{\partial \mathcal G(x)}{\partial x} \end{aligned} \end{cases} ⎩ ⎨ ⎧Normal: ∂x∂x′=∂G(x)∂F[G(x)]⋅∂x∂G(x)={σ′[WTG(x)+b]⋅W}⋅∂x∂G(x)ResNet: ∂x∂x′=∂G(x)∂{F[G(x)]+G(x)}⋅∂x∂G(x)={1+σ′[WTG(x)+b]⋅W}⋅∂x∂G(x)
在这种梯度传递方式下,使其保证:残差网络在方向传播过程中传播的残差梯度是有效的,而不同于常规神经网络中,随着反向传播层数的加深,传回的梯度信息忽略不计或者传回一些接近噪声的信息。从而最终呈现出类似互补的现象:
- 在接近输出层的部分,经过深度神经网络若干次的前馈计算,它包含的初始信息是最少的 ;相反,其对应反向传播是最初始的部分,因而它的梯度是最活跃的 ,最终导致:当前层梯度中梯度信息自身占主导地位。
- 在接近输入层的部分,经过多次反向传播计算,虽然使用 ResNet \text{ResNet} ResNet抑制了梯度衰减,但梯度信息在一次又一次反向传播计算中被稀释了,但这部分同样是初始信息参与最多的部分。从而导致:当前层梯度中初始信息占主导地位。
BERT的配置
BERT \text{BERT} BERT的研究人员在发布该模型时提出了两种标准配置:
BERT-base \text{BERT-base} BERT-base
BERT-base \text{BERT-base} BERT-base对应的编码器层数 L = 12 \mathcal L = 12 L=12,每层编码器使用的注意力头的个数 A = 12 \mathcal A = 12 A=12,输入特征向量的维度 H = 768 \mathcal H = 768 H=768,如果词表 token \text{token} token的大小是 30 , 000 30,000 30,000,那么 BERT-base \text{BERT-base} BERT-base中包含的参数量大小是:
-
模型初始是一个 Embedding \text{Embedding} Embedding层,需要将 Token \text{Token} Token映射成相应维度为 H \mathcal H H的 Embedding \text{Embedding} Embedding向量。该层对应的权重的参数量大小是: 30 , 000 ∗ H 30,000 * \mathcal H 30,000∗H。
-
在自注意力机制中, Q , K , V \mathcal Q,\mathcal K,\mathcal V Q,K,V映射层对应的权重矩阵 W Q , W K , W V \mathcal W_{\mathcal Q},\mathcal W_{\mathcal K},\mathcal W_{\mathcal V} WQ,WK,WV的大小均为 ( 768 , 64 ) (768,64) (768,64),那么 12 12 12个头对应的每个权重维度大小为 ( 768 , 12 ∗ 64 ) (768,12*64) (768,12∗64),对应参数数量为 H ∗ H \mathcal H *\mathcal H H∗H;最终多头注意力机制中的参数量为 3 ∗ H ∗ H 3 * \mathcal H * \mathcal H 3∗H∗H;
自注意力机制的末尾还包含一个维度不发生变化 的全链接层 Linear ( H , H ) \text{Linear}(\mathcal H,\mathcal H) Linear(H,H),该层权重对应的参数量大小是 H ∗ H \mathcal H * \mathcal H H∗H,最终自注意力机制对应的总参数量为 H 2 ∗ 4 \mathcal H^2 * 4 H2∗4。
-
编码器自注意力机制后是一个 FeedForword Network \text{FeedForword Network} FeedForword Network,由一对全连接层组成: Linear ( H , 4 ∗ H ) , Linear ( 4 ∗ H , H ) \text{Linear}(\mathcal H,4 * \mathcal H),\text{Linear}(4 * \mathcal H,\mathcal H) Linear(H,4∗H),Linear(4∗H,H),两个层权重的参数量大小均为 H 2 ∗ 4 \mathcal H^2 * 4 H2∗4,最终该部分的参数量大小为 H 2 ∗ 8 \mathcal H^2 * 8 H2∗8。
至此, BERT-base \text{BERT-base} BERT-base的参数量为:
L \mathcal L L个编码器均包含同样的结构。
I = 30 , 000 ∗ H + L ∗ ( H 2 ∗ 4 + H 2 ∗ 8 ) = 107 , 974 , 656 ≈ 110 M \mathcal I = 30,000 * \mathcal H + \mathcal L * (\mathcal H^2 *4 + \mathcal H^2 * 8) =107,974,656 \approx 110M I=30,000∗H+L∗(H2∗4+H2∗8)=107,974,656≈110M
可以看出, BERT-base \text{BERT-base} BERT-base中大约包含 1.1 1.1 1.1亿参数。
BERT-large \text{BERT-large} BERT-large
BERT-large \text{BERT-large} BERT-large结构和 BERT-base \text{BERT-base} BERT-base相同,只不过参数规格有所变化。其编码器层数 L = 24 \mathcal L = 24 L=24,自注意力头数量 A = 16 \mathcal A = 16 A=16,输入特征向量维度 H = 1024 \mathcal H = 1024 H=1024。至此, BERT-large \text{BERT-large} BERT-large的参数量为:
W Q , W K , W V \mathcal W_{\mathcal Q},\mathcal W_{\mathcal K},\mathcal W_{\mathcal V} WQ,WK,WV的大小依然是
( H , 64 ) (\mathcal H,64) (H,64)。
I = 332 , 709 , 888 ≈ 340 M \mathcal I = 332,709,888 \approx 340M I=332,709,888≈340M
相应地, BERT-large \text{BERT-large} BERT-large中大约包含 3.4 3.4 3.4亿参数。
BERT的问题/缺陷
-
无论是 BERT-base \text{BERT-base} BERT-base还是 BERT-large \text{BERT-large} BERT-large,这中规模的参数量,这使它极难训练。诚然对 Token \text{Token} Token进行更好的表示,但该模型对计算资源也有更高的要求。
-
模型退化:在 NLP \text{NLP} NLP领域的研究趋势------规模越大、参数量越多,模型的表征就越完整,模型性能越高。但实际上, ALBERT \text{ALBERT} ALBERT的研发团队研究表明,这种逻辑并不完全正确。
他们将 BERT-large \text{BERT-large} BERT-large中的输入特征以及隐藏层单元数量 H = 1024 → 2048 \mathcal H = 1024 \rightarrow 2048 H=1024→2048,并称之为 BERT-xlarge \text{BERT-xlarge} BERT-xlarge,但该模型无论在语言建模任务还是阅读理解测试 ( RACE ) (\text{RACE}) (RACE)中,该模型的表现明显不如 BERT-large \text{BERT-large} BERT-large,在 RACE \text{RACE} RACE任务中的准确率呈现断崖式下跌 ( Acc:73.9 \text{Acc:73.9} Acc:73.9% → 54.3 \rightarrow \text{54.3} →54.3%)
下面是原文中 BERT-large \text{BERT-large} BERT-large与 BERT-xlarge \text{BERT-xlarge} BERT-xlarge随着迭代步骤的增加,损失函数 和准确率 的变化情况:
从第一张图(左)可以看出: BERT-large \text{BERT-large} BERT-large相比于 BERT-xlarge \text{BERT-xlarge} BERT-xlarge更快地达到下降效果,并趋于稳定;相比之下, BERT-xlarge \text{BERT-xlarge} BERT-xlarge损失函数的波动更剧烈。第二张图(右)可以看出: BERT-large \text{BERT-large} BERT-large相比于 BERT-xlarge \text{BERT-xlarge} BERT-xlarge在初始有限的迭代步骤内,准确率提升的更快,最终准确率也高于 BERT-xlarge \text{BERT-xlarge} BERT-xlarge。
很明显,规模越大,模型性能越高被局限在模型没有退化的前提下,为什么会出现模型退化 这种现象呢 ? ? ? 个人认为,在模型未退化 的范畴内,参数量大优于参数量小是因为:在模型中各神经元被充分激活的条件下,反向传播过程中,更多的神经元能够传回更多、更丰富的梯度信息;
如果不限制 地对模型参数进行扩张,模型中神经元数量越来越多。由于数据体量不变,会导致:反向传播过程中,绝大多数神经元没有被充分激活,这种半激活状态下的模型效果自然会大打折扣。
ALBERT
BERT \text{BERT} BERT的缺陷,就是参数量过大,导致训练难以及潜在出现的神经元/参数冗余现象 ,针对这个问题, ALBERT \text{ALBERT} ALBERT通过两种技巧对参数量进行优化:
-
Embedding \text{Embedding} Embedding层参数的因子分解( Factorized Embedding Parameterization \text{Factorized Embedding Parameterization} Factorized Embedding Parameterization): BERT \text{BERT} BERT系列模型,它的 Embedding \text{Embedding} Embedding直接作为后续自注意力 层的输入, W Q , W K , W V \mathcal W_{\mathcal Q},\mathcal W_{\mathcal K},\mathcal W_{\mathcal V} WQ,WK,WV直接与 Embedding \text{Embedding} Embedding进行计算;但如果想要提高隐藏层的维度 H \mathcal H H,那我们不得不一并提高 Embedding \text{Embedding} Embedding的维度 E \mathcal E E并使 E = H \mathcal E = \mathcal H E=H,再进行计算时,参数的增长会是一个平方级的增加。
参数量级表示为
O ( V ∗ H ) \mathcal O(\mathcal V * \mathcal H) O(V∗H),其中
V \mathcal V V表示
Token \text{Token} Token的数量,也就是词汇表词语的数量;
H \mathcal H H则表示神经元维数,再没有因子分解的情况下,将所有的
Token \text{Token} Token转化为相应的
Embedding \text{Embedding} Embedding需要的参数量。
而因子分解的思路是: Embedding \text{Embedding} Embedding维度 E \mathcal E E与 H \mathcal H H不相关。具体做法是:在 Embedding \text{Embedding} Embedding后面额外增加一个参数矩阵 W ∈ R E ∗ H \mathcal W \in \mathbb R^{\mathcal E * \mathcal H} W∈RE∗H对 Embedding \text{Embedding} Embedding进行维度变换。此时就可以赋予 E \mathcal E E一个较小的值 来约束参数数量,最终参数量级表示为 O ( V ∗ E + E ∗ H ) \mathcal O(\mathcal V * \mathcal E + \mathcal E * \mathcal H) O(V∗E+E∗H)。
下图表示当
V = 30000 , E = 128 , H = 768 \mathcal V=30000,\mathcal E=128,\mathcal H=768 V=30000,E=128,H=768时,对应参数数量的对比结果
原文提供的基于 Embedding \text{Embedding} Embedding因子分解对于各类任务效果表示如下:
通过观察可以发现:在未执行参数共享的状态下,使用 Embedding \text{Embedding} Embedding因子分解技巧,各任务准确率随着 Embedding \text{Embedding} Embedding维数的增加而增加,但相差普遍不大,并且参数量最多相差近 30 30 30%。也就是说:削掉 30 30 30%参数,同样可以得到与原来相差不大的效果。
-
跨层参数共享( Cross-Layer Parameter Sharing \text{Cross-Layer Parameter Sharing} Cross-Layer Parameter Sharing):无论是 BERT \text{BERT} BERT还是 Transformer \text{Transformer} Transformer,各个 Transformer block \text{Transformer block} Transformer block内的参数,包括 self-attention \text{self-attention} self-attention、全连接部分,均是相互独立 的,这导致:每增加一个 Block \text{Block} Block,参数量都会上升, ALBERT \text{ALBERT} ALBERT则尝试:只学习第一层参数,剩下的所有层的参数重新使用第一层参数,最终待学习的参数仅变成了一层参数 。
这里的层并非仅仅指一个
Block \text{Block} Block,可以将所有的
self-attention \text{self-attention} self-attention进行共享,或者所有的
全连接部分进行共享,或者所有的
Block \text{Block} Block进行共享
浅谈一下为什么要用第一层参数 :由于存在 ResNet \text{ResNet} ResNet结构,会导致:每一层的传回梯度都是残差梯度 ,差异在于:初始层中梯度信息不占主要部分,但该梯度信息同样有效,只有选择第一层,才能够对初始信息进行更好地优化。
下面是原文中对 BERT-large \text{BERT-large} BERT-large和 ALBERT-large \text{ALBERT-large} ALBERT-large相比,使用欧式距离和余弦相似度 作为标准,各层输入输出分布稳定性的一个对比情况:
左图 描述的是各层输入输出分布之间的欧氏距离,以及欧式距离随着层级变化的一个变化趋势;右图 描述的是各层输入输出分布之间的余弦相似度,以及相似度随着层级的一个变化趋势。两者本质上均是描述各层输入输出分布之间的差异性趋势。蓝色线的 ALBERT-large \text{ALBERT-large} ALBERT-large所描述的线更加平滑,这意味着:各层输入输出的分布相差不大,并且各层之间的输入输出分布相差都不大;相反,红色线描述的 BERT-large \text{BERT-large} BERT-large,其在接近末尾时变动变化很大,这意味着对应层的输入输出分布之间差异更大。这也说明跨层参数共享对于网络参数的稳定性有积极的影响。
另一角度观察, BERT-large \text{BERT-large} BERT-large的差异性更大意味着差异性大的若干层对输出分布起更关键作用,而 ALBERT-large \text{ALBERT-large} ALBERT-large相邻层的差异性普遍相差不大,可以解释为:产生输出分布结果的"关键点"分摊给了每一层,并共同发生作用。这也说明 BERT-large \text{BERT-large} BERT-large和 ALBERT-large \text{ALBERT-large} ALBERT-large对应参数找到的解分布存在差异。
由于跨层参数共享的方式有很多种,原文将:
- 无共享 ( not-shared ) (\text{not-shared}) (not-shared)
- 基于 Block ( \text{Block}( Block( attention \text{attention} attention,全连接 ) ) )跨层参数共享 ( all-shared ) (\text{all-shared}) (all-shared)
- 基于自注意力跨层参数共享 ( shared-attention ) (\text{shared-attention}) (shared-attention)
- 基于全连接跨层参数共享 ( shared-FFN ) (\text{shared-FFN}) (shared-FFN)
4 4 4种跨层参数共享方式进行比对,比对结果如下:
从表中可以看出:
- 在隐藏层单元格式均使用 768 768 768的条件下,可以使用精度换时间的方式进行高效运算。例如 ALBERT-base(shared-attention,E=128) \text{ALBERT-base(shared-attention,E=128)} ALBERT-base(shared-attention,E=128)相比 ALBERT-base(not-shared,E=768) \text{ALBERT-base(not-shared,E=768)} ALBERT-base(not-shared,E=768)仅差不到一个点,但能节省约 40 40 40%的计算资源;
实际上
ALBERT-base(not-shared,E=768) \text{ALBERT-base(not-shared,E=768)} ALBERT-base(not-shared,E=768)比
BERT-base \text{BERT-base} BERT-base还多了
768 ∗ 768 768*768 768∗768个参数~
- 相比于 shared-attention \text{shared-attention} shared-attention, Feed-Forward \text{Feed-Forward} Feed-Forward层的参数共享会对最终精度产生更大的负面影响。
-
Dropout \text{Dropout} Dropout移除
ALBERT \text{ALBERT} ALBERT作者在实验过程中发现的奇特现象,即便训练了 1 , 000 , 000 1,000,000 1,000,000个 step \text{step} step,依然没有产生类似过拟合 的现象,并在后续通过移除 Dropout \text{Dropout} Dropout来提升模型能力。右图描述了在 1.2M \text{1.2M} 1.2M左右个 step \text{step} step之后,移除 Dropout \text{Dropout} Dropout对 Mask LM \text{Mask LM} Mask LM准确率的提升效果:
ALBERT的策略
在介绍BERT \text{BERT} BERT策略中提到一个下句预测 ( Next Sentence Prediction,NSP ) (\text{Next Sentence Prediction,NSP}) (Next Sentence Prediction,NSP),但在随后的实践中, RoBERTa,XLNet \text{RoBERTa,XLNet} RoBERTa,XLNet等论文已经阐明了该任务并没有给模型的训练带来收益。因此, ALBERT \text{ALBERT} ALBERT提出了另一个任务------句子顺序预测 ( Sentence-order Prediction,SOP ) (\text{Sentence-order Prediction,SOP}) (Sentence-order Prediction,SOP)。具体采样方式是:
- 从文档中选取两个连续句子作为一个正样本;
- 将上述两个句子调换顺序 ,并作为一个负样本
这里区别于
BERT \text{BERT} BERT,NSP是随机选取两个句子作为负样本,并判别他们的关联关系
基于这种方式的二分类任务提高了多种下游任务的表现:
BERT VS ALBERT
类似于 BERT-xlarge \text{BERT-xlarge} BERT-xlarge, ALBERT \text{ALBERT} ALBERT也有自己的 large \text{large} large版本,并与 BERT \text{BERT} BERT相关模型进行对比:
可以发现: ALBERT-xxlarge \text{ALBERT-xxlarge} ALBERT-xxlarge参数量少于 BERT-large \text{BERT-large} BERT-large情况下,各项指标均优于 BERT-large \text{BERT-large} BERT-large。从训练实践的角度观察:
可以发现: ALBERT-xxlarge \text{ALBERT-xxlarge} ALBERT-xxlarge使用更少的迭代步骤、更短的时间,能够得到优于 BERT-large \text{BERT-large} BERT-large的结果。需要注意的是,这仅仅是训练时间,而不是 Inference \text{Inference} Inference时间,也就是说:在前馈计算的时候实现网络共享,但在反向传播过程中,依然需要一个一个 Block \text{Block} Block将梯度传递回去。
Reference \text{Reference} Reference:
ALBERT详解