雷锋网 AI 科技评论按:自上个月谷歌公开 BERT 模型以来,BERT 模型以其双向、深层等特点,成功在 11 项 NLP 任务中取得 state of the art 的结果,赢得自然语言处理学界的一片赞誉之声。惊鸿一瞥后,人们都在期待谷歌何时会放出 BERT 模型源代码。
直至今日,谷歌终于一鼓作气发布了包括 BERT 模型 TensorFlow 代码、BERT-Base 与 BERT-Large 模型的预训练检查点、微调实验结果的自动化复现 TensorFlow 代码、预训练数据生成和数据训练的代码在内的「BERT 模型大礼包」。雷锋网 AI 科技评论将通过本文分享 BERT 模型的源代码开源网址,以及源代码页面 Readme 的部分简介内容(已译成中文),以飨读者。
BERT 项目地址:
https://github.com/google-research/bert#fine-tuning-with-bert
BERT 项目论文:
https://arxiv.org/abs/1810.04805
什么是 Bert ?
BERT 是一种对语言表征进行预训练的方法,换句话说,是经过大型文本语料库(如维基百科)训练后获得的通用「语言理解」模型,该模型可用于我们最在乎的 NLP 下游任务(如问答)。BERT 之所以表现得比过往的方法要好,是因为它是首个用于进行 NLP 预训练的无监督、深度双向系统。
无监督意味着 BERT 仅使用文本语料库进行训练,这点很重要,因为在网络上存在着大量公开的多语言文本数据。
预训练表征可能无上下文语境,也可能有上下文语境,有上下文语境的系统可以进一步划分成单向的或者双向的。以 word2vec ( https://www.tensorflow.org/tutorials/representation/word2vec ) 和 GloVe ( https://nlp.stanford.edu/projects/glove/ )为例,无上下文语境的模型为词汇表中的每个单词生成单个「词嵌入」表征,因此「 bank 」在「 bank deposit 」和「 river bank 」中可能存在同样的表征。反之,有上下文语境的模型会根据整句话生成词的表征。
BERT 建立在近期一些上下文预训练语境表征工作的基础上,包括半监督序列学习( https://arxiv.org/abs/1511.01432 )、预训练生成模型( https://blog.openai.com/language-unsupervised/ )、ELMo ( https://allennlp.org/elmo )以及 ULMFit ( http://nlp.fast.ai/classification/2018/05/15/introducting-ulmfit.html ),但以上模型要么是单向的,要么是浅层双向的,这意味着每个单词只能与其左边(或右边)的单词进行语境化结合。以「 I made a bank deposit 」为例,由于是单向表示,「 bank 」只能基于左边「 I made a 」而不是与关联性更强的「 deposit 」生成语境。过去有一些工作试图打造出一个能够结合上下文语境的生成模型,然而这些工作目前看来都较「 浅层 」。BERT 真正做到了结合上下文语境来生成「 bank 」,兼顾到「 I made a 」和「 deposit 」,从深度神经网络的最底层开始,拥有深度双向属性。
BERT 的方法很简单:一开始先屏蔽掉输入词汇的 15%,然后通过深度双向的 Transformer 编码器运行整个序列,最后预测屏蔽的单词。举个例子:
Input: the man went to the [MASK1] . he bought a [MASK2] of milk.
Labels: [MASK1] = store; [MASK2] = gallon
为了让模型学习到句子之间的关系,我们特意将模型放在可以从任意单语语料库里生成的简单任务中进行训练:给出两个句子 A 和 B,句子 B 究竟是句子 A 的下一个衔接句,亦或者只是语料库中随机生成的句子?
Sentence A: the man went to the store .
Sentence B: he bought a gallon of milk .
Label: IsNextSentence
Sentence A: the man went to the store .
Sentence B: penguins are flightless .
Label: NotNextSentence
最后,我们在一个大型语料库(维基百科 + BookCorpus )中对一个较大的模型(12 - 24 层的 Transformer 编码器 )进行了长时间训练,最终得到 BERT。
BERT 的使用基本可以分为两个阶段:
预训练阶段的费用不菲(在 4-16 个 TPU 上训练需要花上4天),好在每个语种的训练都能一次性搞定(目前模型只支持英语,多语言模型会在不久的将来发布)。我们正在陆续发布一些论文中提及的预训练模型。大多数 NLP 研究人员日后再无需从头预训练自己的模型。
微调阶段的费用很便宜。只要一开始使用同样的预训练模型,论文中所有的成果只需在单个TPU 中训练 1 个小时就能复现(在单个 GPU 上也只需几个小时就能复现)。以 SQUAD 为例,只要在单个 TPU 上将模型训练 30 分钟,就能获得 91.0% 的 Dev F1 得分,这是单系统目前所能达到的最好水准。
BERT 的另外一个优势是能够轻松适用多种类型的 NLP 任务。论文中我们展示了BERT在句子级别(如 SST-2 )、句对级别(如 MultiNLI )、单词级别(如 NER )以及长文本级别(如 SQuAD )任务上的最新结果,几乎没有对模型进行特定修改。
本次资料库发布了哪些东西?
我们将发布以下成果:
BERT 模型(主要是标准 Transformer 结构)的 TensorFlow 代码
全小写语料训练版和正常语料训练版的 BERT-Base 与 BERT-Large 模型的预训练检查点
自动化复现文中重要的微调实验结果的 TensorFlow 代码,包括在 SQuAD、MultiNLI 和 MRPC 数据集下的训练。
预训练数据生成和数据训练的代码
可以通过免费 TPU 集群运行 BERT 的 Colab 链接
资料库里的所有代码都可以在 CPU、GPU 和 TPU 集群上运行。
使用 BERT 进行微调
重要事项:文中的所有结果都是在 64GB 内存的单个 TPU 上进行微调。我们目前无法在 12GB - 16GB 内存的 GPU 上来复现 BERT-Large 的大部分结果,因为其支持的最大 batch 数太小了。为此,我们正努力在库中添加一段可以在 GPU 上进行更大 batch 数训练的代码。请在“内存不足问题”章节(https://github.com/google-research/bert/blob/master/README.md#out-of-memory-issues )查阅详情。
此代码使用了 TensorFlow 1.11.0 进行测试。此外,也使用了 Python2 和 Python3 进行测试(使用最多的还是 Python2 ,因为这是谷歌内部正在使用的)。
使用 BERT-Base 模型进行微调的代码正常情况下可以在给定超参数、拥有 12GB 内存以上的 GPU 上运行。
via https://github.com/google-research/bert/blob/master/README.md
雷锋网 AI 科技评论编译