美文网首页
Transformer编码层-Bert深度

Transformer编码层-Bert深度

作者: 骆旺达 | 来源:发表于2021-01-04 21:04 被阅读0次

内容抄自:视频从中文Transformer到BERT的模型精讲,以及基于BERT情感分类实战

代码文本来自:github讲解和内容介绍

一、文章主要组成结构

  1. 进一步理解position encoding , 结合注意力矩阵可视化位置编码;
  2. 语言模型的定义和BERT解读;
  3. BERT训练之前的准备工作, 语料预处理;
  4. BERT的预训练, 训练参数;
  5. 使用BERT预训练模型进行自然语言的情感分类;
  6. BERT代码解读。

二、位置编码position encoding

在上一节中,我们讲述了位置编码的基础理论[超链接]。位置编码由sin和cos函数组成,是一个周期函数,它将距离近的文本权值增强,距离远的文本弱化,来辅助transformer模型对位置的敏感性。

自注意力算法

基于上图自注意力算法,为了更好地了解位置编码,如下图所示,我们通过自注意力机制,获得其可视化的权值图。

结合注意力矩阵的位置编码

在上图中, 在注意力阶段,我们用位置编码矩阵乘以他本身的转置, 也就是PE: \ [seq\_len, \ embedding\_dim ], 我们求PEPE^T, 得出的维度是[seq\_len, \ seq\_len ]. 我们看到上图中, 矩阵的对角线隆起, 也就是值比较大, 是因为一个矩阵乘以他本身的转置之后, 形成的矩阵的对角线正是这个矩阵的每一行(row)点乘这一行本身, 所以是值最大的区域(红色部分)。对于位置编码来说, 也就是当前位置与当前位置本身相关程度最高。再往对角线两边看, 发现以对角线(红色山峰)区域为中心, 两边属于缓慢下降趋势, 这就说明了随着离当前位置越远, 其位置编码的相关程度就越低. 由此可见, 位置编码建立在时间维度的关联关系.

语言模型和Bert

什么是语言模型, 其实用一个公式就可以表示P(c_{1},\ldots ,c_{m}), 假设我们有一句话, c_{1}到c_{m}是这句话里的m个字, 而语言模型就是求的是这句话出现的概率是多少

比如说在一个语音识别的场景, 机器听到一句话是"wo wang dai san le(我忘带伞了)", 然后机器解析出两个可能的句子, 一个是"我网袋散了", 另一个是"我忘带伞了"。根据先验知识,我们知道前者的概率大于后者。然后,语言模型目的是学习判断P("我忘带伞了") > P("我网袋散了"), 从而获得这句语音的正确解析结果是"我忘带伞了"。

BERT的全称是: Bidirectional Encoder Representations from Transformers, 如果翻译过来也就是双向transformer编码表达, 我们在上节课解读了transformer的编码器, 编码器输出的隐藏层就是自然语言序列的数学表达, 那么双向是什么意思呢? 我们来看一下下面这张图。

bert模型

上图中E_i是指的单个字或词, T_i指的是最终计算得出的隐藏层, 还记得我们在Transformer(一)中讲到的注意力矩阵和注意力加权, 经过这样的操作之后, 序列里面的每一个字, 都含有这个字前面的信息和后面的信息, 这就是双向的理解。 在这里, 一句话中每一个字, 经过注意力机制和加权之后, 当前这个字等于用这句话中其他所有字重新表达了一遍, 每个字含有了这句话中所有成分的信息。

在BERT中, 主要是以两种预训练的方式来建立语言模型:

BERT语言模型任务一: MASKED LM

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

  1. 随机把一句话中15 \%token替换成以下内容:
    1). 这些token80 \%的几率被替换成[mask];
    2). 有10 \%的几率被替换成任意一个其他的token;
    3). 有10 \%的几率原封不动.
  1. 之后让模型预测和还原被遮盖掉或替换掉的部分, 模型最终输出的隐藏层的计算结果的维度是:
    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步里当句中随机遮盖或替换的部分, 其余部分不做损失, 对于其他部分, 模型输出什么东西, 我们不在意。

BERT语言模型任务二: Next Sentence Prediction

  1. 首先我们拿到属于上下文的一对句子, 也就是两个句子, 之后我们要在这两段连续的句子里面加一些特殊token:
    [cls]上一句话,[sep]下一句话.[sep]
    也就是在句子开头加一个[cls], 在两句话之中和句末加[sep], 具体地就像下图一样:
bert模型输入
  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)

至此BERT的训练方法就讲完了, 是不是很简单, 下面我们来为BERT的预训练准备数据.

未完,待续!

相关文章

网友评论

      本文标题:Transformer编码层-Bert深度

      本文链接:https://www.haomeiwen.com/subject/shwmoktx.html