BERT的原理与应用

我们在第七章介绍了迁移学习与计算机视觉的故事,不过好故事并没有这么快结束。迁移学习一路前行,走进了自然语言处理的片场。迁移学习在自然语言处理(NLP)领域同样也是一种强大的技术。由这种技术训练出来的模型,我们称之为预训练模型。

预训练模型首先要针对数据丰富的任务进行预训练,然后再针对下游任务进行微调,以达到下游任务的最佳效果。迁移学习的有效性引起了理论和实践的多样性,人们通过迁移学习与自然语言处理两者相结合,高效地完成了各种NLP的实际任务。

8.1 自然语言处理预训练模型

使语言建模和其他学习问题变得困难的一个基本问题是维数的诅咒。在人们想要对许多离散的随机变量(例如句子中的单词或数据挖掘任务中的离散属性)之间的联合分布建模时,这一点尤其明显。

举个例子,假如我们有10000个单词的词汇表,我们要对它们进行离散表示,这样用one-hot 编码整个词汇表就需要10000*10000的矩阵,而one-hot编码矩阵存在很多“0”值,显然浪费了绝大部分的内存空间。为了解决维度诅咒带来的问题,人们开始使用低维度的向量空间来表示单词,从而减少运算资源的损耗,这也是预训练模型思想的开端。

8.1.1 Word2Vec

在4.7.2节的实验中,我们提及了Skip-gram模型,它就是Yoshua Bengio等人[1]提出的经典Word2Vec模型之一。Word2Vec模型对NLP任务的效果有显著的提升,并且能够利用更长的上下文。对于Word2Vec具体的原理与应用,笔者在4.7.2节已经进行了详细的讲解,而且本章的主角并不是它,所以笔者就不进行赘述了。

8.1.2 BERT

在2018年,什么震惊了NLP学术界?毫无疑问是Jacob Devlin等人[2]提出的预训练模型BERT(Bidirectional Encoder Representations from Transformers)。

BERT被设计为通过在所有层的双向上下文上共同进行条件化来预训练未标记文本的深层双向表示。我们可以在仅一个附加输出层的情况下对经过预训练的BERT模型进行微调,以创建适用于各种任务(例如问题解答和语言推断)的最新模型,进而减少了对NLP任务精心设计特定体系结构的需求。BERT是第一个基于微调的表示模型,可在一系列句子级和字符级任务上实现最先进的性能,优于许多特定于任务的体系结构。

通俗易懂来讲就是我们只需要把BERT当成一个深层次的Word2Vec预训练模型,对于一些特定的任务,我们只需要在BERT之后下接一些网络结构就可以出色地完成这些任务。

另外,2018年底提出的BERT推动了11项NLP任务的发展。BERT的结构是来自Transformers模型的Encoder,Transformers如图 8.1所示。我们从图X中可以看到Transformer的内部结构都是由Ashish Vaswani 等人[3]提出的Self-Attention Layer和Layer Normalization的堆叠而产生。

图 8.1 Transformers(左边为Encoder,右边为Decoder)

1. Self-Attention Layer原理

1) Self-Attention Layer的出现原因

为了解决RNN、LSTM等常用于处理序列化数据的网络结构无法在GPU中并行加速计算的问题。

2) Self-Attention Layer的输入

图8.2所示:将输入的Input转化成token embedding + segment embedding +position embedding。因为有时候训练样本是由两句话组成,因此“[CLS]”是用来分类输入的两句话是否有上下文关系,而“[SEP]”则是用以分开两句话的标志符。其中,因为这里的Input是英文单词,所以在灌入模型之前,需要用BERT源码的Tokenization工具对每一个单词进行分词,分词后的形式如图 8.2中Input的“Playing”转换成“Play”+“# #ing”,因为英文词汇表是通过词根与词缀的组合来新增单词语义的,所以我们选择用分词方法可以减少整体的词汇表长度。如果是中文字符的话,输入就不需要分词,整段话的每一个字用“空格”隔开即可。

值得注意的是,模型是无法处理文本字符的,所以不管是英文还是中文,我们都需要通过预训练模型BERT自带的字典vocab.txt将每一个字或者单词转换成字典索引(即id)输入。

(1) segment embedding的目的:有些任务是两句话一起放入输入X,而segment便是用来区分这两句话的。在Input那里就是用“[SEP]”作为标志符号。而“[CLS]”用来分类输入的两句话是否有上下文关系。

(2) position embedding的目的:因为我们的网络结构没有RNN 或者LSTM,因此我们无法得到序列的位置信息,所以需要构建一个position embedding。构建position embedding有两种方法:BERT是初始化一个position embedding,然后通过训练将其学出来;而Transformer是通过制定规则来构建一个position embedding:使用正弦函数,位置维度对应曲线,而且方便序列之间的选对位置,使用正弦会比余弦好的原因是可以在训练过程中,将原本序列外拓成比原来序列还要长的序列,如公式(8.1)~(8.2)所示。

图 8.2 Self-Attention的输入

首先,将 Q与K 矩阵乘积并scale(为了防止结果过大,除以他们维度的均方根),其次,将其灌入Softmax函数得到概率分布,最后再与V 矩阵相乘,得到self-attention的输出,如公式(8.3)所示。其中,(Q,K,V) 均来自同一输入X ,他们是 X分别乘上 WQ,WK,WV初始化权值矩阵所得,而后这三个权值矩阵会在训练的过程中确定下来,如图 8.3所示。

图 8.3初始化(Q,K,V)

通过Linear线性投影来初始化不同的(Q,K,V) ,将多个单头的结果融合会比单头Self-Attention的效果好。我们可以将初始化不同的(Q,K,V) 理解为单头从不同的方向去观察文本,这样使Self-Attention更加具有“大局观”。整体的运算逻辑就是Multi-Head Self-Attention将多个不同单头的Self-Attention输出Concat成一条,然后再经过一个全连接层降维输出,如图 8.4所示。

图 8.4 Multi-Head Self-Attention

(左边为单头Self-Attention运算逻辑,右边为多头Self-Attention运算逻辑)

2. Layer Normalization

Self-Attention的输出会经过Layer Normalization,为什么选择Layer Normalization而不是Batch Normalization?此时,我们应该先对我们的数据形状有个直观的认识,当一个batch的数据输入模型的时候,形状是长方体如图 8.5所示,大小为(batch_size, max_len, embedding),其中batch_size为batch的批数,max_len为每一批数据的序列最大长度,embedding则为每一个单词或者字的embedding维度大小。而Batch Normalization是对每个Batch的每一列做normalization,相当于是对batch里相同位置的字或者单词embedding做归一化,Layer Normalization是Batch的每一行做normalization,相当于是对每句话的embedding做归一化。显然,LN更加符合我们处理文本的直觉。

图 8.5 Layer Normalization与Batch Normalization

3. BERT预训练

图 8.6所示。

1) 预训练过程是生成BERT模型的过程

一般来说,个人用不着自己训练一个BERT预训练模型,都是直接调用模型的权重,进行fine-tune以适应当前特定任务,但我们可以了解一下BERT是怎么训练出来的。

2) 输入X

就是Self-Attention Layer的输入,利用字典将每一个字或者单词用数字表示,并转换成token embedding + segment embedding + position embedding。序列的长度一般有512 或者 1024,不足用“[PAD]”补充。句子开头第一个位置用“[CLS]”表示,如果是输入两句话,则用“[SEP]”隔开。

3) MaskLM策略

对于输入X,15%的字或者英文单词采用随机掩盖策略。对于这15%的字或者英文单词,80%的概率用“[mask]”替换序列中的某个字或者英文单词,10%的概率替换序列中的某个字或者英文单词,10%的概率不做任何变换。

4) 训练语料总量

330亿语料

5) 预训练

两种训练同时进行:

(1) 预测被掩盖的字或者英文单词(MaskLM)。

(2) 预测两句话之间是否有顺序关系(Next Sentence Prediction)。

这里需要补充说明的是NLP的预训练模型与计算机视觉的预训练模型有些许不同,NLP的预训练方式采用的是无监督学习,即我们不需要人工打标签,而计算机视觉需要则需要对图像进行人工分类。因为NLP的预训练正如笔者所说,只是预测被掩盖的单词或者字,以及判断是两段话是否有顺序关系,这些只需要写个小程序就可以轻松得到相应的标签,无需人工进行大量的标记。

6) BERT模型权重

最后经过大量语料的无监督学习,我们得到了BERT预训练模型,BERT自带字典vocab.txt的每一个字或者单词都被768维度的embedding(即权重)所表示。当我们需要完成特定任务时,若对它们的embedding进行微调(即fine-tune),还能更好的适应任务。

8.6 预训练与Fine-Tune过程

4. BERT的 fine-tune过程

图 8.6所示。

可以选择是否fine-tune(微调),如果不选择fine-tune,那就是简单地使用BERT的权重,把它完全当成文本特征提取器使用;若使用fine-tune,则相当于在训练过程中微调BERT的权重,以适应我们当前的任务。

文章提及到如果选择下面这几个参数进行fine-tune调参,任务的完成度会比较好。

1) Batch Size:16 or 32;

2) Learning Rate: 5e-5, 3e-5, 2e-5;

3) Epochs:2, 3, 4;

参考文献

[1] Bengio Y, Ducharme R, Vincent P, et al. A neural probabilistic language model[J]. Journal of machine learning research, 2003, 3(Feb): 1137-1155.

[2] Devlin J, Chang M-W, Lee K, et al. Bert: Pre-training of deep bidirectional transformers for language understanding[J]. arXiv preprint arXiv:1810.04805, 2018.

[3] Vaswani A, Shazeer N, Parmar N, et al. Attention is all you need[C]. Advances in neural information processing systems, 2017: 5998-6008.

下一期,我们将继续讲授其他预训练模型

敬请期待~

关注我的微信公众号~不定期更新相关专业知识~

内容 |阿力阿哩哩 

编辑 | 阿璃 

点个“在看”,作者高产似那啥~

发布了76 篇原创文章 · 获赞 5 · 访问量 6250

猜你喜欢

转载自blog.csdn.net/Chile_Wang/article/details/103884365