- 什么是 BERT
BERT 的全称是 Bidirectional Encoder Representation from Transformers,是 Google2018 年提出的预训练模型,即双向 Transformer 的 Encoder,因为 decoder 是不能获要预测的信息的。模型的主要创新点都在 pre-train 方法上,即用了 Masked LM 和 Next Sentence Prediction 两种方法分别捕捉词语和句子级别的 representation。
Bert 最近很火,应该是最近最火爆的 AI 进展,网上的评价很高,那么 Bert 值得这么高的评价吗?我个人判断是值得。那为什么会有这么高的评价呢?是因为它有重大的理论或者模型创新吗?其实并没有,从模型创新角度看一般,创新不算大。但是架不住效果太好了,基本刷新了很多 NLP 的任务的最好性能,有些任务还被刷爆了,这个才是关键。另外一点是 Bert 具备广泛的通用性,就是说绝大部分 NLP 任务都可以采用类似的两阶段模式直接去提升效果,这个第二关键。客观的说,把 Bert 当做最近两年 NLP 重大进展的集大成者更符合事实。
- 从 Word Embedding 到 Bert 模型的发展
2.1 图像的预训练
自从深度学习火起来后,预训练过程就是做图像或者视频领域的一种比较常规的做法,有比较长的历史了,而且这种做法很有效,能明显促进应用的效果。
那么图像领域怎么做预训练呢,上图展示了这个过程,
我们设计好网络结构以后,对于图像来说一般是 CNN 的多层叠加网络结构,可以先用某个训练集合比如训练集合 A 或者训练集合 B 对这个网络进行预先训练,在 A 任务上或者 B 任务上学会网络参数,然后存起来以备后用。
假设我们面临第三个任务 C,网络结构采取相同的网络结构,在比较浅的几层 CNN 结构,网络参数初始化的时候可以加载 A 任务或者 B 任务学习好的参数,其它 CNN 高层参数仍然随机初始化。
之后我们用 C 任务的训练数据来训练网络,此时有两种做法:
一种是浅层加载的参数在训练 C 任务过程中不动,这种方法被称为 “Frozen”;
另一种是底层网络参数尽管被初始化了,在 C 任务训练过程中仍然随着训练的进程不断改变,这种一般叫 “Fine-Tuning”,顾名思义,就是更好地把参数进行调整使得更适应当前的 C 任务。
一般图像或者视频领域要做预训练一般都这么做。这样做的优点是:如果手头任务 C 的训练集合数据量较少的话,利用预训练出来的参数来训练任务 C,加个预训练过程也能极大加快任务训练的收敛速度,所以这种预训练方式是老少皆宜的解决方案,另外疗效又好,所以在做图像处理领域很快就流行开来。
为什么预训练可行
对于层级的 CNN 结构来说,不同层级的神经元学习到了不同类型的图像特征,由底向上特征形成层级结构,所以预训练好的网络参数,尤其是底层的网络参数抽取出特征跟具体任务越无关,越具备任务的通用性,所以这是为何一般用底层预训练好的参数初始化新任务网络参数的原因。而高层特征跟任务关联较大,实际可以不用使用,或者采用 Fine-tuning 用新数据集合清洗掉高层无关的特征抽取器。
2.2 Word Embedding
神经网络语言模型 (NNLM) 的思路。先说训练过程。学习任务是输入某个句中单词
前面句子的 t-1 个单词,要求网络正确预测单词 Bert,即最大化:
前面任意单词
用 Onehot 编码(比如:0001000)作为原始单词输入,之后乘以矩阵 Q 后获得向量
,每个单词的
拼接,上接隐层,然后接 softmax 去预测后面应该后续接哪个单词。这个
是什么?这其实就是单词对应的 Word Embedding 值,那个矩阵 Q 包含 V 行,V 代表词典大小,每一行内容代表对应单词的 Word embedding 值。只不过 Q 的内容也是网络参数,需要学习获得,训练刚开始用随机值初始化矩阵 Q,当这个网络训练好之后,矩阵 Q 的内容被正确赋值,每一行代表一个单词对应的 Word embedding 值。所以你看,通过这个网络学习语言模型任务,这个网络不仅自己能够根据上文预测后接单词是什么,同时获得一个副产品,就是那个矩阵 Q,这就是单词的 Word Embedding。
2013 年最火的用语言模型做 Word Embedding 的工具是 Word2Vec,后来又出了 Glove,Word2Vec。对于这两个模型不熟悉的可以参考我之前的文章,这里不再赘述:
上面这种模型做法就是 18 年之前 NLP 领域里面采用预训练的典型做法,之前说过,Word Embedding 其实对于很多下游 NLP 任务是有帮助的,只是帮助没有大到闪瞎忘记戴墨镜的围观群众的双眼而已。那么新问题来了,为什么这样训练及使用 Word Embedding 的效果没有期待中那么好呢?答案很简单,因为 Word Embedding 有问题呗。这貌似是个比较弱智的答案,关键是 Word Embedding 存在什么问题?这其实是个好问题。
这片在 Word Embedding 头上笼罩了好几年的乌云是什么?是多义词问题。 我们知道,多义词是自然语言中经常出现的现象,也是语言灵活性和高效性的一种体现。多义词对 Word Embedding 来说有什么负面影响?如上图所示,比如多义词 Bank,有两个常用含义,但是 Word Embedding 在对 bank 这个单词进行编码的时候,是区分不开这两个含义的,因为它们尽管上下文环境中出现的单词不同,但是在用语言模型训练的时候,不论什么上下文的句子经过 word2vec,都是预测相同的单词 bank,而同一个单词占的是同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的 word embedding 空间里去。所以 word embedding 无法区分多义词的不同语义,这就是它的一个比较严重的问题。
有没有简单优美的解决方案呢?ELMO 提供了一种简洁优雅的解决方案。
2.3 ELMO
ELMO 是 “Embedding from Language Models” 的简称,其实这个名字并没有反应它的本质思想,提出 ELMO 的论文题目:“Deep contextualized word representation”更能体现其精髓,而精髓在哪里?在 deep contextualized 这个短语,一个是 deep,一个是 context,其中 context 更关键。
在此之前的 Word Embedding 本质上是个静态的方式,所谓静态指的是训练好之后每个单词的表达就固定住了,以后使用的时候,不论新句子上下文单词是什么,这个单词的 Word Embedding 不会跟着上下文场景的变化而改变,所以对于比如 Bank 这个词,它事先学好的 Word Embedding 中混合了几种语义 ,在应用中来了个新句子,即使从上下文中(比如句子包含 money 等词)明显可以看出它代表的是 “银行” 的含义,但是对应的 Word Embedding 内容也不会变,它还是混合了多种语义。这是为何说它是静态的,这也是问题所在。
ELMO 的本质思想是:我事先用语言模型学好一个单词的 Word Embedding,此时多义词无法区分,不过这没关系。在我实际使用 Word Embedding 的时候,单词已经具备了特定的上下文了,这个时候我可以根据上下文单词的语义去调整单词的 Word Embedding 表示,这样经过调整后的 Word Embedding 更能表达在这个上下文中的具体含义,自然也就解决了多义词的问题了。所以 ELMO 本身是个根据当前上下文对 Word Embedding 动态调整的思路。
ELMO 采用了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的 Word Embedding 作为新特征补充到下游任务中。
上图展示的是其预训练过程,它的网络结构采用了双层双向 LSTM,目前语言模型训练的任务目标是根据单词
的上下文去正确预测单词
,
之前的单词序列 Context-before 称为上文,之后的单词序列 Context-after 称为下文。
图中左端的前向双层 LSTM 代表正方向编码器,输入的是从左到右顺序的除了预测单词外
的上文 Context-before;右端的逆向双层 LSTM 代表反方向编码器,输入的是从右到左的逆序的句子下文 Context-after;每个编码器的深度都是两层 LSTM 叠加。
这个网络结构其实在 NLP 中是很常用的。使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子
,句子中每个单词都能得到对应的三个 Embedding:
- 最底层是单词的 Word Embedding;
- 往上走是第一层双向 LSTM 中对应单词位置的 Embedding,这层编码单词的句法信息更多一些;
- 再往上走是第二层 LSTM 中对应单词位置的 Embedding,这层编码单词的语义信息更多一些。
也就是说,ELMO 的预训练过程不仅仅学会单词的 Word Embedding,还学会了一个双层双向的 LSTM 网络结构,而这两者后面都有用。
上面介绍的是 ELMO 的第一阶段:预训练阶段。那么预训练好网络结构后,如何给下游任务使用呢?上图展示了下游任务的使用过程,比如我们的下游任务仍然是 QA 问题:
- 此时对于问句 X,我们可以先将句子 X 作为预训练好的 ELMO 网络的输入,这样句子 X 中每个单词在 ELMO 网络中都能获得对应的三个 Embedding;
- 之后给予这三个 Embedding 中的每一个 Embedding 一个权重 a,这个权重可以学习得来,根据各自权重累加求和,将三个 Embedding 整合成一个;
- 然后将整合后的这个 Embedding 作为 X 句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于上图所示下游任务 QA 中的回答句子 Y 来说也是如此处理。
因为 ELMO 给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为 “Feature-based Pre-Training”。
前面我们提到静态 Word Embedding 无法解决多义词的问题,那么 ELMO 引入上下文动态调整单词的 embedding 后多义词问题解决了吗?解决了,而且比我们期待的解决得还要好。对于 Glove 训练出的 Word Embedding 来说,多义词比如 play,根据它的 embedding 找出的最接近的其它单词大多数集中在体育领域,这很明显是因为训练数据中包含 play 的句子中体育领域的数量明显占优导致;而使用 ELMO,根据上下文动态调整后的 embedding 不仅能够找出对应的 “演出” 的相同语义的句子,而且还可以保证找出的句子中的 play 对应的词性也是相同的,这是超出期待之处。之所以会这样,是因为我们上面提到过,第一层 LSTM 编码了很多句法信息,这在这里起到了重要作用。
ELMO 有什么值得改进的缺点呢?
- 首先,一个非常明显的缺点在特征抽取器选择方面,ELMO 使用了 LSTM 而不是新贵 Transformer,Transformer 是谷歌在 17 年做机器翻译任务的 “Attention is all you need” 的论文中提出的,引起了相当大的反响,很多研究已经证明了 Transformer 提取特征的能力是要远强于 LSTM 的。如果 ELMO 采取 Transformer 作为特征提取器,那么估计 Bert 的反响远不如现在的这种火爆场面。
- 另外一点,ELMO 采取双向拼接这种融合特征的能力可能比 Bert 一体化的融合特征方式弱,但是,这只是一种从道理推断产生的怀疑,目前并没有具体实验说明这一点。
2.4 GPT
GPT 是 “Generative Pre-Training” 的简称,从名字看其含义是指的生成式的预训练。GPT 也采用两阶段过程,第一个阶段是利用语言模型进行预训练,第二阶段通过 Fine-tuning 的模式解决下游任务。
上图展示了 GPT 的预训练过程,其实和 ELMO 是类似的,主要不同在于两点:
- 首先,特征抽取器不是用的 RNN,而是用的 Transformer,上面提到过它的特征抽取能力要强于 RNN,这个选择很明显是很明智的;
- 其次,GPT 的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,所谓 “单向” 的含义是指:语言模型训练的任务目标是根据 单词的上下文去正确预测单词 , 之前的单词序列 Context-before 称为上文,之后的单词序列 Context-after 称为下文。
如果对 Transformer 模型不太了解的,可以参考我写的文章:Transformer
ELMO 在做语言模型预训练的时候,预测单词
同时使用了上文和下文,而 GPT 则只采用 Context-before 这个单词的上文来进行预测,而抛开了下文。这个选择现在看不是个太好的选择,原因很简单,它没有把单词的下文融合进来,这限制了其在更多应用场景的效果,比如阅读理解这种任务,在做任务的时候是可以允许同时看到上文和下文一起做决策的。如果预训练时候不把单词的下文嵌入到 Word Embedding 中,是很吃亏的,白白丢掉了很多信息。
2.5 BERT
Bert 采用和 GPT 完全相同的两阶段模型,首先是语言模型预训练;其次是使用 Fine-Tuning 模式解决下游任务。和 GPT 的最主要不同在于在预训练阶段采用了类似 ELMO 的双向语言模型,即双向的 Transformer,当然另外一点是语言模型的数据规模要比 GPT 大。所以这里 Bert 的预训练过程不必多讲了。模型结构如下:
对比 OpenAI GPT(Generative pre-trained transformer),BERT 是双向的 Transformer block 连接;就像单向 rnn 和双向 rnn 的区别,直觉上来讲效果会好一些。
对比 ELMo,虽然都是 “双向”,但目标函数其实是不同的。ELMo 是分别以
和
作为目标函数,独立训练处两个 representation 然后拼接,而 BERT 则是以
作为目标函数训练 LM。
BERT 预训练模型分为以下三个步骤:Embedding、Masked LM、Next Sentence Prediction
2.5.1 Embedding
这里的 Embedding 由三种 Embedding 求和而成:
- Token Embeddings 是词向量,第一个单词是 CLS 标志,可以用于之后的分类任务
- Segment Embeddings 用来区别两种句子,因为预训练不光做 LM 还要做以两个句子为输入的分类任务
- Position Embeddings 和之前文章中的 Transformer 不一样,不是三角函数而是学习出来的
2.5.2 Masked LM
MLM 可以理解为完形填空,作者会随机 mask 每一个句子中 15% 的词,用其上下文来做预测,例如:my dog is hairy → my dog is [MASK]
此处将 hairy 进行了 mask 处理,然后采用非监督学习的方法预测 mask 位置的词是什么,但是该方法有一个问题,因为是 mask15% 的词,其数量已经很高了,这样就会导致某些词在 fine-tuning 阶段从未见过,为了解决这个问题,作者做了如下的处理:
80% 是采用 [mask],my dog is hairy → my dog is [MASK]
10% 是随机取一个词来代替 mask 的词,my dog is hairy -> my dog is apple
10% 保持不变,my dog is hairy -> my dog is hairy
注意:这里的 10% 是 15% 需要 mask 中的 10%
那么为啥要以一定的概率使用随机词呢?这是因为 transformer 要保持对每个输入 token 分布式的表征,否则 Transformer 很可能会记住这个 [MASK] 就是 “hairy”。至于使用随机词带来的负面影响,文章中解释说, 所有其他的 token(即非 “hairy” 的 token)共享 15%*10% = 1.5% 的概率,其影响是可以忽略不计的。Transformer 全局的可视,又增加了信息的获取,但是不让模型获取全量信息。
2.5.3 Next Sentence Prediction
选择一些句子对 A 与 B,其中 50% 的数据 B 是 A 的下一条句子,剩余 50% 的数据 B 是语料库中随机选择的,学习其中的相关性,添加这样的预训练的目的是目前很多 NLP 的任务比如 QA 和 NLI 都需要理解两个句子之间的关系,从而能让预训练的模型更好的适应这样的任务。 个人理解:
- Bert 先是用 Mask 来提高视野范围的信息获取量,增加 duplicate 再随机 Mask,这样跟 RNN 类方法依次训练预测没什么区别了除了 mask 不同位置外;
- 全局视野极大地降低了学习的难度,然后再用 A+B/C 来作为样本,这样每条样本都有 50% 的概率看到一半左右的噪声;
- 但直接学习 Mask A+B/C 是没法学习的,因为不知道哪些是噪声,所以又加上 next_sentence 预测任务,与 MLM 同时进行训练,这样用 next 来辅助模型对噪声 / 非噪声的辨识,用 MLM 来完成语义的大部分的学习。
- BERT 的评价
总结下 BERT 的主要贡献:
- 引入了 Masked LM,使用双向 LM 做模型预训练。
- 为预训练引入了新目标 NSP,它可以学习句子与句子间的关系。
- 进一步验证了更大的模型效果更好: 12 —> 24 层。
- 为下游任务引入了很通用的求解框架,不再为任务做模型定制。
- 刷新了多项 NLP 任务的记录,引爆了 NLP 无监督预训练技术。
BERT 优点
- Transformer Encoder 因为有 Self-attention 机制,因此 BERT 自带双向功能。
- 因为双向功能以及多层 Self-attention 机制的影响,使得 BERT 必须使用 Cloze 版的语言模型 Masked-LM 来完成 token 级别的预训练。
- 为了获取比词更高级别的句子级别的语义表征,BERT 加入了 Next Sentence Prediction 来和 Masked-LM 一起做联合训练。
- 为了适配多任务下的迁移学习,BERT 设计了更通用的输入层和输出层。
- 微调成本小。
BERT 缺点
- task1 的随机遮挡策略略显粗犷,推荐阅读《Data Nosing As Smoothing In Neural Network Language Models》。
- [MASK]标记在实际预测中不会出现,训练时用过多 [MASK] 影响模型表现。每个 batch 只有 15% 的 token 被预测,所以 BERT 收敛得比 left-to-right 模型要慢(它们会预测每个 token)。
- BERT 对硬件资源的消耗巨大(大模型需要 16 个 tpu,历时四天;更大的模型需要 64 个 tpu,历时四天。
评价
Bert 是 NLP 里里程碑式的工作,对于后面 NLP 的研究和工业应用会产生长久的影响,这点毫无疑问。但是从上文介绍也可以看出,从模型或者方法角度看,Bert 借鉴了 ELMO,GPT 及 CBOW,主要提出了 Masked 语言模型及 Next Sentence Prediction,但是这里 Next Sentence Prediction 基本不影响大局,而 Masked LM 明显借鉴了 CBOW 的思想。所以说 Bert 的模型没什么大的创新,更像最近几年 NLP 重要进展的集大成者,这点如果你看懂了上文估计也没有太大异议,如果你有大的异议,杠精这个大帽子我随时准备戴给你。如果归纳一下这些进展就是:
- 首先是两阶段模型,第一阶段双向语言模型预训练,这里注意要用双向而不是单向,第二阶段采用具体任务 Fine-tuning 或者做特征集成;
- 第二是特征抽取要用 Transformer 作为特征提取器而不是 RNN 或者 CNN;
- 第三,双向语言模型可以采取 CBOW 的方法去做(当然我觉得这个是个细节问题,不算太关键,前两个因素比较关键)。
Bert 最大的亮点在于效果好及普适性强,几乎所有 NLP 任务都可以套用 Bert 这种两阶段解决思路,而且效果应该会有明显提升。可以预见的是,未来一段时间在 NLP 应用领域,Transformer 将占据主导地位,而且这种两阶段预训练方法也会主导各种应用。
- 代码实现
- 参考文献
作者:@mantchs
GitHub:github.com/NLP-LOVE/ML…