1、作者动机
动机就是原始的BERT模型太大,训练时间太久。作者希望能够将原始的bert模型轻量化。
在BERT模型出来后,很多人也意识到这个问题,提出了各种各样的解决方案。对于BERT模型训练速度的问题有的方案是使用分布式训练,但是分布式训练有个问题:在分布式训练中,训练速度也会受到很大的影响,因为通信开销与模型中参数的数量成正比。当然了,还有人使用蒸馏技术来缩小原始BERT模型的大小,这样做常常就是模型的性能有所下降,但模型仍然不小。
对于内存限制(就是GPU的内存是有限的)的问题,有人提出一个内存管理方法,但是仍然没有解决训练时候的通信开销。
前面说的这些就是ALBERT的作者要解决的问题。ALBERT采用了两种参数简化技术,消除了预训练模型缩放的主要障碍(通信开销和内存限制)。
第一种技术:矩阵分解。通过将大的词汇嵌入矩阵(就是BERT的输入嵌入)分解为两个小的矩阵,将隐含层的大小与输入嵌入的大小分离。这种分离使得在不显著增加词汇表嵌入参数大小的情况下更容易增加隐含层的大小。
第二种技术:跨层参数共享。这种技术避免模型层数的增加而导致参数数量的增加。
当然了,模型参数的减少会导致模型性能的下降,作者为了解决这个问题呢,引入了自监督学习的损失用于句子词序预测(sentence-order prediction, SOP)。
2、模型具体细节
2.1、模型的结构
ALBERT模型的架构和原始的BERT模型差不多,仍然使用Transformer模型。
在讨论细节之前,先对一些能够用到的符号做一些说明:
- E E E: 词汇嵌入的大小。
- L L L: 编码层的数量。
- H H H: 隐层大小。
2.2、分解嵌入参数
在BERT模型中,词嵌入的大小
E
E
E和隐层的大小
L
L
L是相等的。作者从两个角度来阐述BERT这样做的弊端。
建模角度。词汇嵌入主要是学习上下文无关表示,而隐层的嵌入主要是学习上下文相关的表示。有实验表明,BERT强大的原因是隐层习得的上下文相关表示,因此作者就想将词汇嵌入和隐层嵌入分解开来,这样就可以
实践角度。一般情况下,自然语言处理中的词汇表的大小是很庞大的,如预训练的中文BERT的词汇表大小就有1万多。如果
E
=
L
E=L
E=L,增大
H
H
H就会增大
E
E
E的大小。如果词汇表的大小是
V
V
V,那么参数就是
V
×
E
V \times E
V×E。这很容易得到一个包含数十亿个参数的模型,其中大多数参数只在训练期间进行少量的更新。所以作者使用因数分解的嵌入参数,把它们分解成两个更小的矩阵。
作者没有将one-hot向量直接投影到大小为
H
H
H的隐藏空间,而是首先将它们投影到大小为
E
E
E的低维嵌入空间,然后再投影到隐藏空间。通过这种分解,就将嵌入参数从
O
(
V
×
H
)
O(V \times H)
O(V×H)减小到
O
(
V
×
E
+
E
×
H
)
O(V \times E + E \times H)
O(V×E+E×H)。当
H
≫
E
H \gg E
H≫E时,效果会很明显。
举个例子,在BERT中,输入嵌入的大小是
V
×
H
V \times H
V×H;在ALBERT中,我们需要指定一个参数:embedding_width=
E
E
E,如果我们指定的这个参数等于
H
H
H,那么此时的ALBERT就是一个参数共享的BERT模型。我们在指定这个参数的时候往往要远小于
H
H
H。
2.2、跨层参数共享
整个BERT里面可以看作只有两个组件:注意力层和全连接层。跨层参数共享有两种方式:1.跨注意力层参数共享。2.跨全连接层参数共享。在ALBERT中,作者两个参数共享方式都使用。
当然,你可以根据你自己的任务来合理的设置层之间的参数共享机制。