阅读 494

BERT模型:自然语言处理最新里程碑完整详解!

全文共7055字,预计学习时长14分钟

BERT全称是来自变换器的双向编码器表征量(Bidirectional Encoder Representations from Transformers),它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自然语言推理、文本分类等在许多自然语言处理任务中发挥着重要作用。

BERT是一种基于微调的多层双向变换器编码器。首先介绍下该变换器的架构,这一点尤为重要。

什么是变换器(Transformer)?

2017年,谷歌发表了一篇题为《你所需要的是注意力》的论文,该论文提出一种基于注意力的结构,以处理与序列模型相关的问题,例如机器翻译。传统的神经机器翻译大多使用循环神经网络(RNN)或卷积神经网络(CNN)作为编码-解码的模型库。然而,谷歌这一基于注意力的变换器模型摒弃传统的RNN和CNN公式。该模型高度并行运行,因此在提高翻译性能的同时,其训练速度也非常快。

进一步阐述变换器模型前,我们先对注意力做个介绍。

什么是注意力(Attention)?

注意力机制可看作模糊记忆的一种形式。记忆由模型的隐藏状态组成,模型选择从记忆中检索内容。深入了解注意力之前,先简要回顾Seq2Seq模型。传统的机器翻译主要基于Seq2Seq模型。该模型分为编码层和解码层,并由RNN或RNN变体(LSTM、GRU等)组成。编码矢量是从模型的编码部分产生的最终隐藏状态。该向量旨在封装所有输入元素的信息,以帮助解码器进行准确的预测。其用于充当模型解码器部分的初始隐藏状态。

Seq2Seq模型的主要瓶颈是需要将源序列的全部内容压缩为固定大小的矢量。如果文本稍长,则很容易丢失文本的某些信息。为解决这个问题,注意力应运而生。注意机制通过使解码器回顾源序列隐藏状态,然后将其加权平均值作为附加输入提供给解码器来缓解该问题。使用注意力,顾名思义,模型在解码阶段选择最适合当前节点的上下文作为输入内容。

注意力与传统的Seq2Seq模型有两个主要区别。

第一,编码器向解码器提供更多数据,并且编码器会向解码器提供所有节点的隐藏状态,而不仅仅是编码器的最后节点的隐藏状态。

第二,解码器不直接将所有编码器提供的隐藏状态作为输入,而是采用选择机制来选择与当前位置最匹配的隐藏状态。为此,它尝试通过计算每个隐藏状态的得分值并对得分进行softmax计算来确定哪个隐藏状态与当前节点相关性最高,这使得隐藏状态的更高相关性具有更大的分数值,不太相关的隐藏状态具有较小的分数值。然后它将每个隐藏状态与其softmax得分相乘,从而放大分数高的隐藏状态,淹没分数低的隐藏状态。该评分练习在解码器侧的每个迭代时间完成。

现在,将注意机制用可视化予以表现,研究注意流程如何进行:

1.注意解码器RNN接收<END>令牌的嵌入和初始解码器隐藏状态。

2.RNN处理其输入,产生一个输出和一个新的隐藏状态向量(h4),并丢弃输入。

3.注意步骤:使用编码器隐藏状态和h4向量来计算该迭代时间的语境向量(C4)。

4.将h4和C4连成一个向量。

5.将这个向量传递给前馈神经网络(一个与模型共同训练的网络)。

6.前馈神经网络的输出即该迭代时间的输出字。

7.重复下一个迭代时间的步骤

回到变换器

变换器模型使用编码器-解码器(encoder-decoder)架构。在谷歌发表的论文中,编码层和解码层都由6个编码器堆叠而成。每个编码器和解码器的内部结构如下:


编码器由两层组成,一个自注意层和一个前馈神经网络。自我关注不仅有助于当前节点关注当前单词,还能助其获取上下文的语义。解码器还包含编码器提到的双层网络,但在两层中间还有一个注意层,以帮助当前节点获得需要注意的关键内容。

以下是变换器架构的详细结构:

接下来逐个分析其组成部分。

自注意(Self-Attention)

自注意是变换器将其他相关单词的“理解”转换为所处理的单词的一种方式。

首先,自注意计算三个新的向量。在论文中,向量的维度是512维。将这三个向量分别称为Query,Key和Value。这三个向量通过字嵌入向量与随机初始化矩阵(论文中的维数为(64,512))相乘而产生的,并在反向传播过程中不断更新。

接下来,计算自注意的分数值,在某个位置编码单词时,它能决定在所输入句子其余部分投入的注意力。该分数值可通过Query和Key向量计算得出。然后用所得结果除以一个常数。本文中,该常数为8,这个值通常是上述矩阵第一维的平方根,即64的平方根8。然后对所有得分进行softmax计算。结果表示每个单词与当前位置单词的相关性。当然,当前词的相关性肯定会很大。最后一步是将Value向量与softmax所得结果相乘并求和。结果是当前节点处的自注意值。

这种通过查询和密钥之间的相似度,来确定值的权重分布的方法,被称为缩放的点积注意。

多头注意

本论文中更精辟的部分是增加了另一种自注意机制,称为“多头”注意,它不仅仅初始化一组Q,K,V矩阵。相反,初始化多个组,且变换器使用8个组,因此最终结果是8个矩阵。

前馈神经网络不能接受8个矩阵,因此需要一种方法将其减少为1个。为此,首先将8个矩阵连接在一起得到一个大矩阵,然后将这个组合矩阵与一个随机初始化矩阵相乘得到最后的矩阵。整个流程如下图所示。

变换器的多头注意有三种使用方式:

1.在“编码-解码注意”层中,查询来自先前的解码器层,存储器键和值来自编码器的输出。这使解码器中的每个位置都参与输入序列中的所有位置。并模拟出序列到序列模型中典型的编码-解码注意机制。

2.编码器包含自注意层。在自注意层中,所有键、所有值和查询都来自相同的位置,在这种情况下,它们来自于编码器中前一层的输出。编码器中的每个位置都可以处理编码器前一层中的所有位置。

3.与其相似的是,解码器中的自注意层令解码器中的每个位置参与到解码器中的所有位置,直到并包括该位置。在此需要预防解码器中的向左信息流,以此保持自回归属性。通过掩蔽(设置为-∞)softmax中与非法连接相对应的所有值来实现缩放点积注意。这将在解码器部分更加详细地探讨,在此仅讨论掩蔽(Masking)。

位置编码

到目前为止,还没有办法解释变换器模型中输入序列中的单词顺序。为了解决此问题,变换器在编码器和解码器层的输入端增加了一个额外的矢量位置编码。其维度与嵌入维度相同。此位置编码的值将添加到嵌入层的值中,并作为输入发送到下一层。位置编码选项有很多,包括学习和修复。

残余连接和层规范化

在编码器和解码器中,在两个子层的周围都采用残余连接,然后进行层规范化。跳过连接或残余连接用于允许梯度直接流过网络,而不通过非线性激活功能。非线性激活函数本质上是非线性的,导致梯度爆炸或消失(取决于权重)。从概念上说,跳过连接形成一条“总线”,它在网络中流动,反过来,梯度也可以沿着它向后流动。规范化有助于解决内部协变量偏移的问题。内部协变量偏移是指在神经网络内发生的协变量偏移,即从(例如)第2层到第3层。这是因为当网络学习且权重被更新时,网络中特定层的输出分布会发生变化。这迫使较高层适应该漂移,这减慢了学习速度。在对神经网络中的输入进行归一化后,不必担心输入特征的规模差别很大。要了解层规范化,将其与批规范化进行对比非常有用。一小批包含具有相同数量功能的多个示例。小批是矩阵 - 如果每个输入是多维的,则为张量 - 其中一个轴对应批,另一个轴或多个轴对应特征尺寸。批规范化规范批维度中的输入要素。层规范化的关键特性是它可以对要素之间的输入进行标准化。在批规范化中,统计信息在批处理中计算,并且对于批中的每个示例都是相同的。相反,在层规范化中,统计数据是跨每个特征计算的,并且与其他示例无关。

将残余连接和层规范化放在一起

解码器

回看变换器体系结构图,可以看到解码器部分与编码器部分相似,但底部有一个掩盖的多头注意。Mask表示屏蔽某些值的掩码,以便在更新参数时它们不起作用。变换器模型中有两种掩码—填充掩码和序列掩码。填充掩码用于所有缩放的点积注意,序列掩码仅用于解码器的自注意。

填充掩码解决了输入序列具有可变长度的问题。具体来说,在较短的序列后填0。但是如果输入序列太长,则会截取左侧的内容,并直接丢弃多余的内容。因为这些填充的位置实际上没有意义,注意机制不应该集中在这些位置,所以需要做一些处理。具体方法是在这些位置的值上加一个非常大的负数(负无穷大),这样这些位置的概率在softmax计算之后将接近0!填充掩码实际上是一个张量,每个值都是一个布尔值,false值指想要处理的值。

A序列掩码旨在确保解码器无法查看将来的信息。也就是说,对于序列,在time_step t,解码输出应该仅取决于t之前的输出,而不取决于t之后的输出。这针对于变换器架构,因为没有RNN,可以按顺序输入序列。在此,一起输入所有内容,如果没有掩码,多头注意将考虑每个位置的整个解码器输入序列。通过生成上三角矩阵来实现这一点,上三角形的值全为零,并将该矩阵应用于每个序列。

对于解码器的自注意,在此使用缩放的点积注意,并且添加填充掩码和序列掩码作为attn_mask。在其他情况下,attn_mask等于填充掩码。

另一个细节是解码器输入将向右移动一个位置。这样做的一个原因是不希望模型在训练期间学习如何复制解码器输入,但还是想要了解给定编码器序列和模型已经看到的特定解码器序列,从而预测下一个单词/字符。如果不移位解码器序列,模型则简单地学习“复制”解码器输入,因为位置 i 的目标字/字符将是解码器输入中的字/字符 i 。因此,通过将解码器输入移位一个位置,模型需要预测仅在解码器序列中看到单词/字符 1, …, i-1 的位置 i 的目标字/字符。这可以防止模型学习复制/粘贴任务。用句子开头令牌填充解码器输入的第一个位置,由于右移,该位置将是空的。类似地,将一个句末标记附加到解码器输入序列以标记该序列的结尾,并且它还附加到目标输出语句。

输出层

在完全执行解码器层后,为将得到的矢量映射到来自词汇表的单词,在结尾添加完全连接层和softmax层。

线性层是一个简单的完全连接的神经网络,它将解码器堆栈产生的矢量投影到一个更大的矢量中,称为logits矢量。假设模型知道从训练数据集中学到的10,000个独特的英语单词(模型的“输出词汇表”) 这将使logits矢量10,000个细胞变宽 - 每个单元对应于一个唯一单词的得分。这就是对于线性层后的模型输出的解释。然后,softmax层将这些分数转换为概率(所有正数,所有加起来都为1.0)。选择具有最高概率的单元,并将与其相关联的单词作为该迭代时长的输出。

回到BERT模型

BERT模型基于变换器架构。它是一种具有双向深度的神经网络模型。BERT模型的关键技术创新是将变换器的双向培训应用于语言建模。这与先前从左到右查看文本序列或从左到右和从右到左组合训练的努力尝试形成对比。BERT模型采用了一种名为掩蔽语言模型(Masked Language Modeling)的新技术(将在后文看到),它允许在从前不可能使用的模型中进行双向训练。在其vanilla form中,变换器包括两个独立的机制——读取文本输入的编码器和产生任务预测的解码器。由于BERT模型的目标是生成语言模型,因此只需要编码器机制。

谷歌最初发布了两个版本,如下图所示。这里L表示变压器的层数,H表示输出的维数,A表示多头注意的数量。在这两个版本中,前馈大小都设置为4层。

BERTBASE: L=12, H=768, A=12, Total Parameters=110M

BERTLARGE: L=24, H=1024, A=16, Total Parameters=340M

使用BERT模型有两个阶段:预训练和微调。在预训练期间,模型在不同的预训练任务上训练未标记的数据。对于微调,首先使用预训练参数初始化BERT模型,并使用来自下游任务的标记数据对所有参数进行微调。每个下游任务都有单独的微调模型,即使它们使用相同的预训练参数进行初始化。BERT模型的一个显著特点是它跨越不同任务的统一架构。预训练架构与最终下游架构之间的差异很小。在微调期间,所有参数都经过微调。


BERT模型预训练过程

BERT模型预训练阶段包括两个无监督预测任务:掩蔽语言模型和下一句预测。

掩蔽语言模型(MLM)——由于BERT模型的双向功能(双向性)及其使用的多层自关注机制的效果,为了训练深度双向表示,一些百分比(论文中为15%)输入令牌的输入被简单地随机掩盖,然后预测那些被屏蔽的令牌。对应于掩模标记的最终隐藏向量被馈送到词汇表上的输出softmax,如在标准学习模型LM中。与从左到右的语言模型预训练不同,MLM目标允许表示融合的左侧和右侧的上下文,这使得可以预先训练深度双向变换器。虽然这允许获得双向预训练模型,但缺点是预训练和微调之间存在不匹配,因为在微调期间不出现[MASK]标记。为了缓解这种情况,作者并不总是用实际的[MASK]标记替换“蒙面”单词。训练数据生成器随机选择15%的令牌位置进行预测。如果选择了第i个令牌,则将其替换为(1)[MASK]标记80%的时间(2)随机标记10%的时间(3)未更改的第i个标记10%时间。BERT模型损失函数仅考虑掩蔽值的预测并忽略非掩蔽字的预测。因此,模型比定向模型收敛得慢,这一特征被其增加的情境感知所抵消。

下一句预测(NSP)。为了训练理解句子关系以及单词之间的语义关系的模型,BERT模型还预先训练二进制化的下一句预测任务,该任务可以从任何文本语料库中轻易生成。为A和B选择一些句子,其中50%的数据B是A的下一个句子,剩余的50%的数据B是在语料库中随机选择的,然后学习相关性。添加这种预训练的目的是许多自然语言处理任务(如QA和NLI)需要理解两个句子之间的关系,以便预训练模型能够更好地适应这些任务。

为了帮助模型区分训练中的两个句子,输入在进入模型之前按以下方式处理:

1.在第一个句子的开头插入[CLS]标记,并在每个句子的末尾插入[SEP]标记。

2.在每个标记中添加表示句子A或句子B的句子嵌入。句子嵌入在概念上类似于词汇量为2的标记嵌入。

3.向每个标记添加位置嵌入以指示其在序列中的位置。位置嵌入的概念和实现已在变换器论文中给出。

要预测第二个句子是否确实与第一个句子连接,需执行以下步骤:

1.整个输入序列经过变换器模型。

2.使用简单的分类层(权重和偏差的学习矩阵)将[CLS]标记的输出转换为2×1型的矢量。

3.使用softmax计算IsNextSequence的概率。

在训练BERT模型时,MLM和NSP是被同时训练的,目标是最小化两种策略的组合损失函数。

标记化—BERT模型不会将单词视作标记。相反,它会看WordPieces。这意味着一个单词可以分解为多个子单词。这种标记化在处理词汇单词时是有益的,它可以帮助更好地表示复杂的单词。

BERT模型的输入

BERT的输入可以是单词序列中的单个句子或句子对(例如,[问题,答案])。对于给定的单词,其输入表示可以由三部分嵌入求和组成。嵌入的可视化表示如下所示:

标记嵌入表示单词向量。第一个字是CLS标志,可用于后续分类任务。对于非分类任务,可以忽略CLS标志。段嵌入用于区分两个句子,因为预训练不仅是语言模型,而且还是具有两个句子作为输入的分类任务。位置嵌入编码字顺序。

用于下游自然语言处理任务的BERT模型微调

对于每个下游自然语言处理任务,只需将特定于任务的输入和输出插入BERT模型,并对端到端的所有参数进行微调。在输入处,来自预训练的句子A和句子B可类比于释义中的句子对,蕴涵中的假设前提对,问题回答中的问题通道对等。在输出处,标记表示被馈送到用于标记级别任务的输出层,例如序列标记或问题回答,并且[CLS]表示被馈送到输出层以进行分类,例如蕴涵或情绪分析。与预训练相比,微调相对便宜。

BERT模型可用于各种语言任务,而只需在核心模型中添加一个小层:

1.通过在[CLS]标记的变换器输出上添加分类层,类似于下一句分类,进行情感分析等分类任务。

2.在问题回答任务(例如SQUAD v1.1)中,软件会收到有关文本序列的问题,并且需要在序列中标记答案。使用BERT模型,可以通过学习标记答案开始和结束的两个额外向量来训练Q&A模型。

3.在命名实体识别(NER)中,软件接收文本序列,并且需要标记文本中出现的各种类型的实体(人员,组织,日期等)。使用BERT模型,可以通过将每个标记的输出向量馈送到预测NER标签的分类层来训练NER模型。

BERT模型用于特征提取

微调法不是使用BERT模型的唯一方法。可以使用预先训练的BERT模型创建语境化词嵌入。然后,可以将这些嵌入提供给现有的模型——该过程本文展示了产生结果,在命名实体识别等任务上微调BERT模型并不远。


哪个向量最适合作为上下文嵌入呢?这要视任务而定。本文共考察了六种可选方法(与得分为96.4的微调模型相比):


留言 点赞 关注

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”


(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)


关注下面的标签,发现更多相似文章
评论