BERT模型总结

BERT模型总结

前言

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

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

1. 模型总体结构

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

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

2. 位置编码

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

​ 在具体处理方式上,采用的是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的结构中,在对每维数据计算权重时,是采用点积的形式,本质上就是计算向量之间的相关性。而位置编码将临近的数据加上频率接近的位置编码,就是增长了相邻数据的相关性。下图是位置编码向量的热图,能够看出距离越近,频率就更加接近。jvm

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\),这样作的目的上文已经说过,是为了获取文本的时序相关性。ui

​ 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. 残差链接

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

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的预训练中任务之一, 简单来讲, 就是随机遮盖或替换一句话里面任意字或词, 而后让模型经过上下文的理解预测那一个被遮盖或替换的部分, 以后Loss的时候只计算被遮盖部分的Loss, 实际上是一个很容易理解的任务, 实际操做方式以下:

  1. 随机把一句话中$15 % $token替换成如下内容:
    1) 这些token$80 % $的概率被替换成[mask];
    2) 有10 \%的概率被替换成任意一个其余的token;
    3) 有10 \%的概率原封不动.
  2. 以后让模型预测和还原被遮盖掉或替换掉的部分, 模型最终输出的隐藏层的计算结果的维度是:
    X_{hidden}: [batch\_size, \ seq\_len, \  embedding\_dim]
    咱们初始化一个映射层的权重W_{vocab}:
    W_{vocab}: [embedding\_dim, \ vocab\_size]
    咱们用W_{vocab}完成隐藏维度到字向量数量的映射, 只要求X_{hidden}W_{vocab}的矩阵乘(点积):
    $X_{hidden}W_{vocab}: [batch_size,  seq_len,  vocab_size] $ 以后把上面的计算结果在vocab\_size(最后一个)维度作softmax归一化, 是每一个字对应的vocab\_size的和为1, 咱们就能够经过vocab\_size里几率最大的字来获得模型的预测结果, 就能够和咱们准备好的Label作损失(Loss)并反传梯度了.
    注意作损失的时候, 只计算在第1步里当句中随机遮盖或替换的部分, 其他部分不作损失, 对于其余部分, 模型输出什么东西, 咱们不在乎.

(2) Next Sentence Predict(NSP)

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

img

  1. 咱们看到上图中两句话是[cls] my dog is cute [sep] he likes playing [sep], [cls]个人狗很可爱[sep]他喜欢玩耍[sep], 除此以外, 咱们还要准备一样格式的两句话, 但他们不属于上下文关系的状况;
    [cls]个人狗很可爱[sep]企鹅不擅长飞行[sep], 可见这属于上下句不属于上下文关系的状况;
    在实际的训练中, 咱们让上面两种状况出现的比例为1:1, 也就是一半的时间输出的文本属于上下文关系, 一半时间不是.
  2. 咱们进行完上述步骤以后, 还要随机初始化一个可训练的segment \ embeddings, 见上图中, 做用就是用embeddings的信息让模型分开上下句, 咱们一把给上句全0token, 下句啊全1token, 让模型得以判断上下句的起止位置, 例如:
    [cls]个人狗很可爱[sep]企鹅不擅长飞行[sep]
    $0 \quad   0   0    0   0   0   0    0    1    1   1   1   1   1   1   1 $
    上面01就是segment \ embeddings.
  3. 还记得咱们上节课说过的, 注意力机制就是, 让每句话中的每个字对应的那一条向量里, 都融入这句话全部字的信息, 那么咱们在最终隐藏层的计算结果里, 只要取出[cls]token所对应的一条向量, 里面就含有整个句子的信息, 由于咱们指望这个句子里面全部信息都会往[cls]token所对应的一条向量里汇总:
    模型最终输出的隐藏层的计算结果的维度是:
    咱们X_{hidden}: [batch\_size, \ seq\_len, \  embedding\_dim]
    咱们要取出[cls]token所对应的一条向量, [cls]对应着\ seq\_len维度的第0条:
    cls\_vector = X_{hidden}[:, \ 0, \ :]
    cls\_vector \in \mathbb{R}^{batch\_size, \  embedding\_dim}
    以后咱们再初始化一个权重, 完成从embedding\_dim维度到1的映射, 也就是逻辑回归, 以后用sigmoid函数激活, 就获得了而分类问题的推断.
    咱们用\hat{y}来表示模型的输出的推断, 他的值介于(0, \ 1)之间:
    \(\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

相关文章
相关标签/搜索