*****新的3月11日,2020年:较小的Bert模型*****
这是24个较小的BERT模型(仅英语,未固定,接受文字掩盖训练)的发行版,在阅读良好的学生中提到了更好的学习:关于预训练的紧凑型模型的重要性。
我们已经表明,标准的BERT配方(包括模型架构和训练目标)在广泛的模型大小上是有效的,除了Bert-Base和Bert-large之外。较小的BERT模型旨在用于具有限制计算资源的环境。它们可以以与原始BERT模型相同的方式进行微调。但是,它们在知识蒸馏的背景下最有效,在知识蒸馏的背景下,微调标签是由更大,更准确的老师生产的。
我们的目标是在具有更少的计算资源的机构中进行研究,并鼓励社区寻求创新替代方向以提高模型能力。
您可以从这里下载全部24个,也可以从下表中单独下载:
H = 128 | H = 256 | H = 512 | H = 768 | |
---|---|---|---|---|
L = 2 | 2/128(Bert-微小) | 2/256 | 2/512 | 2/768 |
L = 4 | 4/128 | 4/256(Bert-Mini) | 4/512(Bert-Small) | 4/768 |
L = 6 | 6/128 | 6/256 | 6/512 | 6/768 |
L = 8 | 8/128 | 8/256 | 8/512(Bert-Medium) | 8/768 |
L = 10 | 10/128 | 10/256 | 10/512 | 10/768 |
L = 12 | 12/128 | 12/256 | 12/512 | 12/768(Bert-base) |
请注意,此版本中的BERT基本模型仅用于完整性;它在与原始模型相同的方向下进行了重新训练。
这是测试集上的相应胶水分数:
模型 | 分数 | 可乐 | SST-2 | MRPC | STS-B | QQP | mnli-m | mnli-mm | QNLI(v2) | rte | wnli | 斧头 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
伯特小 | 64.2 | 0.0 | 83.2 | 81.1/71.1 | 74.3/73.6 | 62.2/83.4 | 70.2 | 70.3 | 81.5 | 57.2 | 62.3 | 21.0 |
伯特·米尼(Bert-Mini) | 65.8 | 0.0 | 85.9 | 81.1/71.8 | 75.4/73.3 | 66.4/86.2 | 74.8 | 74.3 | 84.1 | 57.9 | 62.3 | 26.1 |
伯特·萨尔 | 71.2 | 27.8 | 89.7 | 83.4/76.2 | 78.8/77.0 | 68.1/87.0 | 77.6 | 77.0 | 86.4 | 61.8 | 62.3 | 28.6 |
伯特中等 | 73.5 | 38.0 | 89.6 | 86.6/81.6 | 80.4/78.4 | 69.6/87.9 | 80.0 | 79.1 | 87.7 | 62.2 | 62.3 | 30.5 |
对于每个任务,我们从下面的列表中选择了最佳的微调超参数,并接受了4个时代的培训:
如果您使用这些模型,请引用以下论文:
@article{turc2019,
title={Well-Read Students Learn Better: On the Importance of Pre-training Compact Models},
author={Turc, Iulia and Chang, Ming-Wei and Lee, Kenton and Toutanova, Kristina},
journal={arXiv preprint arXiv:1908.08962v2 },
year={2019}
}
*****新的2019年5月31日:整个单词蒙版模型*****
这是几种新模型的版本,这是改进预处理代码的结果。
在原始的预处理代码中,我们随机选择文字代币将其掩盖。例如:
Input Text: the man jumped up , put his basket on phil ##am ##mon ' s head
Original Masked Input: [MASK] man [MASK] up , put his [MASK] on phil [MASK] ##mon ' s head
新技术称为整个单词掩蔽。在这种情况下,我们总是掩盖与单词相对应的所有令牌。总体掩蔽率保持不变。
Whole Word Masked Input: the man [MASK] up , put his basket on [MASK] [MASK] [MASK] ' s head
培训是相同的 - 我们仍然可以独立预测每个蒙版的文章令牌令牌。改进来自以下事实:原始预测任务对于已经分为多个文字的单词太“容易”。
可以通过传递标志--do_whole_word_mask=True
to create_pretraining_data.py
在数据生成过程中启用这一点。
带有整个单词掩蔽的预训练模型在下面链接。数据和培训是相同的,模型与原始模型具有相同的结构和词汇。我们仅包括Bert-large模型。使用这些模型时,请在论文中清楚地表明您使用的是Bert-Large的整个单词掩盖变体。
BERT-Large, Uncased (Whole Word Masking)
:24层,1024个隐藏,16个头,340m参数
BERT-Large, Cased (Whole Word Masking)
:24层,1024隐藏,16头,340m参数
模型 | 小队1.1 F1/EM | 多NLI准确性 |
---|---|---|
Bert-large,未露面(原始) | 91.0/84.3 | 86.05 |
Bert-large,未露面(整个单词掩盖) | 92.8/86.7 | 87.07 |
Bert-large,Cased(原始) | 91.5/84.8 | 86.09 |
Bert-large,Cased(整个单词掩蔽) | 92.9/86.7 | 86.46 |
*****新的2019年2月7日:TFHUB模块*****
Bert已上传到TensorFlow Hub。有关如何使用TF集线器模块的示例,请参见run_classifier_with_tfhub.py
。或在COLAB上的浏览器中运行示例。
*****新的2018年11月23日:非正态化的多语言模型 +泰语 +蒙古人*****
我们上传了一个新的多语言模型,该模型在输入上不执行任何归一化(没有较低的套管,口音剥离或Unicode归一化),还包括泰语和蒙古人。
建议使用此版本来开发多语言模型,尤其是在具有非拉丁字母的语言上。
这不需要任何代码更改,可以在此处下载:
BERT-Base, Multilingual Cased
:104种语言,12层,768隐藏,12个头,110m参数*****新的2018年11月15日:Sota Squad 2.0系统*****
我们发布了代码更改,以重现我们的83%F1 Squad 2.0系统,该系统目前在排行榜上排名3%。有关详细信息,请参见README的小队2.0部分。
*****新的2018年11月5日:Bert的第三方Pytorch和Chainer版本*****
Huggingface的NLP研究人员为BERT提供了Pytorch版本,该版本与我们的预训练检查点兼容,并能够重现我们的结果。 Sosuke Kobayashi还制作了Bert的连锁版本(谢谢!),我们没有参与Pytorch实施的创建或维护,因此请将任何问题指向该存储库的作者。
*****新的2018年11月3日:多语言和中文模型*****
我们已经制造了两个新的BERT模型:
BERT-Base, Multilingual
(不建议使用Multilingual Cased
) :102种语言,12层,768隐藏,12个头,110m参数BERT-Base, Chinese
:中文简化和传统,12层,768隐藏,12个头,1.10亿参数我们为中文使用基于字符的令牌化,以及所有其他语言的文字词组化。这两种模型均应在没有任何代码更改的情况下开箱即用。我们确实更新了在tokenization.py
中的BasicTokenizer
的实现,以支持中文令牌化,因此,如果您分叉,请更新。但是,我们没有更改令牌化API。
有关更多信息,请参阅多语言读数。
*****结束新信息*****
BERT或t Ransformers的bert e Ncoder resentations是一种新的训练语言表示的方法,可以在各种自然语言处理(NLP)任务中获得最新的结果。
我们的学术论文详细描述了BERT,并可以在此处找到许多任务的完整结果:https://arxiv.org/abs/1810.04805。
要提供几个数字,以下是小队v1.1问题回答任务的结果:
小队V1.1排行榜(2018年10月8日) | 测试EM | 测试F1 |
---|---|---|
第一名合奏 - 伯特 | 87.4 | 93.2 |
第二名合奏-NLNET | 86.0 | 91.7 |
第一名单模型 - 伯特 | 85.1 | 91.8 |
第二名单模型-NLNET | 83.5 | 90.1 |
以及几个自然语言推理任务:
系统 | Multinli | 问题NLI | 赃物 |
---|---|---|---|
伯特 | 86.7 | 91.1 | 86.3 |
Openai GPT(sota Press) | 82.2 | 88.1 | 75.0 |
加上许多其他任务。
此外,这些结果几乎没有特定于任务的神经网络体系结构设计获得。
如果您已经知道Bert是什么,并且只想开始,则可以下载预训练的型号,并在几分钟内进行最新的微调。
伯特是一种预训练语言表示的方法,这意味着我们可以在大型文本语料库(如Wikipedia)上训练通用的“语言理解”模型,然后将该模型用于我们关心的下游NLP任务(例如问题)回答)。伯特(Bert)的表现要优于先前的方法,因为它是第一个无监督的,深层的双向系统,用于训练NLP。
无监督意味着BERT仅使用纯文本语料库进行培训,这很重要,因为在网络上以多种语言在网络上公开获得大量的纯文本数据。
预训练的表示也可以是无上下文的或上下文的,上下文表示可以进一步是单向或双向。诸如Word2Vec或Glove之类的无上下文模型为词汇中的每个单词产生一个单一的“词嵌入”表示形式,因此bank
在bank deposit
和river bank
中的代表性相同。上下文模型相反,会生成基于句子中其他单词的每个单词的表示。
伯特(Bert)建立在训练前上下文表示的最新工作基础上,包括半监督序列学习,生成的预训练,Elmo和Ulmfit - 但至关重要的是,这些模型都是单向或浅薄的双向。这意味着每个单词仅使用其左侧(或右)的单词进行上下文化。例如,在句子中I made a bank deposit
的单向表示bank
表示仅基于I made a
但没有deposit
。以前的某些工作确实结合了单独的左转文字和右文本模型的表示形式,但仅以“浅”方式。 Bert使用其左和右下文代表“银行” - I made a ... deposit
- 从深度神经网络的底部开始,因此它是深度的双向。
伯特使用一种简单的方法:我们掩盖了输入中的15%单词,通过深层双向变压器编码运行整个序列,然后仅预测掩盖的单词。例如:
Input: the man went to the [MASK1] . he bought a [MASK2] of milk.
Labels: [MASK1] = store; [MASK2] = gallon
为了学习句子之间的关系,我们还训练可以从任何单语语料库生成的简单任务:给定两个A
A
和B
是B
?
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
然后,我们在大型语料库(Wikipedia + BookCorpus)上训练大型型号(12层到24层变压器)长时间(1m更新步骤),这就是Bert。
使用BERT有两个阶段:预训练和微调。
预训练相当昂贵(在4至16个云TPU上进行四天),但是每种语言的一次性程序(当前模型仅英语,但多语言模型将在不久的将来发布)。我们正在从Google预先培训的论文中释放许多预先培训的模型。大多数NLP研究人员无需从头开始预先培训自己的模型。
微调便宜。从单个云TPU或GPU上几个小时,本文中的所有结果最多可以在完全相同的预训练模型上复制。例如,可以在大约30分钟内对单个云TPU进行训练,以达到91.0%的开发F1分数,这是单个系统的最新系统。
BERT的另一个重要方面是,它可以非常轻松地适应许多类型的NLP任务。在本文中,我们在句子级别(例如,SST-2),句子级级别(例如,Multinli),Word级(例如,NER)和Span-Level上演示了最新的结果(例如,小队)几乎没有特定任务修改的任务。
我们发布以下内容:
BERT-Base
和BERT-Large
的小写和外壳版本的预训练检查点。该存储库中的所有代码都使用CPU,GPU和Cloud TPU播放。
我们正在从论文中释放BERT-Base
和BERT-Large
模型。 Uncased
意味着文字在文字词造型之前已经被降低了,例如, John Smith
成为john smith
。 Uncased
模型还剥离了任何重音标记。 Cased
意味着保留真实的情况和重音标记。通常,除非您知道该案例信息对于您的任务很重要(例如,命名实体识别或词性词性标记), Uncased
会更好。
这些模型均与源代码相同的许可(Apache 2.0)发布。
有关多语言和中文模型的信息,请参见多语言读数。
使用壳体模型时,请确保通过--do_lower=False
to to training脚本。 (或通过使用自己的脚本,将do_lower_case=False
直接传递到FullTokenizer
。)
指向模型的链接在此处(右键单击,在名称上保存链接为...”):
BERT-Large, Uncased (Whole Word Masking)
:24层,1024个隐藏,16个头,340m参数BERT-Large, Cased (Whole Word Masking)
:24层,1024隐藏,16头,340m参数BERT-Base, Uncased
:12层,768隐藏,12个头,110m参数BERT-Large, Uncased
:24层,1024个隐藏,16头,340m参数BERT-Base, Cased
:12层,768 HIDDER,12头,110m参数BERT-Large, Cased
:24层,1024隐藏,16头,340m参数BERT-Base, Multilingual Cased (New, recommended)
:104种语言,12层,768隐藏,12个头,110m参数BERT-Base, Multilingual Uncased (Orig, not recommended)
(不建议使用,使用Multilingual Cased
) :102种语言,12层,768隐藏,12个头,120m的参数BERT-Base, Chinese
:中文简化和传统,12层,768隐藏,12个头,1.10亿参数每个.zip文件包含三个项目:
bert_model.ckpt
),其中包含预先训练的权重(实际上是3个文件)。vocab.txt
)将文字映射到单词ID。bert_config.json
)指定模型的超参数。 重要的是:纸上的所有结果均在单个云TPU上进行了微调,该云TPU具有64GB的RAM。目前无法使用具有12GB-16GB RAM的GPU在纸上重新生产大多数BERT-Large
结果,因为可以适合内存的最大批量大小太小。我们正在为此存储库添加代码,该存储库允许在GPU上更大的有效批量尺寸。有关更多详细信息,请参见有关默认问题的部分。
使用TensorFlow 1.11.0测试了此代码。它通过Python2和Python3进行了测试(但更彻底地用Python2进行了测试,因为这是Google内部使用的内容)。
使用BERT-Base
微调示例应该能够在具有至少12GB RAM的GPU上运行,使用给定的超参数。
下面的大多数示例都假定您将使用像Titan X或GTX 1080这样的GPU在本地机器上进行培训/评估。
但是,如果您可以访问要训练的云TPU,只需将以下标志添加到run_classifier.py
或run_squad.py
:
--use_tpu=True
--tpu_name=$TPU_NAME
请参阅Google Cloud TPU教程,以了解如何使用Cloud TPU。另外,您可以使用Google Colab笔记本“与Cloud TPU的Bert Finetuning”。
在Cloud TPU上,验证的模型和输出目录将需要在Google Cloud Storage上。例如,如果您有一个名为some_bucket
的存储桶,则可以使用以下标志:
--output_dir=gs://some_bucket/my_output_dir/
也可以在Google Cloud Storage文件夹gs://bert_models/2018_10_18
中找到未拉链的预训练模型文件。例如:
export BERT_BASE_DIR=gs://bert_models/2018_10_18/uncased_L-12_H-768_A-12
在运行此示例之前,您必须通过运行此脚本并将其解放到某些目录$GLUE_DIR
之前下载胶水数据。接下来,下载BERT-Base
检查点,然后将其解压缩到某些目录$BERT_BASE_DIR
。
此示例代码在Microsoft Research释义语料库(MRPC)语料库上进行微调BERT-Base
,该语料库仅包含3,600个示例,并且在大多数GPU中可以在几分钟内进行微调。
export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/glue
python run_classifier.py
--task_name=MRPC
--do_train=true
--do_eval=true
--data_dir= $GLUE_DIR /MRPC
--vocab_file= $BERT_BASE_DIR /vocab.txt
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $BERT_BASE_DIR /bert_model.ckpt
--max_seq_length=128
--train_batch_size=32
--learning_rate=2e-5
--num_train_epochs=3.0
--output_dir=/tmp/mrpc_output/
您应该看到这样的输出:
***** Eval results *****
eval_accuracy = 0.845588
eval_loss = 0.505248
global_step = 343
loss = 0.505248
这意味着开发设置的精度为84.55%。即使从相同的预训练检查点开始时,诸如MRPC之类的小集合在开发设置的精度上也具有很大的差异。如果您多次重新运行(确保指向不同的output_dir
),则应看到结果在84%至88%之间。
在run_classifier.py
中实现了其他一些预训练的模型,因此,遵循这些示例以将BERT用于任何单句或句子对分类任务,应该直接实现。
注意:您可能会看到Running train on CPU
消息。这实际上只是意味着它在包括GPU的云TPU以外的其他东西上运行。
训练分类器后,可以使用-do_predict = true命令在推理模式下使用它。您需要在输入文件夹中使用一个名为test.tsv的文件。输出将在输出文件夹中的名为test_results.tsv的文件中创建。每行将包含每个样本的输出,列是类概率。
export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/glue
export TRAINED_CLASSIFIER=/path/to/fine/tuned/classifier
python run_classifier.py
--task_name=MRPC
--do_predict=true
--data_dir= $GLUE_DIR /MRPC
--vocab_file= $BERT_BASE_DIR /vocab.txt
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $TRAINED_CLASSIFIER
--max_seq_length=128
--output_dir=/tmp/mrpc_output/
斯坦福问题回答数据集(小队)是回答基准数据集的一个流行问题。 BERT(在发布时)在小队上获得最先进的结果,几乎没有特定于任务的网络体系结构修改或数据增强。但是,它确实需要半复合数据预处理和后处理才能处理(a)小队上下文段落的可变长度性质,以及(b)用于小队训练的字符级答案注释。此处理已在run_squad.py
中实现和记录。
要在小队上运行,您将首先需要下载数据集。该小队网站似乎不再链接到v1.1数据集,但是可以在此处找到必要的文件:
将这些下载到一些目录$SQUAD_DIR
。
由于内存限制,目前无法在12GB-16GB GPU上复制该论文的最先进小队(实际上,即使是批次1也似乎不适合使用BERT-Large
)。但是,可以使用这些超参数在GPU上训练合理强大的BERT-Base
模型:
python run_squad.py
--vocab_file= $BERT_BASE_DIR /vocab.txt
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $BERT_BASE_DIR /bert_model.ckpt
--do_train=True
--train_file= $SQUAD_DIR /train-v1.1.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v1.1.json
--train_batch_size=12
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=/tmp/squad_base/
开发集预测将被保存到一个名为predictions.json
的output_dir
中。
python $SQUAD_DIR /evaluate-v1.1.py $SQUAD_DIR /dev-v1.1.json ./squad/predictions.json
应该产生这样的输出:
{ " f1 " : 88.41249612335034, " exact_match " : 81.2488174077578}
您应该看到类似于BERT-Base
论文中报告的88.5%的结果。
如果您可以访问云TPU,则可以使用BERT-Large
训练。这是一组超参数(略有不同),始终获得约90.5%-91.0%的F1单一系统,仅在小队上训练:
python run_squad.py
--vocab_file= $BERT_LARGE_DIR /vocab.txt
--bert_config_file= $BERT_LARGE_DIR /bert_config.json
--init_checkpoint= $BERT_LARGE_DIR /bert_model.ckpt
--do_train=True
--train_file= $SQUAD_DIR /train-v1.1.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v1.1.json
--train_batch_size=24
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=gs://some_bucket/squad_large/
--use_tpu=True
--tpu_name= $TPU_NAME
例如,一个随机运行这些参数会产生以下DEV分数:
{ " f1 " : 90.87081895814865, " exact_match " : 84.38978240302744}
如果您在此之前在Triviaqa上微调一个时代,则结果将会更好,但是您需要将Triviaqa转换为小队JSON格式。
该模型还在run_squad.py
中实现和记录。
要在Squad 2.0上运行,您首先需要下载数据集。必要的文件可以在此处找到:
将这些下载到一些目录$SQUAD_DIR
。
在Cloud TPU上,您可以使用Bert-Large运行,如下所示:
python run_squad.py
--vocab_file= $BERT_LARGE_DIR /vocab.txt
--bert_config_file= $BERT_LARGE_DIR /bert_config.json
--init_checkpoint= $BERT_LARGE_DIR /bert_model.ckpt
--do_train=True
--train_file= $SQUAD_DIR /train-v2.0.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v2.0.json
--train_batch_size=24
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=gs://some_bucket/squad_large/
--use_tpu=True
--tpu_name= $TPU_NAME
--version_2_with_negative=True
我们假设您已经复制了从输出目录到称为./squad/的本地目录的所有内容。最初的开发设置预测将在./squad/predictions.json以及无答案的分数(“”)与每个问题的最佳非零答案之间的差异。/squad/null_odds.json中
运行此脚本以调整预测零与非空的答案的阈值:
python $ squad_dir/evaluate-v2.0.py $ skead_dir/dev-v2.0.json ./squad/predictions.json -na-prob-file ./squad/squad/null_odds.json
假设脚本输出“ BEST_F1_THRESH”阈值。 (典型值在-1.0和-5.0之间。现在,您可以重新运行模型以生成衍生阈值的预测,也可以从./squad/nbest_predictions.json提取适当的答案。
python run_squad.py
--vocab_file= $BERT_LARGE_DIR /vocab.txt
--bert_config_file= $BERT_LARGE_DIR /bert_config.json
--init_checkpoint= $BERT_LARGE_DIR /bert_model.ckpt
--do_train=False
--train_file= $SQUAD_DIR /train-v2.0.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v2.0.json
--train_batch_size=24
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=gs://some_bucket/squad_large/
--use_tpu=True
--tpu_name= $TPU_NAME
--version_2_with_negative=True
--null_score_diff_threshold= $THRESH
纸上的所有实验均在云TPU上进行微调,该云TPU具有64GB的设备RAM。因此,当使用具有12GB-16GB RAM的GPU时,如果您使用论文中描述的相同的超参数,则可能会遇到不可存储的问题。
影响内存使用的因素是:
max_seq_length
:释放的型号的序列长度最高为512,但您可以以较短的最大序列长度进行微调以节省大量内存。这是由我们示例代码中的max_seq_length
标志控制的。
train_batch_size
:内存使用也与批处理大小成正比。
模型类型, BERT-Base
与BERT-Large
: BERT-Large
模型所需的记忆比BERT-Base
要多得多。
优化器:BERT的默认优化器是Adam,它需要大量的存储器来存储m
和v
向量。切换到更有效的内存优化器可以减少内存使用量,但也会影响结果。我们尚未对其他优化器进行微调。
使用默认培训脚本( run_classifier.py
和run_squad.py
),我们用TensorFlow 1.11.0:在单泰坦X GPU(12GB RAM)上基准了最大批量大小:
系统 | SEQ长度 | 最大批处理大小 |
---|---|---|
BERT-Base | 64 | 64 |
... | 128 | 32 |
... | 256 | 16 |
... | 320 | 14 |
... | 384 | 12 |
... | 512 | 6 |
BERT-Large | 64 | 12 |
... | 128 | 6 |
... | 256 | 2 |
... | 320 | 1 |
... | 384 | 0 |
... | 512 | 0 |
不幸的是,这些最大批量的大小是BERT-Large
如此之小,以至于无论使用的学习率如何,它们实际上会损害模型的准确性。我们正在为此存储库添加代码,该库将允许在GPU上使用更大的有效批量大小。该代码将基于以下技术之一:
梯度积累:在Minibatch中的样品通常相对于梯度计算独立(不包括批准归一化,此处未使用)。这意味着在执行重量更新之前,可以累积多个较小小型匹配的梯度,这将完全等同于单个较大的更新。
梯度检查点:DNN训练期间GPU/TPU存储器的主要用途是缓存向前通行中有效计算所必需的中间激活。 “梯度检查点”通过以智能方式重新计算激活来交换内存时间。
但是,这在当前版本中尚未实现。
在某些情况下,与其微调整个预训练的模型端到端,不如获得预训练的上下文嵌入,它们是从PRE的隐藏层生成的每个输入令牌的固定上下文表示 - 训练模型。这也应该减轻大多数陈旧的问题。
例如,我们包括脚本extract_features.py
,可以这样使用:
# Sentence A and Sentence B are separated by the ||| delimiter for sentence
# pair tasks like question answering and entailment.
# For single sentence inputs, put one sentence per line and DON'T use the
# delimiter.
echo ' Who was Jim Henson ? ||| Jim Henson was a puppeteer ' > /tmp/input.txt
python extract_features.py
--input_file=/tmp/input.txt
--output_file=/tmp/output.jsonl
--vocab_file= $BERT_BASE_DIR /vocab.txt
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $BERT_BASE_DIR /bert_model.ckpt
--layers=-1,-2,-3,-4
--max_seq_length=128
--batch_size=8
这将创建一个JSON文件(每行输入线一行),该文件包含来自layers
指定的每个变压器层的BERT激活(-1是变压器的最终隐藏层等)。
请注意,此脚本将产生非常大的输出文件(默认情况下,每个输入令牌约为15kb)。
如果您需要保持原始单词和令牌化词(用于投影培训标签)之间的一致性,请参见下面的令牌化部分。
注意:您可能会Could not find trained model in model_dir: /tmp/tmpuB5g5c, running initialization to predict.
可以预期此消息,这只是意味着我们正在使用init_from_checkpoint()
API而不是保存的模型API。如果您没有指定检查点或指定无效的检查点,则此脚本将抱怨。
对于句子级任务(或句子意)任务,令牌化非常简单。只需按照run_classifier.py
和extract_features.py
中的示例代码。句子级任务的基本过程是:
实例化tokenizer = tokenization.FullTokenizer
tokens = tokenizer.tokenize(raw_text)
tokenize原始文本。
截断至最大序列长度。 (您最多可以使用512,但是如果可能的话,您可能想使用较短的时间。)
在正确的位置添加[CLS]
和[SEP]
令牌。
文字级别和跨度级任务(例如,小队和NER)更为复杂,因为您需要保持输入文本和输出文本之间的一致性,以便可以投影培训标签。小队是一个特别复杂的例子,因为输入标签是基于字符的,而小队的段落通常比我们的最大序列长度更长。请参阅run_squad.py
中的代码以显示我们如何处理此操作。
在我们描述处理单词级任务的一般配方之前,重要的是要了解我们的令牌机在做什么。它有三个主要步骤:
文本归一化:将所有空格字符转换为空间,(对于Uncased
型号)缩小输入并剥离口音标记。例如, John Johanson's, → john johanson's,
。
标点符号拆分:将所有标点字符分开(即,围绕所有标点字符添加空格)。标点字符定义为(a)具有P*
unicode类的任何内容,(b)任何非字母/number/space ascii字符(例如,诸如$
之类的字符在技术上不是标点符号)。例如, john johanson's, → john johanson ' s ,
WordPiece令牌化:将Whitespace令牌化应用于上述过程的输出,并将单词令牌化应用于每个令牌。 (我们的实现直接基于链接的tensor2tensor
的实现)。例如, john johanson ' s , → john johan ##son ' s ,
该方案的优点是它与大多数现有的英语象征器“兼容”。例如,想象一下您有一个词性标记任务,看起来像这样:
Input: John Johanson 's house
Labels: NNP NNP POS NN
令牌化输出看起来像这样:
Tokens: john johan ##son ' s house
至关重要的是,这将是相同的输出,就像原始文本是John Johanson's house
(在's
之前没有空间)。
如果您具有带有单词级注释的预先讲述的表示形式,则可以独立地将每个输入单词归为每个输入单词,并确定性地维护原始的对准:
### Input
orig_tokens = [ "John" , "Johanson" , "'s" , "house" ]
labels = [ "NNP" , "NNP" , "POS" , "NN" ]
### Output
bert_tokens = []
# Token map will be an int -> int mapping between the `orig_tokens` index and
# the `bert_tokens` index.
orig_to_tok_map = []
tokenizer = tokenization . FullTokenizer (
vocab_file = vocab_file , do_lower_case = True )
bert_tokens . append ( "[CLS]" )
for orig_token in orig_tokens :
orig_to_tok_map . append ( len ( bert_tokens ))
bert_tokens . extend ( tokenizer . tokenize ( orig_token ))
bert_tokens . append ( "[SEP]" )
# bert_tokens == ["[CLS]", "john", "johan", "##son", "'", "s", "house", "[SEP]"]
# orig_to_tok_map == [1, 2, 4, 6]
现在, orig_to_tok_map
可用于将labels
投影到令牌化表示形式。
有普通的英语令牌化方案,这将导致BERT预先培训的方式之间的不匹配。例如,如果您的输入令牌化do n't
收缩分开,这将导致不匹配。如果有可能这样做,则应预处理数据以将其转换回原始文本,但是如果不可能,则此不匹配可能没什么大不了的。
我们正在发布代码以在任意文本语料库上进行“蒙版LM”和“下一个句子预测”。请注意,这不是用于论文使用的确切代码(原始代码是用C ++编写的,并且具有额外的复杂性),但是此代码确实会如文纸中所述生成预训练数据。
这是运行数据生成的方法。输入是一个纯文本文件,每行1个句子。 (重要的是,这些是“下一个句子预测”任务的实际句子)。文档由空线界定。输出是一组tf.train.Example
序列化为TFRecord
文件格式。
您可以使用现成的NLP工具包(例如Spacy)执行句子细分。 create_pretraining_data.py
脚本将连接段,直到达到最大序列长度,以最大程度地减少填充的计算浪费(有关更多详细信息,请参见脚本)。但是,您可能需要故意在输入数据(例如,随机截断输入段的2%)中添加少量噪声,以使其在微调过程中更适合非句子输入。
该脚本将整个输入文件的所有示例存储在内存中,因此,对于大型数据文件,您应该将输入文件碎片并多次调用脚本。 (您可以将文件圈传递到run_pretraining.py
,例如, tf_examples.tf_record*
。)
max_predictions_per_seq
是每个序列蒙版LM预测的最大数量。您应该将其设置为围绕max_seq_length
* masked_lm_prob
(脚本不会自动执行此操作,因为确切的值需要传递给两个脚本)。
python create_pretraining_data.py
--input_file=./sample_text.txt
--output_file=/tmp/tf_examples.tfrecord
--vocab_file= $BERT_BASE_DIR /vocab.txt
--do_lower_case=True
--max_seq_length=128
--max_predictions_per_seq=20
--masked_lm_prob=0.15
--random_seed=12345
--dupe_factor=5
这是运行预训练的方法。如果您是从头开始的预训练,请勿包括init_checkpoint
。 bert_config_file
中指定了模型配置(包括词汇大小)。此演示代码仅针对少数步骤(20)进行预训练,但是实际上,您可能希望将num_train_steps
设置为10000个或更多步骤。传递给run_pretraining.py
max_seq_length
和max_predictions_per_seq
参数必须与create_pretraining_data.py
相同。
python run_pretraining.py
--input_file=/tmp/tf_examples.tfrecord
--output_dir=/tmp/pretraining_output
--do_train=True
--do_eval=True
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $BERT_BASE_DIR /bert_model.ckpt
--train_batch_size=32
--max_seq_length=128
--max_predictions_per_seq=20
--num_train_steps=20
--num_warmup_steps=10
--learning_rate=2e-5
这将产生这样的输出:
***** Eval results *****
global_step = 20
loss = 0.0979674
masked_lm_accuracy = 0.985479
masked_lm_loss = 0.0979328
next_sentence_accuracy = 1.0
next_sentence_loss = 3.45724e-05
请注意,由于我们的sample_text.txt
文件很小,因此此示例培训将仅以几个步骤拟合该数据并产生不切实际的高精度数字。
bert_config.json
中更改vocab_size
。如果您使用较大的词汇量而不更改此词汇,则由于未经检查的外部访问,在GPU或TPU上进行培训时,您可能会得到NAN。max_seq_length
的不同值生成两次数据。BERT-Base
,该基础大约需要2周,费用约为500美元(基于2018年10月的价格) 。与论文中使用的内容相比,仅在单个云TPU上进行训练时,您将不得不缩小批量尺寸。建议使用适合TPU内存的最大批量尺寸。我们将无法释放论文中使用的预处理数据集。对于Wikipedia,建议的预处理是下载最新的转储,使用WikiExtractor.py
提取文本,然后应用任何必要的清理以将其转换为纯文本。
不幸的是,收集BookCorpus的研究人员不再可以公开下载。 Guttenberg数据集项目是一个较小的(200m)的旧书籍(200m),这些旧书籍是公共领域。
Common Crawl是另一个非常大的文本集合,但是您可能需要进行大量的预处理和清理才能提取可用的语料库进行预训练BERT。
该存储库不包括学习新文字词汇的代码。原因是本文中使用的代码是在C ++中实现的,并具有对Google内部库的依赖关系。对于英语而言,从我们的词汇和预训练的模型开始几乎总是更好。对于学习其他语言的词汇,有许多开源选项可用。 However, keep in mind that these are not compatible with our tokenization.py
library:
Google's SentencePiece library
tensor2tensor's WordPiece generation script
Rico Sennrich's Byte Pair Encoding library
If you want to use BERT with Colab, you can get started with the notebook "BERT FineTuning with Cloud TPUs". At the time of this writing (October 31st, 2018), Colab users can access a Cloud TPU completely for free. Note: One per user, availability limited, requires a Google Cloud Platform account with storage (although storage may be purchased with free credit for signing up with GCP), and this capability may not longer be available in the future. Click on the BERT Colab that was just linked for more information.
Yes, all of the code in this repository works out-of-the-box with CPU, GPU, and Cloud TPU. However, GPU training is single-GPU only.
See the section on out-of-memory issues for more information.
There is no official PyTorch implementation. However, NLP researchers from HuggingFace made a PyTorch version of BERT available which is compatible with our pre-trained checkpoints and is able to reproduce our results. We were not involved in the creation or maintenance of the PyTorch implementation so please direct any questions towards the authors of that repository.
There is no official Chainer implementation. However, Sosuke Kobayashi made a Chainer version of BERT available which is compatible with our pre-trained checkpoints and is able to reproduce our results. We were not involved in the creation or maintenance of the Chainer implementation so please direct any questions towards the authors of that repository.
Yes, we plan to release a multi-lingual BERT model in the near future. We cannot make promises about exactly which languages will be included, but it will likely be a single model which includes most of the languages which have a significantly-sized Wikipedia.
BERT-Large
be released? So far we have not attempted to train anything larger than BERT-Large
. It is possible that we will release larger models if we are able to obtain significant improvements.
All code and models are released under the Apache 2.0 license.有关更多信息,请参见LICENSE
文件。
For now, cite the Arxiv paper:
@article{devlin2018bert,
title={BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding},
author={Devlin, Jacob and Chang, Ming-Wei and Lee, Kenton and Toutanova, Kristina},
journal={arXiv preprint arXiv:1810.04805},
year={2018}
}
If we submit the paper to a conference or journal, we will update the BibTeX.
This is not an official Google product.
For help or issues using BERT, please submit a GitHub issue.
For personal communication related to BERT, please contact Jacob Devlin ( [email protected]
), Ming-Wei Chang ( [email protected]
), or Kenton Lee ( [email protected]
).