BERT模型总结

BERT模型总结

前言

​ BERT是在Google论文《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》中被提出的,是一个面向NLP的无监督预训练模型,并在多达11个任务上取得了优秀的结果。这个模型的最大意义是使得NLP任务可以向CV一样使用与训练模型,这极大的方便了一个新的任务开始,因为在NLP领域,海量数据的获取还是有难度的。

模型概述:BERT是一个无监督的NLP与训练模型,结构上是Transformer的编码部分,每个block主要由多头self-Attention、标准化(Norm)、残差连接、Feed Fordawrd组成。在具体任务中,主要分为模型预训练和模型微调两个阶段。在模型预训练阶段,因为模型参数巨大,通常是上千万乃至上亿的数量级,所以需要大量的数据训练,所幸这时候模型是无监督的,只需要爬取或使用开源数据集即可;在模型微调阶段,需要针对具体的任务来微调模型,已达到较好的效果。

1. 模型整体结构

​ Bert就是Transformer的编码部分,下图是Transformer的具体结构:

​ 上图左侧为Transformer的编码部分,右侧为Transformer的解码部分,本文主要以编码部分详细讲解Bert的结构。左侧的编码部分包括输入,添加位置编码,以self-Attention、Add&Norm、Feed Fordward的block。下面就每个具体细节进行具体分析。

2. 位置编码

​ 位置编码是用来捕获文本之间的时序关联性的,例如打开现在热度第一的新闻的第一句话:“重庆主城区一栋30层的居民楼发生大火,造成百余名群众被困,重庆市政府迅速调集消防、公安、卫生等数百名人员赶赴现场施救。”其中,“重庆市”与“主城区”相关度最高,位置最近。当对NLP文本处理时,位置更近的文本一般相关性更大,所以将位置编码融入到数据中是很有必要的。需要要说明的是与Bert这种全部基于Attention不同的是,之前基于RNN的模型在模型结构上已经可以将这种时序信息考虑在内。

​ 在具体处理方式上,采用的是Embedding+Positional的方法,将数据之间的关联性融入到数据中。Embedding是嵌入到相应维度的文本数据,Positional在论文中使用了\(sine\)\(cosine\)函数的线性变换来提供模型的位置信息,公式如下:

\[PE_{(pos,2i)}=sin(pos/10000^{2i/d_{model}})\\PE_{(pos,2i+1)}=cos(pos/10000^{2i/d_{model}}) \tag{1} \]

​ 那为何加了位置编码就能获取数据间位置的特征呢?在self-attention的结构中,在对每维数据计算权重时,是采用点积的形式,本质上就是计算向量之间的相关性。而位置编码将临近的数据加上频率接近的位置编码,就是增加了相邻数据的相关性。下图是位置编码向量的热图,可以看出距离越近,频率就更加接近。

img

3. self-Attention

self-attention是BERT的重要思想,其与位置编码结合,解决了文本数据的时序相关性的问题,从而一举结束了依靠RNN、LSTM、GRU等之前一直用来解决时序问题的网络模型。self-attention通俗的说就是信息向前传播时动态的计算权重的一种方式,与CNN常见的MaxPooling、MeanPooling不同的是,attention模型是经过训练,当不同信息传入时,自动的调整权重的一种结构。self-attention的具体结构如下图所示:

具体的,将上图的过程进行详细的解释,主要是拆分成4个步骤:

​ 1)\(x^1, x^2, x^3, x^4\)代表的是经过embedding的4条时序文本信息,首先将4条信息加上位置向量,得到\(a^1, a^2,a^3, a^4\),这样做的目的上文已经说过,是为了获取文本的时序相关性。

​ 2) 对每条信息分配三个权重\(W_Q, W_K, W_V (embed.dim*embed.dim)\),分别与\(a^1, a^2, a^3, a^4\)相乘后形成3个矩阵\(Q, K, V\)也就是上图的\(q^i, k^i, v^i\)

\[Q = Linear(a^1) = a^iW^Q\\ K = Linear(a^1) = a^iW^K \\ V = Linear(a^1) = a^iW^V \]

​ 3) 将\(q_1\)分别与\(k^1, k^2, ...,k^i\)点乘,得到\(\alpha_{1, i}\),再有softmax的计算公式,计算得\(\hat\alpha_{1, i}\)

\[\alpha_{1, i} = q^1*k^i\\ \hat\alpha_{1, i} = exp(\alpha_{1, i})/\sum_j{exp(\alpha_{1, j})} \]

​ 4)最后按照softmax输出的权重对\(V\)进行加权,计算得\(b^1\)。使用同样的方法计算得\(b^2, b^3, ...,b^i\)。将\(b^1, b^2, b^3, ...,b^i\)进行合并,完成self-attention

\[b^1 = \sum_i\hat{\hat\alpha_{1, i}*v^i} \]

4. 残差连接

​ 残差连接是训练深层模型时惯用的方法,主要是为了避免模型较深时,在进行反向传播时,梯度消失等问题。具体实现时,当网络进行前向传播时,不仅仅时按照网络层数进行逐层传播,还会由当前层隔一层或多层向前传播,如下图所示:

5. 模型实现

​ 以上是BERT的整体结构,Input输入的是文本数据,经过Embedding加上位置向量Positional Encoding。Multi-Head Atention为多头的self-Attention,实际上就是将self-attention的Q、K、V均分成n份,分别进行计算。Add&Norm为残差计算和标准化;Feedward为全连接层,进行前向传播。其中\(N_x\)为基本单元的个数,是可以条调整的超参数。

6. Bert模型预训练策略

​ 在预训练Bert模型时,论文提供了两种策略:

(1) Masked LM

​ 在BERT中, Masked LM(Masked language Model)构建了语言模型, 这也是BERT的预训练中任务之一, 简单来说, 就是随机遮盖或替换一句话里面任意字或词, 然后让模型通过上下文的理解预测那一个被遮盖或替换的部分, 之后的时候只计算被遮盖部分的, 其实是一个很容易理解的任务, 实际操作方式如下:

  1. 随机把一句话中$15 % token$替换成以下内容:
    1. 这些$80 % [mask]$;
    2. 的几率被替换成任意一个其他的;
    3. 的几率原封不动.
  2. 之后让模型预测和还原被遮盖掉或替换掉的部分, 模型最终输出的隐藏层的计算结果的维度是:

    我们初始化一个映射层的权重:

    我们用完成隐藏维度到字向量数量的映射, 只要求的矩阵乘(点积):
    $X_{hidden}W_{vocab}: [batch_size, \ seq_len, \ vocab_size] vocab_sizesoftmaxvocab_size$的和为, 我们就可以通过里概率最大的字来得到模型的预测结果, 就可以和我们准备好的做损失()并反传梯度了.
    注意做损失的时候, 只计算在第1步里当句中随机遮盖或替换的部分, 其余部分不做损失, 对于其他部分, 模型输出什么东西, 我们不在意.

(2) Next Sentence Predict(NSP)

  1. 首先我们拿到属于上下文的一对句子, 也就是两个句子, 之后我们要在这两段连续的句子里面加一些特殊:\([cls]\)上一句话,\([sep]\)下一句话\([sep]\)
    也就是在句子开头加一个, 在两句话之中和句末加, 具体地就像下图一样:

img

  1. 我们看到上图中两句话是 my dog is cute he likes playing , 我的狗很可爱他喜欢玩耍, 除此之外, 我们还要准备同样格式的两句话, 但他们不属于上下文关系的情况;
    我的狗很可爱企鹅不擅长飞行, 可见这属于上下句不属于上下文关系的情况;
    在实际的训练中, 我们让上面两种情况出现的比例为, 也就是一半的时间输出的文本属于上下文关系, 一半时间不是.
  2. 我们进行完上述步骤之后, 还要随机初始化一个可训练的, 见上图中, 作用就是用的信息让模型分开上下句, 我们一把给上句全, 下句啊全, 让模型得以判断上下句的起止位置, 例如:
    我的狗很可爱企鹅不擅长飞行
    $0 \quad  \  0 \ \ 0 \ \  0 \ \ 0 \ \ 0 \ \ 0 \ \  0 \ \ \ 1 \ \  1 \ \ 1 \ \ 1 \ \ 1 \ \ 1 \ \ 1 \ \ 1 $
    上面就是.
  3. 还记得我们上节课说过的, 注意力机制就是, 让每句话中的每一个字对应的那一条向量里, 都融入这句话所有字的信息, 那么我们在最终隐藏层的计算结果里, 只要取出所对应的一条向量, 里面就含有整个句子的信息, 因为我们期望这个句子里面所有信息都会往所对应的一条向量里汇总:
    模型最终输出的隐藏层的计算结果的维度是:
    我们
    我们要取出所对应的一条向量, 对应着维度的第条:


    之后我们再初始化一个权重, 完成从维度到的映射, 也就是逻辑回归, 之后用函数激活, 就得到了而分类问题的推断.
    我们用来表示模型的输出的推断, 他的值介于之间:
    \(\hat{y} = sigmoid(Linear(cls\_vector)) \quad \hat{y} \in (0, \ 1)\)

参考内容:

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

[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] https://github.com/aespresso/a_journey_into_math_of_ml

posted @ 2020-02-03 20:18  ffjsls  阅读(6067)  评论(0编辑  收藏  举报