有任何的书写错误、排版错误、概念错误等,希望大家包含指正。
在阅读本篇之前建议先学习:
【自然语言处理】Seq2Seq 讲解
【自然语言处理】Attention 讲解
【自然语言处理】ELMo 讲解
【自然语言处理】Transformer 讲解
ELMo 模型可以根据上下文更新词的特征表示,实现了词向量由静态向动态的转变,较好的解决了一词多义问题。不过因 ELMo 依赖 LSTM 的架构,仍然属于自动回归问题,导致其训练只能按部就班,严格遵守从左到右或从右到左的次序进行训练,所以在面对特大语料库时将非常耗时,这种局限也直接影响其性能和扩展性。此外,LSTM 虽然也有记忆功能,但其长期记忆的效果并不理想。
为解决 ELMo 模型的这些问题,人们研究出了新的方法,如 BERT、GPT 等预训练模型,这些模型不再基于 LSTM 框架,而是基于一种更强大的 Transformer 框架,很好地解决了并发问题。另外,相较于 ELMo,BERT 采用了真正的微调。
整体来说,BERT 模型是由 Transformer 编码器堆叠而成的深层编码器,模型的输入由三个嵌入相加表示。模型的训练包括两个阶段:预训练和微调。在预训练阶段,使用由无人工标注的大型语料库构建数据集,训练目标是让模型在两个预训练任务上表现尽可能出色;在微调阶段,为每个下游任务设计简单的模型(或部件),完成预训练的模型的输出作为其输入,使用人工标注的小型数据集对两部分共同训练,训练目标是让与下游任务有关的部件的输出在对应任务上的效果尽可能理想。
BERT 模型结构非常简单,由多个 Transformer 的编码器堆叠而成,如图 1 1 1 所示。
图 1 Bert 模型框架
论文中提到了简单和复杂两个模型,对应的超参数分别如下。
B E R T B A S E \rm BERT_{BASE} BERTBASE: L = 12 L=12 L=12, H = 768 H=768 H=768, A = 12 A=12 A=12,参数总量 110 M 110\rm M 110M;
B E R T L A R G E \rm BERT_{LARGE} BERTLARGE: L = 24 L=24 L=24, H = 1024 H=1024 H=1024, A = 16 A=16 A=16,参数总量 340 M 340\rm M 340M。
其中, L L L 表示网络层数,即堆叠的编码器个数, H H H 表示隐层大小,实际对应每个输入词元(token)的向量维度, A A A 表示多注意力中自注意力头数量,这里 FFN 的隐藏层大小与输入大小的比值一般设置为 4 4 4,即 4 × H 4\times H 4×H。
关于参数总量的计算。首先,每个词元都需要经过嵌入层,将单词(编号)转换为词向量,对应的参数个数为 v o c a b _ s i z e × H {\rm vocab\_size} \times H vocab_size×H;多头注意力机制中,总共涉及四个参数矩阵, W Q W_Q WQ、 W K W_K WK、 W V W_V WV 和 W O W_O WO,其中 W Q W_Q WQ、 W K W_K WK 和 W V W_V WV 是每个头拼接后的参数矩阵,用于获取 Q Q Q、 K K K 和 V V V, W O W_O WO 用于融合每个头提取的特征,一般地,四者的行数与列数相等,均为 H H H,故对应的参数个数为 4 × H × H 4\times H\times H 4×H×H;FFN 是单隐层的多层感知机,输入层和输出层神经元个数均为 H H H,隐藏层神经元个数为 4 × H 4\times H 4×H,对应的参数个数为 H × 4 H + 4 H × H H\times 4H + 4H\times H H×4H+4H×H;总共 L L L 层编码器,因此模型参数总量计算公式为 v o c a b _ s i z e × H + ( 4 × H 2 + 8 × H 2 ) × L = v o c a b _ s i z e × H + 12 × L × H 2 {\rm vocab\_size} \times H + (4\times H^2 + 8\times H^2)\times L = {\rm vocab\_size} \times H + 12 \times L \times H^2 vocab_size×H+(4×H2+8×H2)×L=vocab_size×H+12×L×H2。
对于简单 BERT 模型,可以计算出参数总量为 107 , 974 , 656 ≈ 110 M 107,974,656≈110 \rm M 107,974,656≈110M;对于复杂 BERT 模型,可以计算出参数总量为 332 , 709 , 888 ≈ 340 M 332,709,888≈340 \rm M 332,709,888≈340M 。
BERT 模型输入的 H H H 维词元编码向量是三个嵌入特征的加和,如图 2 2 2 所示。
图 2 Bert 的输入特征
引入两个特殊符号
和
,分别表示 classification 和 separation。BERT 模型允许输入一段语句或者两段语句。每段语句由特殊符号
结尾,作为语句之间的边界;第一段语句由特殊符号
开头,用于保存单段语句的语义信息或两段语句的语义关系。
这里的“语句”不是以句号界定,而是以特殊符号
界定。
BERT 模型由注意力模块构成,注意力模块中的单元与时序无关,因此
可以放在开头,也可以放在末尾,甚至可以放在中间任意位置。注意其它词元或特殊符号学习到的向量无法起到与
相同的作用,这是因为其它词元对应的注意力向量会对自己“情不自禁”地偏爱,而
对全部词元都是“公平”的,不会出现与训练目标无关的偏爱;其他特殊符号,比如
,起到分割语句的作用,可以认为是
,这显然具有语义信息,也就存在偏爱问题。
BERT 采用 WordPiece 分词器将单词划分成词元,这种分词方式可以将单词本体与前缀或后缀分开,与直接将不同形式的同词根单词记为词汇表中的不同项相比,WordPiece 可以减少词汇表大小,并可以做到一定程度的词汇相似性,比如 play
和 playing
将具有一定的联系。但不足的是,由于一个单词将可能被分解为多个词元,模型的输入序列长度将会增加,产生输入序列长度的非线性复杂度的问题。
在代码实现时,特殊符号除了
和
外,还有
、
和
,这三个特殊符号分别是遮掩符号、未知符号和填充符号。
将在下面介绍;
用于表示不在词汇表中的单词、标点符号或表情等;
用于保证序列长度相同。输入的原始语句经过分词后得到分词序列,向分词序列的合适位置插入特殊符号后得到词元序列,词元序列中的每个词元都对应三种嵌入,三种嵌入的加和作为 BERT 模型的真正输入。
代码实现时的一些细节:
不属于任何一段语句,因此其对应的段嵌入一般设置为 0;
我们知道 Transformer 的编码器存在 Padding Mask,同理,由 Trm 编码器堆叠而成的 BERT 模型在将序列输入到 Trm 编码器的结构中时,需要连同 Padding Mask 一并输入。
BERT 模型中位置嵌入是通过训练不断调整的,但是一般会将位置嵌入初始化为 Transformer 中由正弦、余弦函数生成的位置嵌入。依然要注意,词元序列中的每个词元(包括特殊符号)都有对应的位置嵌入。
掩码语言模型(Masked Language Model,MLM)是一种真正的双向的方法,而 ELMo 模型只是将从左到右和从右到左的训练结果拼接起来。具体来说,MLM 的核心思想在于预训练时将一部分词元随机遮掩掉,该语言模型的任务是预测出被遮盖部分的词元。这和完形填空(cloze)的思想一致,在进行完形填空时,模型不得不学习被遮掉部分的上下文信息来确定正确的填法。
BERT 模型将这种完形填空作为预训练任务之一,使其具有直接捕获上下文信息的能力,而不是拼接双向信息。其实,BERT 模型不得不选择完形填空作为学习上下文信息的方法。BERT 模型仅由 Transformer 的编码器构成,作为自编码(AutoEncode)语言模型,它仅具备编码能力,但不具备解码能力。在编码阶段,模型可以看见全部输入,这使得其无法像自回归语言(AutoRegressive)语言模型一样根据前面的输入来预测下一个单词,因此,完形填空的方法是 BERT 模型在预训练阶段迫不得以的选择。
在代码实现时,每个输入语句 15 % 15\% 15% 的词元会被随机遮掩掉,这些被遮掩掉的词的预测结果将会被用于定义损失函数。对于这 15 % 15\% 15% 的词元,有 80 % 80\% 80% 是真正被特殊符号
替换,还有 10 % 10\% 10% 被替换为其他任意词元,剩下的 10 % 10\% 10% 会保留原始词元。不对全部的 15 % 15\% 15% 的词元进行替换的原因在于,模型在推断阶段中的输入不包括特殊符号
,如果模型在预训练阶段的预测结果过度依赖
而不是被遮掩位置的上下文信息,那么预训练出的模型是不理想的。因此需要引入一些噪声,减轻遮掩位置词元对模型的影响,这些噪声就是被随机替换的词元和保留的词元。另外,只会对非特殊符号进行遮掩。
完形填空预训练任务对应的损失函数定义为,将被遮掩掉的位置的输出向量经过可学习的线性映射( H × v o c a b _ s i z e H\times {\rm vocab\_size} H×vocab_size)和 Softmax 后与真实标签计算交叉熵之和。
BERT 模型的第二个预训练任务是预测下一个句子(Next Sentence Prediction,NSP)。具体来说,NSP 对应的数据集为语句对,标签为后段语句是否是后段语句的下一个句子。在代码实现时,从一篇文章中选择两段连续的语句作为正样本,从不同文章中随机选择两段语句作为负样本,正负样本各占 50 % 50\% 50%。
这种生成正负样本的方式存在一点问题。在 NSP 中负样本的两段语句来自主题不同的两篇文章,但是正样本的两段语句具有相同的主题,这导致 NSP 将两段语句的主题预测任务和语句的连贯性判断任务合并成一个任务。主题预测任务相比于连贯性判断任务更加简单、更加有效,从而导致模型过多的学习主题特征而不是连贯性特征,这与我们的目标是相违背的。后续的改进,比如 ALbert,直接抛弃了主题预测,ALbert 要求正样本和负样本来自同一篇文章。
可见,BERT 模型允许输入两段语句,与 NSP 任务有密不可分的关系。论文作者希望 BERT 模型在问答(Question Answering,QA)和自然语言推理(Natural Language Inference,NLI)等涉及多段语句的下游任务也能够有理想的效果,因此在预训练阶段添加 NSP 让模型学习两段语句之间的潜在关系。
QA:准确来说是 Extraction-based Question Answering,即问题的答案一定是文本中的一段连续的语句。
NLI:判断两个语句的语义关系:Entailment(蕴含)、Contradiction(矛盾)、Neutral(中立)。
NSP 预训练任务对应的损失函数定义为,将特殊符号
位置的输出向量经过可学习的线性映射( H × 2 H\times 2 H×2)和 Softmax 后由与真实标签计算交叉熵之和。
另外,预训练阶段的完整损失函数由完形填空损失函数与 NSP 损失函数相加来定义。预训练过程(包括生成掩码输入的过程)如图 3 3 3 所示。
图 3 预训练过程(包括生成掩码输入过程)
现有的两种方法可以将预训练好的语言模型表示应用到下游任务:基于特征(feature-based)和微调(fine-tuning)。ELMo 是基于特征的方法,预训练提取到的文本特征将作为附加信息输入到特定的下游任务模型中。Bert 一般采用微调方法,在完成预训练的模型的输出后连接与特定下游任务有关的简单结构,使用与下游任务有关的带标签的数据集对模型的内部参数进行微调,而与下游任务有关的简单结构内的参数则从头开始训练(trained from scratch)。可见,微调是一种迁移学习方法。
BERT 可以采用基于特征的方法,即选择 BERT 不同层的编码器的输出作为提取到的不同层次的语义特征,将这些特征加权或者拼接作为下游任务的附加输入,这与 ELMo 的输出向量的用法是类似的。
下面是 BERT 采用微调的方法应用到四种经典下游任务:单语句分类任务(Single Sentence Classification Tasks)、单语句标注任务(Single Sentence Tagging Tasks)、语句对分类任务(Sentence Pair Classification Tasks),问答任务(Question Answering Tasks)。
(朴素)BERT 模型采用编码器的结构使得其无法完成机器翻译等任务。
经典的单语句分类任务是情感分析(Sentiment Analysis)和情绪分析(Emotion Analysis)。BERT 模型将
位置的输出向量经过线性映射层和 Softmax 的结果作为预测标签。线性映射层和 Softmax 层是单语句分类任务对应的模块。如图 4 4 4 所示。
图 4 单语句分类任务微调
情感分析与情绪分析的区别:
情感分析,亦谓观点分析,是二分类,标签只包括积极(positive)和消极(negative),旨在捕捉总体感觉或印象;情绪可以包括喜怒哀乐等,是多分类,可以认为是一种细粒度的情感分析。
单语句标注任务就是命名实体识别(Named Entity Recognition,NER)。与单语句分类任务类似,只不过 NER 需要对全部词元进行多分类。如图 5 5 5 所示。
图 5 单语句标注任务微调
自然语言推理(Natural Language Inference,NLI)是一种语句对的分类任务。根据两段语句
位置的输出向量判断两段语句的关系是Entailment(蕴含)、Contradiction(矛盾)还是 Neutral(中立)。如图 6 6 6 所示。
图 6 语句对分类任务微调
严谨来说,这里的问答任务是指答案是输入文本中的一段话或若干连续单词的问答任务,即 Extraction-based Question Answering。在代码实现时,一般规定输入的第一段语句为问题,第二段语句为答案所在的文章,问答任务是学习两个向量,它们分别表示答案开始所在位置和答案结尾所在位置。推断阶段,让开始向量和结尾向量分别与第二段语句的全部词元计算内积,将计算结果进行 Softmax,以最大概率值分别确定答案的开始位置和结尾位置。如图 7 7 7 所示。
图 7 问答任务微调
[1] 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.
[2] 《深入浅出 Embedding》吴茂贵等著
[3] BERT 论文逐段精读【论文精读】- bilibili
[4] 台大教授 李宏毅 bert - bilibili
[5] BERT模型简单回顾 - bilibili
[6] 预训练之NSP任务详解 - bilibili
[7] 源码(易懂):GitHub - codertimo/BERT-pytorch: Google AI 2018 BERT pytorch implementation
[8] 源码(难懂):GitHub - google-research/bert: TensorFlow code and pre-trained models for BERT
[9] BERT源码实现与解读(Pytorch) -_51CTO
[10] BERT四大下游任务 - 知乎
[11] BERT论文翻译 - 简书
[12] BERT从零详细解读:如何做预训练 - MLM+NSP_bert mlm_- CSDN
[13] NLP中Tokenizers总结(BPE、WordPiece、Unigram和SentencePiece)- CSDN
[14] 【NLP learning】Tokenizer分词技术概述 - CSDN
[15] 【深度学习】NLP之Bert(2)QA - CSDN
[16] 自回归和自编码 - CSDN
[17] NLP情感分析与情绪分析,傻傻分不清楚 - bilibili
[18] Sentiments Analysis Vs emotion Analysis - Stack Overflow