一、BERT模型介绍
思考题:Bert模型的架构以及每一部分的作用?
思考题:Bert模型两大预训练任务,并谈一谈你的理解?
1 BERT简介
BERT是2018年10月由Google AI研究院提出的一种预训练模型.
-
BERT的全称是Bidirectional Encoder Representation from Transformers.
-
BERT在机器阅读理解顶级水平测试SQuAD1.1中表现出惊人的成绩: 全部两个衡量指标上全面超越人类, 并且在11种不同NLP测试中创出SOTA表现. 包括将GLUE基准推高至80.4% (绝对改进7.6%), MultiNLI准确度达到86.7% (绝对改进5.6%). 成为NLP发展史上的里程碑式的模型成就.
2 BERT的架构
总体架构: 如下图所示, 最左边的就是BERT的架构图, 可以很清楚的看到BERT采用了Transformer Encoder block进行连接, 因为是一个典型的双向编码模型.
从上面的架构图中可以看到, 宏观上BERT分三个主要模块.
-
最底层黄色标记的Embedding模块.
-
中间层蓝色标记的Transformer模块.
-
最上层绿色标记的预微调模块.
2.1 Embedding模块
BERT中的该模块是由三种Embedding共同组成而成, 如下图
Token Embeddings 是词嵌入张量, 第一个单词是CLS标志, 可以用于之后的分类任务.
Segment Embeddings 是句子分段嵌入张量, 是为了服务后续的两个句子为输入的预训练任务.
Position Embeddings 是位置编码张量, 此处注意和传统的Transformer不同, 不是三角函数计算的固定位置编码, 而是通过学习得出来的.
整个Embedding模块的输出张量就是这3个张量的直接加和结果.
2.2 双向Transformer模块
BERT中只使用了经典Transformer架构中的Encoder部分, 完全舍弃了Decoder部分. 而两大预训练任务也集中体现在训练Transformer模块中.
2.3 预微调模块
-
经过中间层Transformer的处理后, BERT的最后一层根据任务的不同需求而做不同的调整即可.
-
比如对于sequence-level的分类任务, BERT直接取第一个[CLS] token 的final hidden state, 再加一层全连接层后进行softmax来预测最终的标签.
对于不同的任务, 微调都集中在预微调模块, 几种重要的NLP微调任务架构图展示如下
从上图中可以发现, 在面对特定任务时, 只需要对预微调层进行微调, 就可以利用Transformer强大的注意力机制来模拟很多下游任务, 并得到SOTA的结果. (句子对关系判断, 单文本主题分类, 问答任务(QA), 单句贴标签(NER))
若干可选的超参数建议如下:
Batch size: 16, 32
Learning rate (Adam): 5e-5, 3e-5, 2e-5
Epochs: 3, 4
3 BERT的预训练任务
BERT包含两个预训练任务:
-
任务一: Masked LM (带mask的语言模型训练)
-
任务二: Next Sentence Prediction (下一句话预测任务)
3.1 任务一: Masked LM
带mask的语言模型训练
-
关于传统的语言模型训练, 都是采用left-to-right, 或者left-to-right + right-to-left结合的方式, 但这种单向方式或者拼接的方式提取特征的能力有限. 为此BERT提出一个深度双向表达模型(deep bidirectional representation). 即采用MASK任务来训练模型.
-
1: 在原始训练文本中, 随机的抽取15%的token作为参与MASK任务的对象.
-
2: 在这些被选中的token中, 数据生成器并不是把它们全部变成[MASK], 而是有下列3种情况.
-
2.1: 在80%的概率下, 用[MASK]标记替换该token, 比如my dog is hairy -> my dog is [MASK]
-
2.2: 在10%的概率下, 用一个随机的单词替换token, 比如my dog is hairy -> my dog is apple
-
2.3: 在10%的概率下, 保持该token不变, 比如my dog is hairy -> my dog is hairy
-
3: 模型在训练的过程中, 并不知道它将要预测哪些单词? 哪些单词是原始的样子? 哪些单词被遮掩成了[MASK]? 哪些单词被替换成了其他单词? 正是在这样一种高度不确定的情况下, 反倒逼着模型快速学习该token的分布式上下文的语义, 尽最大努力学习原始语言说话的样子. 同时因为原始文本中只有15%的token参与了MASK操作, 并不会破坏原语言的表达能力和语言规则.
3.2 任务二: Next Sentence Prediction
下一句话预测任务
-
在NLP中有一类重要的问题比如QA(Quention-Answer), NLI(Natural Language Inference), 需要模型能够很好的理解两个句子之间的关系, 从而需要在模型的训练中引入对应的任务. 在BERT中引入的就是Next Sentence Prediction任务. 采用的方式是输入句子对(A, B), 模型来预测句子B是不是句子A的真实的下一句话.
-
1: 所有参与任务训练的语句都被选中作为句子A.
-
1.1: 其中50%的B是原始文本中真实跟随A的下一句话. (标记为IsNext, 代表正样本)
-
1.2: 其中50%的B是原始文本中随机抽取的一句话. (标记为NotNext, 代表负样本)
-
2: 在任务二中, BERT模型可以在测试集上取得97%-98%的准确率.
二、BERT模型特点
思考题:BERT模型的优点和缺点?
思考题:BERT的MLM任务中为什么采用了80%, 10%, 10%的策略?
思考题:长文本预测任务如果想用BERT来实现, 要如何构造训练样本?
1 BERT模型优缺点
1.1 BERT的优点
-
通过预训练, 加上Fine-tunning, 在11项NLP任务上取得最优结果.
-
BERT的根基源于Transformer, 相比传统RNN更加高效, 可以并行化处理同时能捕捉长距离的语义和结构依赖.
-
BERT采用了Transformer架构中的Encoder模块, 不仅仅获得了真正意义上的bidirectional context, 而且为后续微调任务留出了足够的调整空间.
1.2 BERT的缺点
-
BERT模型过于庞大, 参数太多, 不利于资源紧张的应用场景, 也不利于上线的实时处理.
-
BERT目前给出的中文模型中, 是以字为基本token单位的, 很多需要词向量的应用无法直接使用. 同时该模型无法识别很多生僻词, 只能以UNK代替.
-
BERT中第一个预训练任务MLM中, [MASK]标记只在训练阶段出现, 而在预测阶段不会出现, 这就造成了一定的信息偏差, 因此训练时不能过多的使用[MASK], 否则会影响模型的表现.
-
按照BERT的MLM任务中的约定, 每个batch数据中只有15%的token参与了训练, 被模型学习和预测, 所以BERT收敛的速度比left-to-right模型要慢很多(left-to-right模型中每一个token都会参与训练).
2 BERT的MLM任务
2.1 BERT的MLM任务中为什么采用了80%, 10%, 10%的策略?
-
首先, 如果所有参与训练的token被100%的[MASK], 那么在fine-tunning的时候所有单词都是已知的, 不存在[MASK], 那么模型就只能根据其他token的信息和语序结构来预测当前词, 而无法利用到这个词本身的信息, 因为它们从未出现在训练过程中, 等于模型从未接触到它们的信息, 等于整个语义空间损失了部分信息. 采用80%的概率下应用[MASK], 既可以让模型去学着预测这些单词, 又以20%的概率保留了语义信息展示给模型.
-
保留下来的信息如果全部使用原始token, 那么模型在预训练的时候可能会偷懒, 直接照抄当前token信息. 采用10%概率下random token来随机替换当前token, 会让模型不能去死记硬背当前的token, 而去尽力学习单词周边的语义表达和远距离的信息依赖, 尝试建模完整的语言信息.
-
最后再以10%的概率保留原始的token, 意义就是保留语言本来的面貌, 让信息不至于完全被遮掩, 使得模型可以"看清"真实的语言面貌.
3 BERT处理长文本的方法
首选要明确一点, BERT预训练模型所接收的最大sequence长度是512.
那么对于长文本(文本长度超过512的句子), 就需要特殊的方式来构造训练样本. 核心就是如何进行截断.
-
head-only方式: 这是只保留长文本头部信息的截断方式, 具体为保存前510个token (要留两个位置给[CLS]和[SEP]).
-
tail-only方式: 这是只保留长文本尾部信息的截断方式, 具体为保存最后510个token (要留两个位置给[CLS]和[SEP]).
-
head+only方式: 选择前128个token和最后382个token (文本总长度在800以内), 或者前256个token和最后254个token (文本总长度大于800).
三、BERT系列模型介绍
BERT系列模型
1 AlBERT模型
1.1 AlBERT模型的架构
-
AlBERT模型发布于ICLR 2020会议, 是基于BERT模型的重要改进版本. 是谷歌研究院和芝加哥大学共同发布的研究成果.
-
论文全称<< A Lite BERT For Self-Supervised Learning Of Language Representations >>.
-
从模型架构上看, AlBERT和BERT基本一致, 核心模块都是基于Transformer的强大特征提取能力.
-
在本篇论文中, 首先对比了过去几年预训练模型的主流操作思路.
-
第一: 大规模的语料.
-
第二: 更深的网络, 更多的参数.
-
第三: 多任务训练.
1.2 AlBERT模型的优化点
-
相比较于BERT模型, AlBERT的出发点即是希望降低预训练的难度, 同时提升模型关键能力. 主要引入了5大优化.
-
第一: 词嵌入参数的因式分解.
-
第二: 隐藏层之间的参数共享.
-
第三: 去掉NSP, 增加SOP预训练任务.
-
第四: 去掉dropout操作.
-
第五: MLM任务的优化.
-
第一: 词嵌入参数的因式分解.
-
AlBERT的作者认为, 词向量只记录了少量的词汇本身的信息, 更多的语义信息和句法信息包含在隐藏层中. 因此词嵌入的维度不一定非要和隐藏层的维度一致.
-
具体做法就是通过因式分解来降低嵌入矩阵的参数:
-
BERT: embedding_dim * vocab_size = hidden_size * vocab_size, 其中embedding_dim=768, vocab_size大约为30000左右的级别, 大约等于30000 * 768 = 23040000(2300万).
-
AlBERT: vocab_size * project + project * hidden_size, 其中project是因式分解的中间映射层维度, 一般取128, 参数总量大约等于30000 * 128 + 128 * 768 = 482304(48万).
-
第二: 隐藏层之间的参数共享.
-
在BERT模型中, 无论是12层的base, 还是24层的large模型, 其中每一个Encoder Block都拥有独立的参数模块, 包含多头注意力子层, 前馈全连接层. 非常重要的一点是, 这些层之间的参数都是独立的, 随着训练的进行都不一样了!
-
那么为了减少模型的参数量, 一个很直观的做法便是让这些层之间的参数共享, 本质上只有一套Encoder Block的参数!
-
在AlBERT模型中, 所有的多头注意力子层, 全连接层的参数都是分别共享的, 通过这样的方式, AlBERT属于Block的参数量在BERT的基础上, 分别下降到原来的1/12, 1/24.
-
第三: 去掉NSP, 增加SOP预训练任务.
-
BERT模型的成功很大程度上取决于两点, 一个是基础架构采用Transformer, 另一个就是精心设计的两大预训练任务, MLM和NSP. 但是BERT提出后不久, 便有研究人员对NSP任务提出质疑, 我们也可以反思一下NSP任务有什么问题?
-
在AlBERT模型中, 直接舍弃掉了NSP任务, 新提出了SOP任务(Sentence Order Prediction), 即两句话的顺序预测, 文本中正常语序的先后两句话[A, B]作为正样本, 则[B, A]作为负样本.
-
增加了SOP预训练任务后, 使得AlBERT拥有了更强大的语义理解能力和语序关系的预测能力.
-
第四: 去掉dropout操作.
-
原始论文中提到, 在AlBERT训练达到100万个batch_size时, 模型依然没有过拟合, 作者基于这个试验结果直接去掉了Dropout操作, 竟然意外的发现AlBERT对下游任务的效果有了进一步的提升. 这是NLP领域第一次发现dropout对大规模预训练模型会造成负面影响, 也使得AlBERT v2.0版本成为第一个不使用dropout操作而获得优异表现的主流预训练模型
-
第五: MLM任务的优化.
-
segments-pair的优化:
-
BERT为了加速训练, 前90%的steps使用了长度为128个token的短句子, 后10%的steps才使用长度为512个token的长句子.
-
AlBERT在90%的steps中使用了长度为512个token的长句子, 更长的句子可以提供更多上下文信息, 可以显著提升模型的能力.
-
-
Masked-Ngram-LM的优化:
-
BERT的MLM目标是随机mask掉15%的token来进行预测, 其中的token早已分好, 一个个算.
-
AlBERT预测的是Ngram片段, 每个片段长度为n (n=1,2,3), 每个Ngram片段的概率按照公式分别计算即可. 比如1-gram, 2-gram, 3-gram的概率分别为6/11, 3/11, 2/11.
-
-
AlBERT系列中包含一个albert-tiny模型, 隐藏层仅有4层, 参数量1.8M, 非常轻巧. 相比较BERT, 其训练和推理速度提升约10倍, 但精度基本保留, 语义相似度数据集LCQMC测试集达到85.4%, 相比于bert-base仅下降1.5%, 非常优秀.
2 RoBERTa模型
2.1 RoBERTa模型的架构
-
原始论文<< RoBERTa: A Robustly Optimized BERT Pretraining Approach >>, 由FaceBook和华盛顿大学联合于2019年提出的模型.
-
从模型架构上看, RoBERTa和BERT完全一致, 核心模块都是基于Transformer的强大特征提取能力. 改进点主要集中在一些训练细节上.
-
第1点: More data
-
第2点: Larger batch size
-
第3点: Training longer
-
第4点: No NSP
-
第5点: Dynamic masking
-
第6点: Byte level BPE
-
2.2 RoBERTa模型的优化点
-
针对于上面提到的7点细节, 一一展开说明:
-
第1点: More data (更大的数据量)
-
原始BERT的训练语料采用了16GB的文本数据.
-
RoBERTa采用了160GB的文本数据.
-
1: Books Corpus + English Wikipedia (16GB): BERT原文使用的之数据.
-
2: CC-News (76GB): 自CommonCrawl News数据中筛选后得到数据, 约含6300万篇新闻, 2016年9月-2019年2月.
-
3: OpenWebText (38GB): 该数据是借鉴GPT2, 从Reddit论坛中获取, 取点赞数大于3的内容.
-
4: Storie (31GB): 同样从CommonCrawl获取, 属于故事类数据, 而非新闻类.
-
-
-
第2点: Larger batch size (更大的batch size)
-
BERT采用的batch size等于256.
-
RoBERTa的训练在多种模式下采用了更大的batch size, 从256一直到最大的8000.
-
-
第3点: Training longer (更多的训练步数)
-
RoBERTa的训练采用了更多的训练步数, 让模型充分学习数据中的特征.
-
-
第4点: No NSP (去掉NSP任务)
-
从2019年开始, 已经有越来越多的证据表明NSP任务对于大型预训练模型是一个负面作用, 因此在RoBERTa中直接取消掉NSP任务.
-
论文作者进行了多组对照试验:
-
1: Segment + NSP (即BERT模式). 输入包含两部分, 每个部分是来自同一文档或者不同文档的segment(segment是连续的多个句子), 这两个segment的token总数少于512, 预训练包含MLM任务和NSP任务.
-
2: Sentence pair + NSP (使用两个连续的句子 + NSP, 并采用更大的batch size). 输入也是包含两部分, 每个部分是来自同一个文档或者不同文档的单个句子, 这两个句子的token 总数少于512. 由于这些输入明显少于512个tokens, 因此增加batch size的大小, 以使tokens总数保持与SEGMENT-PAIR + NSP相似, 预训练包含MLM任务和NSP任务.
-
3: Full-sentences (如果输入的最大长度为512, 那么尽量选择512长度的连续句子; 如果跨越document, 就在中间加上一个特殊分隔符, 比如[SEP]; 该试验没有NSP). 输入只有一部分(而不是两部分), 来自同一个文档或者不同文档的连续多个句子, token总数不超过512. 输入可能跨越文档边界, 如果跨文档, 则在上一个文档末尾添加文档边界token, 预训练不包含NSP任务.
-
4: Document-sentences (和情况3一样, 但是步跨越document; 该实验没有NSP). 输入只有一部分(而不是两部分), 输入的构造类似于Full-sentences, 只是不需要跨越文档边界, 其输入来自同一个文档的连续句子, token总数不超过512. 在文档末尾附近采样的输入可以短于512个tokens, 因此在这些情况下动态增加batch size大小以达到与Full-sentecens相同的tokens总数, 预训练不包含NSP任务.
-
-
-
总的来说, 实验结果表明1 < 2 < 3 < 4.
-
真实句子过短的话, 不如拼接成句子段.
-
没有NSP任务更优.
-
不跨越document更优.
-
-
第5点: Dynamic masking (采用动态masking策略)
-
原始静态mask: 即BERT版本的mask策略, 准备训练数据时, 每个样本只会进行一次随机mask(因此每个epoch都是重复的), 后续的每个训练步都采用相同的mask方式, 这是原始静态mask.
-
动态mask: 并没有在预处理的时候执行mask, 而是在每次向模型提供输入时动态生成mask, 所以到底哪些tokens被mask掉了是时刻变化的, 无法提前预知的.
-
-
第6点: Byte level BPE (采用字节级别的Encoding)
-
基于char-level: 原始BERT的方式, 在中文场景下就是处理一个个的汉字.
-
基于bytes-level: 与char-level的区别在于编码的粒度是bytes, 而不是unicode字符作为sub-word的基本单位.
-
-
当采用bytes-level的BPE之后, 词表大小从3万(原始BERT的char-level)增加到5万. 这分别为BERT-base和BERT-large增加了1500万和2000万额外的参数. 之前有研究表明, 这样的做法在有些下游任务上会导致轻微的性能下降. 但论文作者相信: 这种统一编码的优势会超过性能的轻微下降.
3 MacBert模型
3.2 MacBert模型的架构
-
MacBert模型由哈工大NLP实验室于2020年11月提出, 2021年5月发布应用, 是针对于BERT模型做了优化改良后的预训练模型.
-
<< Revisiting Pre-trained Models for Chinese Natural Language Processing >>, 通过原始论文题目也可以知道, MacBert是针对于中文场景下的BERT优化.
-
MacBert模型的架构和BERT大部分保持一致, 最大的变化有两点:
-
第一点: 对于MLM预训练任务, 采用了不同的MASK策略.
-
第二点: 删除了NSP任务, 替换成SOP任务.
-
3.3 MacBert模型的优化点
-
第一点: 对于MLM预训练任务, 采用了不同的MASK策略.
-
1: 使用了全词masked以及n-gram masked策略来选择tokens如何被遮掩, 从单个字符到4个字符的遮掩比例分别为40%, 30%, 20%, 10%
-
2: 原始BERT模型中的[MASK]出现在训练阶段, 但没有出现在微调阶段, 这会造成exposure bias的问题. 因此在MacBert中提出使用类似的单词来进行masked. 具体来说, 使用基于Word2Vec相似度计算包训练词向量, 后续利用这里面找近义词的功能来辅助mask, 比如以30%的概率选择了一个3-gram的单词进行masked, 则将在Word2Vec中寻找3-gram的近义词来替换, 在极少数情况下, 当没有符合条件的相似单词时, 策略会进行降级, 直接使用随机单词进行替换.
-
3: 使用15%的百分比对输入单词进行MASK, 其中80%的概率下执行策略2(即替换为相似单词), 10%的概率下替换为随机单词, 10%的概率下保留原始单词不变.
-
-
第二点: 删除了NSP任务, 替换成SOP任务.
-
第二点优化是直接借鉴了AlBERT模型中提出的SOP任务.
-
在NLP著名的难任务阅读理解中, MacBert展现出非常优秀的表现.
4 SpanBERT模型
4.1 SpanBERT模型的架构
-
论文的主要贡献有3点:
-
1: 提出了更好的Span Mask方案, 再次展示了随机遮掩连续一段tokens比随机遮掩单个token要好.
-
2: 通过加入了Span Boundary Objective(SBO)训练任务, 增强了BERT的性能, 特别在一些和Span适配的任务, 如抽取式问答.
-
3: 用实验数据获得了和XLNet一致的结果, 发现去除掉NSP任务, 直接用连续一长句训练效果更好.
-
-
SpanBERT的架构图如下:
-
架构图中可以清晰的展示论文的核心贡献点:
-
Span Masking
-
Span Boundary Objective
-
4.2 Span Masking
-
关于创新的MASK机制, 一般来说都是相对于原始BERT的基准进行改进. 对于BERT, 训练时会随机选取整句中的最小输入单元token来进行遮掩, 中文场景下本质上就是进行字级别的MASK. 但是这种方式会让本来应该有强相关的一些连在一起的字词, 在训练时被割裂开了.
-
那么首先想到的做法: 既然能遮掩字, 那么能不能直接遮掩整个词呢? 这就是BERT-WWM模型的思想.
原始输入: 使用语言模型来预测下一个词的概率. 原始BERT: 使用语言[MASK]型来[MASK]测下一个词的[MASK]率. BERT-WWM: 使用语言[MASK][MASK]来[MASK][MASK]下一个词的[MASK][MASK].
引申: 百度著名的ERNIE模型中, 直接引入命名实体(Named Entity)的外部知识, 进行整个实体的遮掩, 进行训练.
-
综合上面所说, 会更自然的想到, 既然整词的MASK, 那么如果拥有词的边界信息会不会让模型的能力更上一层楼呢? SpanBERT给出的是肯定的回答!!!
-
论文中关于span的选择, 走了这样一个流程:
-
第一步: 根据几何分布, 先随机选择一个span长度.
-
第二步: 再根据均匀分布随机选择这一段的起始位置.
-
第三步: 最后根据前两步的start和length直接进行MASK.
-
结论: 论文中详细论证了按照上述算法进行MASK, 随机被遮掩的文本平均长度等于3.8
4.3 Span Boundary Objective(SBO)
-
SBO任务是本篇论文最核心的创新点, 希望通过增加这个预训练任务, 可以让被遮掩的Span Boundary的词向量, 能够学习到Span内部的信息.
-
具体的做法: 在训练时取Span前后边界的两个词, 需要注意这两个词不在Span内, 然后用这两个词向量加上Span中被MASK掉的词的位置向量, 来预测原词.
-
更详细的操作如下, 即将词向量和位置向量进行拼接, 经过GeLU激活和LayerNorm处理, 连续经过两个全连接层, 得到最终的输出张量:
-
最后预测Span中原词的时候会得到一个损失, 这就是SBO任务的损失; 再将其和BERT自身的MLM任务的损失进行加和, 共同作为SpanBERT的目标损失函数进行训练:
4.4 NSP任务反思
-
为什么选择Single Sentence而不是BERT的Two Sentence?
-
1: 训练文本的长度更大, 可以学会长程依赖.
-
2: 对于NSP的负样本, 基于另一个主题文档的句子来预测单词, 会给MLM任务引入很大的噪声.
-
3: AlBERT模型已经给出了论证, 因为NSP任务太简单了.
-
四、ELMo模型介绍
1 ELMo简介
ELMo是2018年3月由华盛顿大学提出的一种预训练模型.
-
ELMo的全称是Embeddings from Language Models.
-
ELMo模型的提出源于论文<< Deep Contextualized Word Representations >>.
-
ELMo模型提出的动机源于研究人员认为一个好的预训练语言模型应该能够包含丰富的句法和语义信息, 并且能够对多义词进行建模. 而传统的词向量(2013年的word2vec, 2014年的GloVe)都是上下文无关的, 也就是固定的词向量. 最典型的例子就是"apple"在不同的语境下, 应该可以表示水果或公司, 但是固定的词向量显然无法做到这一点. 因此研究团队利用新的语言模型训练一个上下文相关的预训练模型, 成为ELMo, 并在6个NLP任务上获得提升.
2 ELMo的架构
2.1 总体架构
从上面的架构图中可以看到, 宏观上ELMo分三个主要模块.
-
最底层黄色标记的Embedding模块.
-
中间层蓝色标记的两部分双层LSTM模块.
-
最上层绿色标记的词向量表征模块.
2.2 Embedding模块
ELMo最底层的词嵌入采用CNN对字符级进行编码, 本质就是获得一个静态的词嵌入向量作为网络的底层输入.
2.3 两部分的双层LSTM模块
-
这是整个ELMo中最重要的部分, 架构中分成左侧的前向LSTM网络, 和右侧的反向LSTM网络.
-
ELMo的做法是我们只预训练一个Language Model, 而word embedding是通过输入的句子实时给出的, 这样单词的嵌入向量就包含了上下文的信息, 也就彻底改变了Word2Vec和GloVe的静态词向量的做法.
ELMo的这一模块分为左右两部分, 本质上就是一个双向LM, 对于左半部分, 给定了N个tokens(t1, t2, ..., tN), Language Model通过前面k-1个位置的token序列来计算第k个token出现的概率, 构成前向双层LSTM模型.
同理, 对于架构中的右半部分, 给定了N个tokens(t(k+1), t(k+2), ..., t(N)), Language Model通过后面N-k个位置的token序列来计算第k个token出现的概率, 构成后向双层LSTM模型.
ELMo在训练过程中的目标函数就是最大化下面的公式:
2.4 词向量表征模块
因为ELMo是个语言模型, 对于每个token, 通过一个L层的双向LSTM网络可以计算出2L+1个表示向量如下:
从上面的公式可以清楚的看到, 有3个不同的组成部分, 第一个就是对token直接进行CNN编码的结果, 也是ELMo最底层模块的输出; 第二个就是前向LSTM的输出结果, 每一层都会有一个输出, 总共L层就会有L个输出; 第三个就是后向LSTM的输出结果, 每一层都会有一个输出, 总共L层就会有L个输出; 综合三部分的输出加在一起, 就是2L+1个输出向量.
通过整个网络, 每一个token得到了2L+1个表示向量, 但是我们希望每一个token能对应一个向量. 最简单的做法就是取最上层的输出结果作为token的表示向量, 更通用的做法是加入若干参数来融合所有层的信息, 如下所示:
上式的意思是对于2L+1个向量, 每一个前面都加上一个权重稀疏, 然后直接融合成一个向量, 最后再乘一个系数作为最终该token的词向量.
原始论文中提到最前面的那个系数, 在不同任务中取不同的值效果会有较大的差异, 需要注意在SQuAD中设置为0.01取得的效果要好于设置为1.
原始论文中在进行底层token编码时, 用CNN形成了一个512维的列向量, 也就是初始嵌入维度等于512. 中间层使用了双层的LSTM分别进行前向编码和后向编码, 每层的单个LSTM输入维度是512, 输出维度也是512, 保持一致. 因为是双向编码并且分左右两部分, 所以每层的输出维度是512*2=1024, 最后进行权重融合后的向量维度就是1024.
3 ELMo的预训练任务
3.1 ELMo的本质思想
-
首先用一个语言模型学好一个单词的word embedding, 此时是无法区分多义词的, 但没关系. 当实际使用word embedding的时候, 该单词已经具备了特定的上下文信息, 这个时候可以根据上下文单词的语义去调整单词的word embedding表示, 这样经过调整后得到的word embedding向量就可以准确的表达单词在当前上下文中的真实含义了, 也就自然的解决了多义词问题.
-
结论就是ELMo模型是个根据当前上下文对word embedding动态调整的语言模型.
3.2 ELMo的预训练采用了典型的两阶段过程
-
第一阶段: 利用语言模型进行预训练.
-
第二阶段: 在做下游任务时, 从预训练网络中提取对应单词的网络各层的word embedding作为新特征补充到下游任务中.
-
第一阶段: 语言模型预训练.
-
再次回到ELMo的总体架构图, 网络结构采用了双层双向LSTM.
目前语言模型训练的任务目标是根据单词Wi的上下文去正确预测单词Wi, Wi之前的单词序列context-before称为上文, Wi之后的单词序列context-after称为下文.
架构图上左侧的前向双层LSTM代表正方向编码器, 输入的是从左向右顺序的除了预测单词Wi之外的上文context-before; 右侧的反向双层LSTM代表反方向编码器, 输入的是从右向左的逆序的下文context-after;
每个编码器的深度都是L=2, 即双层LSTM叠加.
使用上述的网络结构利用大量语料做语言模型任务就能预训练好这个网络. 当输入一个新句子S_new时, 句子中每个单词都能得到对应的3个embedding向量: 1-最底层的单词的word embedding. 2-中间第一层双向LSTM中对应单词位置的embedding, 这层编码对应单词的句法信息更多一些. 3-中间第二层双向LSTM中对应单词位置的embedding, 这层编码对应单词的语义信息更多一些.
ELMo的预训练过程不仅仅学会了单词的word embedding, 还学习了一个双层双向的LSTM网络, 这两者后续都会用到, 是整个ELMo预训练的两大产出结果.
-
第二阶段: 下游任务的调整.
-
比如我们的下游任务是QA问题.
对于问句X, 可以先将句子X作为预训练好的ELMo网络的输入, 这样X中每个单词在ELMo中都能获得3个对应的embedding向量. 之后赋给这3个向量各自一个权重a, 这个权重a既可以是学习得来的也可以是最简单的平均分布赋值, 然后把3个向量加权求和, 整个成一个词向量. 最后将整合后的词向量作为X在自己任务的那个网络结构中对应单词的输入, 以此作为新特征补充进下游任务中. 对于回答Y可以同样处理.
因为ELMo给下游提供的是每个单词的特征形式, 所以这一类预训练方法被称为"Feature-based Pre-Training".
4 ELMo模型的效果
ELMo对于多义词问题的解决结果:
前面提到静态的word embedding无法解决多义词的问题, 那么ELMo引入上下文动态语义调整后的embedding word可以解决多义词问题吗? 答案正如上图所示, 而且比我们期待的解决效果要更好.
上图中的例子, 对于GloVe训练出来的word embedding来说, 多义词比如play, 根据它的embedding找出最接近其语义的单词, 发现结果集合几乎全部都在体育领域, 这很明显是因为训练数据中包含play的语句中体育领域的数量明显占多数导致的.
再来看使用ELMo后的效果, 根据上下文动态调整后的embedding word不仅仅能找出对应于"play":"演出"的相同语义的句子, 而且还可以保证找出的句子中的play对应的词性也是相同的, 这真的是超出期待之外的惊喜!
原始论文中提到ELMo的试验效果, 在6个NLP主流任务中性能都有不同幅度的提升, 最高的提升达到25%, 任务的覆盖范围很广, 包含句子语义关系判断, 分类任务, 阅读理解等等.
5 ELMo的待改进点
ELMo在传统静态word embedding方法(Word2Vec, GloVe)的基础上提升了很多, 但是依然存在缺陷, 有很大的改进余地.
-
第一点: 一个很明显的缺点在于特征提取器的选择上, ELMo使用了双向双层LSTM, 而不是现在横扫千军的Transformer, 在特征提取能力上肯定是要弱一些的. 设想如果ELMo的提升提取器选用Transformer, 那么后来的BERT的反响将远不如当时那么火爆了.
-
第二点: ELMo选用双向拼接的方式进行特征融合, 这种方法肯定不如BERT一体化的双向提取特征好.
五、GPT模型介绍
1 GPT介绍
-
GPT是OpenAI公司提出的一种语言预训练模型.
-
OpenAI在论文<< Improving Language Understanding by Generative Pre-Training >>中提出GPT模型.
-
OpenAI后续又在论文<< Language Models are Unsupervised Multitask Learners >>中提出GPT2模型.
-
GPT和GPT2模型结构差别不大, 但是GPT2采用了更大的数据集进行训练.
-
OpenAI GPT模型是在Google BERT模型之前提出的, 与BERT最大的区别在于GPT采用了传统的语言模型方法进行预训练, 即使用单词的上文来预测单词, 而BERT是采用了双向上下文的信息共同来预测单词.
-
正是因为训练方法上的区别, 使得GPT更擅长处理自然语言生成任务(NLG), 而BERT更擅长处理自然语言理解任务(NLU).
2 GPT的架构
-
看三个语言模型的对比架构图, 中间的就是GPT:
从上图可以很清楚的看到GPT采用的是单向Transformer模型, 例如给定一个句子[u1, u2, ..., un], GPT在预测单词ui的时候只会利用[u1, u2, ..., u(i-1)]的信息, 而BERT会同时利用上下文的信息[u1, u2, ..., u(i-1), u(i+1), ..., un].
作为两大模型的直接对比, BERT采用了Transformer的Encoder模块, 而GPT采用了Transformer的Decoder模块. 并且GPT的Decoder Block和经典Transformer Decoder Block还有所不同, 如下图所示:
如上图所示, 经典的Transformer Decoder Block包含3个子层, 分别是Masked Multi-Head Attention层, encoder-decoder attention层, 以及Feed Forward层. 但是在GPT中取消了第二个encoder-decoder attention子层, 只保留Masked Multi-Head Attention层, 和Feed Forward层.
作为单向Transformer Decoder模型, GPT利用句子序列信息预测下一个单词的时候, 要使用Masked Multi-Head Attention对单词的下文进行遮掩(look ahead mask), 来防止未来信息的提前泄露. 例如给定一个句子包含4个单词[A, B, C, D], GPT需要用[A]预测B, 用[A, B]预测C, 用[A, B, C]预测D. 很显然的就是当要预测B时, 需要将[B, C, D]遮掩起来.
具体的遮掩操作是在slef-attention进行softmax之前进行的, 一般的实现是将MASK的位置用一个无穷小的数值-inf来替换, 替换后执行softmax计算得到新的结果矩阵. 这样-inf的位置就变成了0. 如上图所示, 最后的矩阵可以很方便的做到当利用A预测B的时候, 只能看到A的信息; 当利用[A, B]预测C的时候, 只能看到A, B的信息.
注意: 对比于经典的Transformer架构, 解码器模块采用了6个Decoder Block; GPT的架构中采用了12个Decoder Block.
3 GPT训练过程
GPT的训练也是典型的两阶段过程:
-
第一阶段: 无监督的预训练语言模型.
-
第二阶段: 有监督的下游任务fine-tunning.
3.1 无监督的预训练语言模型
给定句子U = [u1, u2, ..., un], GPT训练语言模型时的目标是最大化下面的似然函数:
有上述公式可知, GPT是一个单向语言模型, 假设输入张量用h0表示, 则计算公式如下:
其中Wp是单词的位置编码, We是单词本身的word embedding. Wp的形状是[max_seq_len, embedding_dim], We的形状是[vocab_size, embedding_dim].
得到输入张量h0后, 要将h0传入GPT的Decoder Block中, 依次得到ht:
最后通过得到的ht来预测下一个单词:
3.2 有监督的下游任务fine-tunning
GPT经过预训练后, 会针对具体的下游任务对模型进行微调. 微调采用的是有监督学习, 训练样本包括单词序列[x1, x2, ..., xn]和label y. GPT微调的目标任务是根据单词序列[x1, x2, ..., xn]预测标签y.
其中WyWy表示预测输出的矩阵参数, 微调任务的目标是最大化下面的函数:
综合两个阶段的目标任务函数, 可知GPT的最终优化函数为:
六、BERT GPT ELMo模型的对比
1 BERT, GPT, ELMo之间的不同点
-
关于特征提取器:
-
ELMo采用两部分双层双向LSTM进行特征提取, 然后再进行特征拼接来融合语义信息.
-
GPT和BERT采用Transformer进行特征提取.
-
很多NLP任务表明Transformer的特征提取能力强于LSTM, 对于ELMo而言, 采用1层静态token embedding + 2层LSTM, 提取特征的能力有限.
-
-
单/双向语言模型:
-
三者之中, 只有GPT采用单向语言模型, 而ELMo和BERT都采用双向语言模型.
-
ELMo虽然被认为采用了双向语言模型, 但实际上是左右两个单向语言模型分别提取特征, 然后进行特征拼接, 这种融合特征的能力比BERT一体化的融合特征方式弱.
-
三者之中, 只有ELMo没有采用Transformer. GPT和BERT都源于Transformer架构, GPT的单向语言模型采用了经过修改后的Decoder模块, Decoder采用了look-ahead mask, 只能看到context before上文信息, 未来的信息都被mask掉了. 而BERT的双向语言模型采用了Encoder模块, Encoder只采用了padding mask, 可以同时看到context before上文信息, 以及context after下文信息.
-
2 BERT, GPT, ELMo各自的优点和缺点
-
ELMo:
-
优点:
-
从早期的Word2Vec预训练模型的最大缺点出发, 进行改进, 这一缺点就是无法解决多义词的问题.
-
ELMo根据上下文动态调整word embedding, 可以解决多义词的问题.
-
-
缺点:
-
ELMo使用LSTM提取特征的能力弱于Transformer.
-
ELMo使用向量拼接的方式融合上下文特征的能力弱于Transformer.
-
-
GPT:
-
优点:
-
GPT使用了Transformer提取特征, 使得模型能力大幅提升.
-
-
缺点:
-
GPT只使用了单向Decoder, 无法融合未来的信息.
-
-
BERT:
-
优点:
-
BERT使用了双向Transformer提取特征, 使得模型能力大幅提升.
-
添加了两个预训练任务, MLM + NSP的多任务方式进行模型预训练.
-
-
缺点:
-
模型过于庞大, 参数量太多, 需要的数据和算力要求过高, 训练好的模型应用场景要求高.
-
更适合用于语言嵌入表达, 语言理解方面的任务, 不适合用于生成式的任务.
-