1、引言
论文链接:
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding (waqasrana.me)
Jacob Devlin 等提出了一种新的语言表示模型 BERT(Bidirectional Encoder Representations fromTransformers)[1]。BERT 通过在所有层中综合利用文本左右两个方向的上下文信息来从未标记文本中预训练深度双向表示。如图 1 所示,预训练的 BERT 模型可以通过仅仅增加一个额外的输出层而无需大量特定于任务的架构修改, 然后微调, 就能在很多任务上达到 SOTA。
图1 Overall pre-training and fine-tuning procedures for BERT
2、方法
2.1 BERT Embeddings
图2 BERT Embeddings
BERT Embeddings 即 BERT 输入表示,如图 2 所示。BERT Embeddings=Token Embeddings+Segment Embeddings+Position Embeddings。
BertTokenizer 的输入可以是多个句子,BertTokenizer 的输出包括 input_ids、token_type_ids 和 attention_mask。input_ids 是 BertTokenizer 的输入文本的 token id 序列,每个 token 序列的第一个 token 是 [CLS](分类 token),每个句子末尾还要加上一个特殊 token [SEP]。token_type_ids 用于标记一个 token 的所属句子,attention_mask 取值范围为 {0, 1},用于标记一个 token 是不是 padding token。input_ids 经过一个 Embedding 层便得到 Token Embeddings,token_type_ids 经过一个 Embedding 层便得到 Segment Embeddings,位置 id 经过一个 Embedding 层便得到 Position Embeddings。
2.2 Padding Mask
因为 BertTokenizer 的输入文本长度不一, 导致得到的 token id 序列长度也不一致,故需要使用 padding_token_id 填充 token id 序列。即将所有 token id 序列填充至一个 batch 中样本的最大长度或者 'max_length'(舍弃序列中超过 'max_length' 的部分),这一过程也是在 BertTokenizer 中进行,并由此产生 attention_mask。
BERT 默认使用 SDPA(Scaled Dot Product Attention)[2] 和绝对位置嵌入,在这种情况下需要将 attention_mask 的 shape 由 (b, l) 扩展为 (b, 1, l, l) 并使 attention_mask[:, :, :, :tl]=0,attention_mask 的其它值为负无穷,以得到 extended_attention_mask;其中 b 为 batch_size、l 为 token 序列长度、tl 为填充前的 token 序列长度。这样计算Softmax(q@k+extended_attention_mask) 后,就不会注意到填充位置。
2.3 BERT Encoder
默认的 BERT Encoder 与 Transformer Encoder[2] 完全一致。
2.4 Pre-training BERT
BERT Pre-training 的 loss 为 total_loss=masked_lm_loss+next_sentence_loss
2.4.1 Masked LM
这个预训练任务类似于“完形填空”,如图 1 左所示,对于每个 token 序列,训练数据生成器随机选择 15% 的 token 位置进行预测(softmax)和计算 cross entropy loss,即 mask 操作;对于在输入序列中被 mask 的 token, 80% 的 token 被替换为特殊 token [MASK]、10% 的 token 被随机替换为任意一个 token、剩下 10% 的 token 保持不变。
之所以不直接把所有被 mask 的 token 直接替换为 [MASK],是因为:在微调过程中不会出现 [MASK],BERT 的做法可以缓解预训练和微调间的不一致;而且这么做的另一个好处是:预测一个词汇时,模型并不知道输入对应位置的词汇是否为正确的词汇( 10% 概率),这就迫使模型更多地依赖于上下文信息去预测词汇,并且赋予了模型一定的纠错能力。
在这个预训练任务中,BERT Encoder 的输出先经过 2 个 Linear 层使hidden_size=vocab_size 后再 softmax。
2.4.2 NSP(Next Sentence Prediction)
NSP 任务中的一个样本由两个句子组成,如图 1 左所示,设一个样本由句子 A 和句子 B 组成,若 B 是 A 的下一个句子,则该样本的 label=0;若 B 是从语料库中随机选择的句子,则label=1。数据集中的正负样本各占一半。虽然 NSP 任务很简单,但它对 QA(Question Answering) 和 NLI(Natural Language Inference )很有用。
在这个预训练任务中,BERT Encoder 输出中的 [CLS] 经过 1/2 个 Linear 层, 使模型最终输出的 shape=(b, 2) 以计算 cross entropy loss。
3、总结
丰富的无监督预训练是语言理解系统的重要组成部分,它使低资源任务也能从深度单向结构中受益。[1] 的主要贡献在于进一步将这些发现泛化到深度双向结构中, 允许相同的预训练模型成功地解决广泛的 NLP 任务。
BERT 目前仍是 10 余个数据集上的最好的方法之一,且依然是 CoNLL 2003 (English)、CoQA、NCBI- disease 和 SciERC 上的 SOTA。作者开源的 BERT 的 Tensorflow 实现代码在:
https://github.com/google-research/bert
transformers 库中也有 BERT 的 PyTorch 实现: https://github.com/huggingface/transformers
参考文献
[1] Jacob Devlin, Ming-Wei Chang, Kenton Lee, and Kristina Toutanova. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. In NAACL, 2019.
[2] Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N Gomez,
Łukasz Kaiser, and Illia Polosukhin. Attention is all you need. In NIPS, 2017.