原文:The Illustrated BERT, ELMo, and co. (How NLP Cracked Transfer Learning)
作者:Jay Alammar
原文连接: http://jalammar.github.io/illustrated-bert/ BERT论文地址:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding https://arxiv.org/abs/1810.04805

本章节主要概要

  • 词潜入历史发展(word2vec,glove->elmo->…bert)
  • BERT架构以及源码分析
  • 联系方式,你的问题?

目录

  • 前言
  • 示例:BERT句子分类模型结构
  • 模型架构
  • 模型输入
  • 模型输出
  • BERT VS卷积神经网络
  • 词嵌入历史发展
  • Word Embedding Recap
  • word2vec
  • glove
  • ELMo
  • ELMo 前沿
  • ELMo 详细解读
  • ElMO不足之处
  • ULM-FiT:NLP领域应用迁移学习
  • The Transformer:超越LSTM的结构
  • OpenAI Transformer:用于语言模型的Transformer解码器预训练
  • Transfer Learning to Downstream Tasks
  • BERT: From Decoders to Encoders
  • Masked Language Model
  • Two-sentence Tasks
  • 特殊NLP任务
  • BERT用做特征提取
  • BERT源码分析
  • **tensorflow版本 **[BERT](https://github.com/google-research/bert)**代码**
  • **pytorch 版本 **[BERT ](https://github.com/huggingface/transformers)**代码 **

  • GLUE benchmark
  • 留言板

前言

2018年可谓是自然语言处理(NLP)的元年,在我们如何以最能捕捉潜在语义关系的方式 来辅助计算机对的句子概念性的理解 这方面取得了极大的发展进步。此外, NLP领域的一些开源社区已经发布了很多强大的组件,我们可以在自己的模型训练过程中免费的下载使用。(可以说今年是NLP的ImageNet时刻,因为这和几年前计算机视觉的发展很相似)

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型

上图中,最新发布的BERT是一个NLP任务的里程碑式模型,它的发布势必会带来一个NLP的新时代。BERT是一个算法模型,它的出现打破了大量的自然语言处理任务的记录。在BERT的论文发布不久后,Google的研发团队还开放了该模型的代码,并提供了一些在大量数据集上预训练好的算法模型下载方式。Goole开源这个模型,并提供预训练好的模型,这使得所有人都可以通过它来构建一个涉及NLP的算法模型,节约了大量训练语言模型所需的时间,精力,知识和资源。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._nlp_02

BERT集成了最近一段时间内NLP领域中的一些顶尖的思想,包括但不限于 Semi-supervised Sequence Learning (by Andrew Dai and Quoc Le), ELMo (by Matthew Peters and researchers from AI2 and UW CSE), ULMFiT (by fast.ai founder Jeremy Howard and Sebastian Ruder), and the OpenAI transformer (by OpenAI researchers Radford, Narasimhan, Salimans, and Sutskever), and the Transformer (Vaswani et al).。

你需要注意一些事情才能恰当的理解BERT的内容,不过,在介绍模型涉及的概念之前可以使用BERT的方法。

示例:BERT句子分类模型结构

使用BERT最简单的方法就是做一个文本分类模型,这样的模型结构如下图所示:

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_03

为了训练一个这样的模型,(主要是训练一个分类器),在训练阶段BERT模型发生的变化很小。该训练过程称为微调,并且源于 Semi-supervised Sequence Learning 和 ULMFiT.。

为了更方便理解,我们下面举一个分类器的例子。分类器是属于监督学习领域的,这意味着你需要一些标记的数据来训练这些模型。对于垃圾邮件分类器的示例,标记的数据集由邮件的内容和邮件的类别2部分组成(类别分为“垃圾邮件”或“非垃圾邮件”)。

spam: 垃圾邮件

Not spam:非垃圾邮件

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_04

模型架构

现在您已经了解了如何使用BERT的示例,让我们仔细了解一下他的工作原理。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._elmo_05


BERT的论文中介绍了2种版本:

  • BERT BASE - 与OpenAI Transformer的尺寸相当,以便比较性能
  • BERT LARGE - 一个非常庞大的模型,它完成了本文介绍的最先进的结果。

BERT的基础集成单元是Transformer的Encoder。关于Transformer的介绍可以阅读作者之前的文章:The Illustrated Transformer,该文章解释了Transformer模型 - BERT的基本概念以及我们接下来要讨论的概念。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._nlp_06

2个BERT的模型都有一个很大的编码器层数,(论文里面将此称为Transformer Blocks) - 基础版本就有12层,进阶版本有24层。同时它也有很大的前馈神经网络( 768和1024个隐藏层神经元),还有很多attention heads(12-16个)。这超过了Transformer论文中的参考配置参数(6个编码器层,512个隐藏层单元,和8个注意头)

模型输入

输入的第一个字符为[CLS],在这里字符[CLS]表达的意思很简单 - Classification (分类)。

BERT与Transformer 的编码方式一样。将固定长度的字符串作为输入,数据由下而上传递计算,每一层都用到了self attention,并通过前馈神经网络传递其结果,将其交给下一个编码器。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._elmo_07

这样的架构,似乎是沿用了Transformer 的架构(除了层数,不过这是我们可以设置的参数)。那么BERT与Transformer 不同之处在哪里呢?可能在模型的输出上,我们可以发现一些端倪。

模型输出

每个位置返回的输出都是一个隐藏层大小的向量(基本版本BERT为768)。以文本分类为例,我们重点关注第一个位置上的输出(第一个位置是分类标识[CLS]) 。如下图

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._bert_08

该向量现在可以用作我们选择的分类器的输入,在论文中指出使用单层神经网络作为分类器就可以取得很好的效果。原理如下:

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._transformer_09

例子中只有垃圾邮件和非垃圾邮件,如果你有更多的label,你只需要增加输出神经元的个数即可,另外把最后的激活函数换成softmax即可。

BERT VS卷积神经网络

对于那些具有计算机视觉背景的人来说,这个矢量切换应该让人联想到VGGNet等网络的卷积部分与网络末端的完全连接的分类部分之间发生的事情。你可以这样理解,实质上这样理解也很方便。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_10

词嵌入历史发展

BERT的开源随之而来的是一种词嵌入的更新。到目前为止,词嵌入已经成为NLP模型处理自然语言的主要组成部分。诸如Word2vec和Glove 等方法已经广泛的用于处理这些问题,在我们使用新的词嵌入之前,我们有必要回顾一下其发展。

Word Embedding Recap

为了让机器可以学习到文本的特征属性,我们需要一些将文本数值化的表示的方式。Word2vec算法通过使用一组固定维度的向量来表示单词,计算其方式可以捕获到单词的语义及单词与单词之间的关系。使用Word2vec的向量化表示方式可以用于判断单词是否相似,对立,或者说判断“男人‘与’女人”的关系就如同“国王”与“王后”。(这些话是不是听腻了〜 emmm水文必备)。另外还能捕获到一些语法的关系,这个在英语中很实用。例如“had”与“has”的关系如同“was”与“is”的关系。

这样的做法,我们可以使用大量的文本数据来预训练一个词嵌入模型,而这个词嵌入模型可以广泛用于其他NLP的任务,这是个好主意,这使得一些初创公司或者计算资源不足的公司,也能通过下载已经开源的词嵌入模型来完成NLP的任务。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_11

word2vec

https://code.google.com/archive/p/word2vec/

A simple way to investigate the learned representations is to find the closest words for a user-specified word. The distance tool serves that purpose. For example, if you enter ‘france’, distance will display the most similar words and their distances to ‘france’, which should look like:

glove

https://nlp.stanford.edu/projects/glove/

The Euclidean distance (or cosine similarity) between two word vectors provides an effective method for measuring the linguistic or semantic similarity of the corresponding words. Sometimes, the nearest neighbors according to this metric reveal rare but relevant words that lie outside an average human’s vocabulary. For example, here are the closest words to the target word frog:

  1. frog
  2. frogs
  3. toad
  4. litoria
  5. leptodactylidae
  6. rana
  7. lizard
  8. eleutherodactylus

The underlying concept that distinguishes man** from **woman, i.e. sex or gender, may be equivalently specified by various other word pairs, such as king and queen or brother and sister. To state this observation mathematically, we might expect that the vector differences man - woman, king - queen, and brother - sister might all be roughly equal. This property and other interesting patterns can be observed in the above set of visualizations.

ELMo

https://www.mihaileric.com/posts/deep-contextualized-word-representations-elmo/

https://baike.baidu.com/item/%E8%8A%9D%E9%BA%BB%E8%A1%97/5424288?fr=aladdin

ELMo 前沿

《Deep Contextualized Word Representations》这篇论文来自华盛顿大学的工作,最后是发表在今年的NAACL会议上,并获得了最佳论文。其实这个工作的前身来自同一团队在ACL2017发表的《Semi-supervised sequence tagging with bidirectional language models》 [4],只是在这篇论文里,他们把模型更加通用化了。首先我们来看看他们工作的动机,他们认为一个预训练的词表示应该能够包含丰富的句法和语义信息,并且能够对多义词进行建模。而传统的词向量(例如word2vec)是上下文无关的。例如下面"apple"的例子,这两个"apple"根据上下文意思是不同的,但是在word2vec中,只有apple一个词向量,无法对一词多义进行建模。

ELMo 详细解读

上面介绍的词嵌入方式有一个很明显的问题,因为使用预训练好的词向量模型,那么无论上下文的语境关系如何,每个单词都只有一个唯一的且已经固定保存的向量化形式“。Wait a minute “ - 出自(Peters et. al., 2017, McCann et. al., 2017, and yet again Peters et. al., 2018 in the ELMo paper )

“ Wait a minute ”这是一个欧美日常梗,示例:
我:兄弟,你认真学习深度,没准能拿80W年薪啊。
你:Wait a minute,这么好,你为啥不做。

这和中文的同音字其实也类似,用这个举一个例子吧, ‘长’ 这个字,在 ‘长度’ 这个词中表示度量,在 ‘长高’ 这个词中表示增加。那么为什么我们不通过”长’周围是度或者是高来判断它的读音或者它的语义呢?嗖嘎,这个问题就派生出语境化的词嵌入模型。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_12


EMLo改变Word2vec类的将单词固定为指定长度的向量的处理方式,它是在为每个单词分配词向量之前先查看整个句子然后使用bi-LSTM来训练它对应的词向量。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._transformer_13

ELMo为解决NLP的语境问题作出了重要的贡献,它的LSTM可以使用与我们任务相关的大量文本数据来进行训练,然后将训练好的模型用作其他NLP任务的词向量的基准。

ELMo的秘密是什么?

ELMo会训练一个模型,这个模型接受一个句子或者单词的输入,输出最有可能出现在后面的一个单词。想想输入法,对啦,就是这样的道理。这个在NLP中我们也称作Language Modeling。这样的模型很容易实现,因为我们拥有大量的文本数据且我们可以在不需要标签的情况下去学习。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_14

上图介绍了ELMo预训练的过程的步骤的一部分:

我们需要完成一个这样的任务:输入“Lets stick to”,预测下一个最可能出现的单词,如果在训练阶段使用大量的数据集进行训练,那么在预测阶段我们可能准确的预测出我们期待的下一个单词。比如输入“机器”,在‘’学习‘和‘买菜’中它最有可能的输出会是‘学习’而不是‘买菜’。

从上图可以发现,每个展开的LSTM都在最后一步完成预测。

对了真正的ELMo会更进一步,它不仅能判断下一个词,还能预测前一个词。(Bi-Lstm)

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_15


ELMo通过下图的方式将hidden states(的初始的嵌入)组合咋子一起来提炼出具有语境意义的词嵌入方式(全连接后加权求和)

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._bert_16

ELMo的几位作者都是NLP圈内的知名人士

更多ELMo的模型图片

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._transformer_17


自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._bert_18

图片来源(https://www.mihaileric.com/posts/deep-contextualized-word-representations-elmo/

ElMO不足之处

ELMo 有什么值得改进的缺点呢?

一个非常明显的缺点在特征抽取器选择方面,ELMO 使用了 LSTM 而不是新贵 Transformer,Transformer 是谷歌在 17 年做机器翻译任务的“Attention is all you need”的论文中提出的,引起了相当大的反响,很多研究已经证明了 Transformer 提取特征的能力是要远强于 LSTM 的。如果 ELMO 采取 Transformer 作为特征提取器,那么估计 BERT 的反响远不如现在的这种火爆场面。

ULM-FiT:NLP领域应用迁移学习

ULM-FiT机制让模型的预训练参数得到更好的利用。所利用的参数不仅限于embeddings,也不仅限于语境embedding,ULM-FiT引入了Language Model和一个有效微调该Language Model来执行各种NLP任务的流程。这使得NLP任务也能像计算机视觉一样方便的使用迁移学习。

The Transformer:超越LSTM的结构

Transformer论文和代码的发布,以及其在机器翻译等任务上取得的优异成果,让一些研究人员认为它是LSTM的替代品,事实上却是Transformer比LSTM更好的处理long-term dependancies(长程依赖)问题Transformer Encoding和Decoding的结构非常适合机器翻译,但是怎么利用他来做文本分类的任务呢?实际上你只用使用它来预训练可以针对其他任务微调的语言模型即可。

OpenAI Transformer:用于语言模型的Transformer解码器预训练

事实证明,我们并不需要一个完整的transformer结构来使用迁移学习和一个很好的语言模型来处理NLP任务。我们只需要Transformer的解码器就行了。The decoder is a good choice because it’s a natural choice for language modeling (predicting the next word) since it’s built to mask future tokens – a valuable feature when it’s generating a translation word by word.

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._transformer_19


该模型堆叠了十二个Decoder层。 由于在该设置中没有Encoder,因此这些Decoder将不具有Transformer Decoder层具有的Encoder - Decoder attention层。 然而,取而代之的是一个self attention层(masked so it doesn’t peak at future tokens)。

通过这种结构调整,我们可以继续在相似的语言模型任务上训练模型:使用大量的未标记数据集训练,来预测下一个单词。举个列子:你那7000本书喂给你的模型,(书籍是极好的训练样本~比博客和推文好很多。)训练框架如下:

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._bert_20

Transfer Learning to Downstream Tasks

通过OpenAI的transformer的预训练和一些微调后,我们就可以将训练好的模型,用于其他下游NLP任务啦。(比如训练一个语言模型,然后拿他的hidden state来做分类。),下面就介绍一下这个骚操作。(还是如上面例子:分为垃圾邮件和非垃圾邮件)

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._elmo_21


OpenAI论文概述了许多Transformer使用迁移学习来处理不同类型NLP任务的例子。如下图例子所示:

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._elmo_22

BERT: From Decoders to Encoders

OpenAI transformer为我们提供了基于Transformer的精密的预训练模型。但是从LSTM到Transformer的过渡中,我们发现少了些东西。ELMo的语言模型是双向的,但是OpenAI的transformer是前向训练的语言模型。我们能否让我们的Transformer模型也具有Bi-Lstm的特性呢?

R-BERT:“Hold my beer”

Masked Language Model

BERT说:“我要用 transformer 的 encoders”

Ernie不屑道:“呵呵,你不能像Bi-Lstm一样考虑文章”

BERT自信回答道:“我们会用masks”

解释一下Mask:

语言模型会根据前面单词来预测下一个单词,但是self-attention的注意力只会放在自己身上,那么这样100%预测到自己,毫无意义,所以用Mask,把需要预测的词给挡住。

如下图:

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._语言模型_23

Two-sentence Tasks

我们回顾一下OpenAI transformer处理不同任务的输入转换,你会发现在某些任务上我们需要2个句子作为输入,并做一些更为智能的判断,比如是否相似,比如 给出一个维基百科的内容作为输入,同时在放入一条针对该条目的问题,那么我们的算法模型能够处理这个问题吗?

为了使BERT更好的处理2个句子之间的关系,预训练的过程还有一个额外的任务:给定2个句子(A和B),A与B是否相似?(0或者1)

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._bert_24

特殊NLP任务

BERT的论文为我们介绍了几种BERT可以处理的NLP任务:

  1. 短文本相似
  2. 文本分类
  3. QA机器人
  4. 语义标注

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._nlp_25

BERT用做特征提取

微调方法并不是使用BERT的唯一方法,就像ELMo一样,你可以使用预选训练好的BERT来创建语境化词嵌入。然后你可以将这些嵌入提供给现有的模型。

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._nlp_26

哪个向量最适合作为上下文嵌入? 我认为这取决于任务。 本文考察了六种选择(与微调模型相比,得分为96.4):

自然语言处理(NLP): 13 The Illustrated BERT, ELMo, and co._transformer_27

BERT源码分析

使用BERT的最佳方式是通过 BERT FineTuning with Cloud TPUs (https://colab.research.google.com/github/tensorflow/tpu/blob/master/tools/colab/bert_finetuning_with_cloud_tpus.ipynb) 谷歌云上托管的笔记。如果你未使用过谷歌云TPU可以试试看,这是个不错的尝试。另外BERT也适用于TPU,CPU和GPU

**tensorflow版本 **BERT代码

  • 该模型在modeling.py(BertModel类)中构建,与vanilla Transformer编码器完全相同。
  • run_classifier.py是微调过程的一个示例。它还构建了监督模型的分类层。如果要构建自己的分类器,请查看该文件中的create_model()方法。
  • 可以下载几种预先训练的模型。涵盖102种语言的多语言模型,这些语言都是在维基百科的数据基础上训练而成的。
  • BERT不会将单词视为tokens。相反,它注重WordPieces。 tokenization.py是将你的单词转换为适合BERT的wordPieces的tokensizer。

**pytorch 版本 **BERT **代码 **

我们重点关注下面的文件即可

  • modeling

https://github.com/huggingface/transformers/blob/master/src/transformers/modeling_bert.py

HuggingFace提供的一个基于PyTorch实现的BERT 模型

  • BertEmbedding: wordpiece embedding + position embedding + token type embedding
  • BertSelfAttnetion: query, key, value
  • BertSelfOutput:
  • BertIntermediate
  • BertOutput
  • BertForSequenceClassification
  • configuration

https://github.com/huggingface/transformers/blob/master/src/transformers/configuration_bert.py

  • tokenization

https://github.com/huggingface/transformers/blob/master/src/transformers/tokenization_bert.py

  • DataProcessor

https://github.com/huggingface/transformers/blob/master/src/transformers/data/processors/glue.py

  • rule_gule.py 是一个文本分类实现的案例
  • optimization.py 提供了AdamW 梯度更新算法

BERT是Transformer的一部分. Transformer本质是filter size为1的CNN. BERT比较适合几百个单词的情况,文章太长不太行。从github 上下载transformers 实现bert 预训练模型处理和文本分类的案例。

我们在使用bert 的预训练的模型时,首先要下载,下载完成我们修改成下面文件名称即可使用了

  • pytorch_model.bin : 预训练的模型
  • vocab.txt :词典文件
  • config.json: bert 配置文件,主要bert 的定义的参数

英文预训练模型:

https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-pytorch_model.bin

https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-vocab.txt

https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased-config.json

中文预训练模型:

https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-pytorch_model.bin

https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-vocab.txt

https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese-config.json

GLUE benchmark

BERT的很多任务基于GLUE benchmark

https://gluebenchmark.com/tasks/

https://openreview.net/pdf?id=rJ4km2R5t7

最近NVIDIA开源了他们53分钟训练BERT的代码

https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/LanguageModeling/BERT

留言板

如果感觉有用,留个赞吧~~

# 参考文献

[1] BERT全文翻译成中文

https://zhuanlan.zhihu.com/p/59775981

[2] 图解 BERT 模型:从零开始构建 BERT

https://flashgene.com/archives/20062.html

[3] NLP必读:十分钟读懂谷歌BERT模型

https://zhuanlan.zhihu.com/p/51413773

[4] BERT Explained: State of the art language model for NLP

https://towardsdatascience.com/bert-explained-state-of-the-art-language-model-for-nlp-f8b21a9b6270

[5] The Illustrated Transformer

https://jalammar.github.io/illustrated-transformer/

[6]Self Attention 和 Transformer 模型实现理解

[7]The Annotated Transformer

http://nlp.seas.harvard.edu/2018/04/03/attention.html

[8]HuggingFace-Transformers系列的介绍以及在下游任务中的使用

https://dxzmpk.github.io/