LM模型详解
==================================================================
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
Jacob Devlin,Ming-Wei Chang, Kenton Lee, Kristina Toutanova, NAACL-HLT 2019
摘要:
引入一种称为BERT的新型语言表示模型,代表来自Transformer的双向编码器表示。不同于最近的
语言表示模型(Peters 2018a; Radford 2018),BERT被设计为未标记文本的预训练深层双向表示,
通过所有层的左右上下文联合调节。结果,经过预训练的BERT模型只需要增加一个额外的输出层就
可以微调,以此创建适用于各种任务(例如问题解答和语言推断)的SOTA模型,且无需进行特定于
任务的重要架构修改。 (译者注:1)Bert双向编码器,Transformer原生就是双向编码器,双向
是相对于解码器的遮挡式左端自注意版本; 2)训练模型最难的不是模型本身而是数据。微调只需要
一个额外的输出层,这也意味着微调BERT模型时,只需要少量标签数据就能达到训练的目标,这是
非常难能可贵的!)
BERT概念简单但实验效果强大。它在11种NLP任务上获得了SOTA结果,将GLUE得分提高到80.5%
(绝对提高7.7%),MultiNLI准确度提高到86.7%(绝对提高4.6%),SQuAD v1.1问答测试F1达到
93.2(绝对值提高1.5分)和SQuAD v2.0测试F1达到83.1(绝对值提高5.1点)。
3 Bert
我们将介绍BERT及详细实现。框架分为两个步骤:预训练和微调。在预训练期间,通过不同的预训练
任务对未标记的数据进行模型训练。为了进行微调,首先使用预训练参数初始化BERT模型,然后使用
来自下游任务的标记数据对所有参数进行微调。每个下游任务都有单独的微调模型,即使它们使用相同
的预训练参数进行了初始化。Figure 1 中的问题应答将作为本节的运行示例。
BERT的一个独特功能是统一模型架构能够跨越不同任务,因此预训练的模型架构和最终的下游模型之间
的差异很小。
模型架构
-
BERT的模型架构是多层双向Transformer编码器,基于 Vaswani( 2017 )描述的,发布在tensor2tensor库
中的原始实现。 因为Transformer使用已经很普遍,并且我们的实现几乎与原始实现相同,我们将省略对
模型架构的详尽背景说明,读者可参考 Vaswani( 2017 )及优秀的指南,例如“The Annotated Transformer”。
论文中,标记层数(即,Transformer Blocks)为L,标记隐藏层大小为H,标记自注意头数为A。
我们主要报告两个不同大小模型的结果: (L= 12,H = 768,A = 12,Total Parameters = 110M),
(L = 24,H = 1024,A = 16,Total Parameters = 340M)。
为了进行比较,选择与OpenAI GPT相同的模型大小。但是,重要的是,BERT Transformer
使用双向自注意,而GPT Transformer使用受限的自注意,每个分词只能关注其左侧的上下文。
3.0 输入/输出表示形式
为了使BERT处理各种下游任务,我们的输入表示形式可以在一个分词序列中明确表示单个句子和
一对句子(例如 <Question,Answer>)。在整个工作中,“句子”可以是任意跨度的连续文本,
而不是实际的语言句子。“序列”指BERT的输入分词序列,它可以是一个句子或两个句子包装在一起。
我们使用WordPiece嵌入(Wu et al.,2016),[subword embeding: BPE,Wordpiece etc]含有30,000个分词词汇表。每个序列的第一个符号
总是特殊分类标记([CLS])。与此标记对应的最终隐藏状态用作分类任务的聚合序列表示。
一对句子打包在一起形成单个序列。我们通过两种方式区分句子。首先,我们使用特殊符号([SEP])
分隔它们。其次,我们向每个分词添加学习的嵌入,以指示它是属于句子A还是句子B。
如Figure 1所示,我们(建立对应关系)将输入嵌入表示为E,将特殊符号[CLS]的最终隐藏向量表示为,
输入分词的最终隐藏向量为
。
对于给定的分词,其输入表示形式是通过将相应的{分词,分段和位置嵌入}求和来构造的。
在Figure 2中可视化显示这种构造。(与原始的transformer 有何不同?)
-
-
-
- Figure 1 左侧
3.1 预训练BERT
与Peters( 2018a )和 Radford ( 2018 )不同 ,我们没有使用传统的从左到右或从右到左的语言模型
对BERT进行预训练。作为代替,我们使用本节中描述的两个非监督任务对BERT进行预训练。此步骤展示
在Figure 1左侧。
任务1:遮挡的语言模型,MLM
-
直观上,有理由相信,深层双向模型无论如何要比从左至右模型,或者浅层连接的从左至右,从右至右的
模型更强大。不幸的是,标准条件语言模型只能从左到右或从右到左进行训练,因为双向条件将允许每个
单词间接地“看到自己”,并且该模型可以简单地预测目标语言中的目标单词在多层上下文中。
为了训练深层的双向表示,我们简单地随机遮挡某个百分比的输入分词,然后预测这些遮挡的分词。我们
将此过程称为“遮挡的LM”(MLM),尽管在文献中通常将其称为“完形填空任务(Cloze task) ”
( 泰勒,1953年 )。在这种情况下,如在标准LM中一样,和遮挡的分词相对应的最终隐藏向量喂给关于
词汇表的输出softmax。在我们所有的实验中,我们随机遮挡每个序列中所有WordPiece分词的15%。
我们仅预测被掩盖的单词,而不重构整个输入。这与降噪自动编码器( Vincent 2008 )相反。
虽然上述可以使我们获得一个双向预训练模型,但缺点是我们在预训练和微调之间造成了不匹配,因为遮挡
([MASK])分词在微调过程中不会出现。为了缓解这种情况,我并不总是用实际的遮挡([MASK])分词
代替“被遮挡”分词。训练数据生成器随机选择15%分词位置进行预测。假若选择了i-th分词,我们将用
下述(概率)方式替换i-th分词:
(1)80%的概率使用遮挡([MASK])分词
(2)10%的概率使用随机分词
(3)10%的概率使用不变的i-th分词。
然后, 将用于预测具有交叉熵损失的原始分词。在附录 C.2中,我们将比较此过程的不同变体。
任务2:下一个句子预测,NSP
-
许多重要的NLP下游任务,例如问题回答(QA)和自然语言推断(NLI)都基于理解两个句子之间的关系,
这不能被语言模型直接捕获。为了训练模型能够理解句子关系,我们预训练二值化NSP任务,可以从任何
一种单语语料库轻松生成。具体来说,为每个预训练例子选择句子A和B时,(即预测A句的NSP), 有50%
的概率预测为B(标记为 IsNext ),另外50%的概率预测为语料库的随机句子(标记为 NotNext )。
如图所示 1 ,C用于预测(NSP)。尽管很简单,但我们在5.1节证明此任务的预训练对QA和NLI都非常
有益。
NSP任务与表示学习目标密切相关,如 Jernite( 2017 ) 和 Logeswaran and Lee( 2018 )。但是,
在先前的工作中,只有句子嵌入被传输到下游任务,在这里其中BERT传输所有参数以初始化最终任务
模型参数。
预训练数据 预训练过程在很大程度上遵循了有关语言模型预训练的现有文献。对于预训练语料库,我们
使用BooksCorpus(800M单词)( Zhu 2015年 )和English Wikipedia(25亿 单词)。对于Wikipedia,
我们仅提取文本段落,而忽略列表,表和标题。关键是要使用文档级语料库而不是改组的句子级语料库,
诸如Billion Word Benchmark(Chelba 2013),目的是抽取长连续序列。
-
-
- Figure 1 右侧
3.2 微调BERT
微调很直接,因为Transformer的自注意机制允许BERT建模许多下游任务——无论是单个文本还是文本对
——通过交换适当的输入和输出。对于涉及一对文本的应用,常规模式是在应用双向交叉注意力之前,
对文本对进行独立编码,例如Parikh等 ( 2016 ); Seo等( 2017年 )。 作为替代,BERT而是使用
自注意机制来统一这两个阶段,因为自注意高效编码连接的文本对包括了两个句子之间的双向交叉注意力。
对于每个任务,我们只需将特定于任务的输入和输出插入BERT,然后对所有参数进行端到端微调。
在输入端,来自预训练的句子A和句子B类似于(1)释义中的句子对,(2)蕴含的推断假设文本-前提文本
句子对,(3)问题应答中的疑问句对和(4)文本分类和序列标记中退化的句子对。
在输出端,将分词表示喂给输出层,实现分词级任务,例如序列标记或问题回答;将[CLS]表示喂给
输出层,实现分类,例如蕴含或情感分析。
与预训练相比,微调相对容易。从完全相同的预训练模型开始,论文中所有的结果可以被复现,在上
Cloud TPU最多1小时 ,而在GPU上最多几个小时。我们将描述特定于任务的详细信息对于应第4节的小节 。
更多详细信息见附录 A.5 。
4.实验
使用四个benchmark:GLUE,SQuAD1.1,SQuAD2.0,SWAG, 11项NLP任务进行实验。
5.消融研究
对BERT的多个方面进行消融实验,以更好地了解它们的相对重要性。
5.1预训练任务的的效果
5.2模型规模的效果
5.3Bert基于特征的方法
6.结论
由于语言模型迁移学习,最近的实验提升证明丰富的,无监督的预训练是许多语言理解系统必不可少的部分。
尤其是,这些结果甚至使低资源任务受益于深层单向架构。我们的主要贡献是进一步推广这些关于深层双向
架构的发现,允许相同的预训练模型成功处理广泛的NLP任务。
附录:
A.Bert另外的细节
预训练任务,预训练过程,微调过程,比较BERT,ELMO,GPT,图示微调不同的任务。
B.实验搭建的细节
GLUE 9项测试。
C.消融实验细节
===================
Bert源代码实现
Blog Open Sourcing BERT: State-of-the-Art Pre-training for Natural Language Processing
Friday, November 2, 2018
https://ai.googleblog.com/2018/11/open-sourcing-bert-state-of-art-pre.html
google-research / bert https://github.com/google-research/bert
source code analysis: http://fancyerii.github.io/2019/03/09/bert-codes/
Pytorch implementation of Google AI's 2018 BERT https://github.com/codertimo/BERT-pytorch
huggingface / transformers https://github.com/huggingface/transformers/tree/master/src/transformers/models/bert
-
-模型参数:
层数12, 头数12,词汇表30552,
max_position_embeddings: The maximum sequence length, 最大序列长度 512
hidden_size: Size of the encoder layers and the pooler layer. 隐藏层大小768, 指编码层和池化层大小
intermediate_size: The size of the "intermediate" (i.e., feed-forward),FFNN网络层的大小3072
激活函数:
Gaussian Error Linear Units (GELUs), https://arxiv.org/abs/1606.08415
def gelu(x):
"""Gaussian Error Linear Unit.
This is a smoother version of the RELU.
Original paper: https://arxiv.org/abs/1606.08415
Args:
x: float Tensor to perform activation.
Returns:
`x` with the GELU activation applied.
"""
cdf = 0.5 * (1.0 + tf.tanh(
(np.sqrt(2 / np.pi) * (x + 0.044715 * tf.pow(x, 3)))))
return x * cdf
优化器: AdamW, AdamWeightDecayOptimizer
Bert实现 https://github.com/google-research/bert/blob/master/optimization.py
Decoupled Weight Decay Regularization, https://arxiv.org/abs/1711.05101
Github https://github.com/loshchil/AdamW-and-SGDW
===================
Fine-tuning with BERT
Sentence (and sentence-pair) classification tasks
This example code fine-tunes BERT-Base
on the Microsoft Research Paraphrase Corpus (MRPC) corpus,
which only contains 3,600 examples and can fine-tune in a few minutes on most GPUs.
1) github clone到github目录, 使用run_classifier.py脚本:
https://github.com/google-research/bert
2)使用BERT-Base, Uncased 模型。下载,放入bert_base目录:
BERT-Base, Uncased: 12-layer, 768-hidden, 12-heads, 110M parameters
https://storage.googleapis.com/bert_models/2018_10_18/uncased_L-12_H-768_A-12.zip
3)使用glue MRPC数据。下载 放入 glue/MRPC目录, 一共6个数据文件如下:
Step1: fine-tunes
python run_classifier.py
--task_name=MRPC \
--do_train=true \
--do_eval=true \
--data_dir=..\glue\MRPC \
--vocab_file=..\bert_base\uncased_L-12_H-768_A-12\vocab.txt \
--bert_config_file=..\bert_base\uncased_L-12_H-768_A-12\bert_config.json \
--init_checkpoint=..\bert_base\uncased_L-12_H-768_A-12\bert_model.ckpt \
--max_seq_length=128 \
--train_batch_size=8 \
--learning_rate=2e-5 \
--num_train_epochs=3.0 \
--output_dir=..\glue\mrpc_output
Step2: Prediction from classifier
fine-tunes模型写入 ..\glue\mrpc_output, 利用这个模型预测。
python run_classifier.py \
--task_name=MRPC \
--do_predict=true \
--data_dir=..\glue\MRPC \
--vocab_file=..\bert_base\uncased_L-12_H-768_A-12\vocab.txt \
--bert_config_file=..\bert_base\uncased_L-12_H-768_A-12\bert_config.json \
--init_checkpoint=..\glue\mrpc_output\model.ckpt-1375 \
--max_seq_length=128 \
--output_dir=..\glue\mrpc_output
预测结果:
==================================================================
DistilBERT, a distilled version of BERT
NeurIPS 2019
-大模型在实时和/或受限的计算训练或推理。提出了一种预训练较小的通用语言表示模型DistilBERT的方法,
但在预训练阶段利用了知识蒸馏,达到的效果: 模型尺寸减少40%,语言理解能力保留97%,速度提升60%。
为了利用较大的模型在预训练期间学到的归纳偏差,引入了三重损失:
蒸馏Loss,语言模型Loss,余弦距离Loss。
2 知识蒸馏:(Bucila 2006 ; Hinton,2015)
压缩技术,其中训练紧凑模型(学生)以重现较大模型(教师)或模型集合的行为。
在监督学习中,通常会训练分类模型,以通过最大化金标签的估计概率来预测实例类。因此,标准的训练
目标包括最小化模型的预测分布与训练标签的one-hot经验分布之间的交叉熵。在训练集上表现良好的模型
将在正确的类别上以高概率预测输出分布,而在其他类别上以接近零的概率预测输出分布。但是其中一些
“接近零”的概率比其他概率大,部分反映了模型的泛化能力以及模型在测试集上的表现如何。
训练损失。 对学生进行的训练是针对教师的软目标概率的蒸馏损失:
-,t,s分别为教师,学生的概率估计。
通过充分利用教师的全部分布,此Loss目标函数可产生丰富的培训信号。遵从(Hinton,2015)使用,
softmax-temperature公式:
-,T 控制输出分布的平滑度,z是对应分类的模型分数。
在训练时相同温度T应用于学生和老师,而在推断时,T设置为1以恢复标准softmax。
引入了三重损失, 蒸馏Loss,语言模型Loss,余弦距离Loss,增加余弦嵌入损失有利于使学生和老师的
隐藏状态向量的方向对齐。
蒸馏Loss: 先计算teacher model 和student model的soft label损失, 再计算交叉熵;
语言模型Loss: hard label 损失函数,BERT 的 MLM 损失,删除了NSP;
余弦距离Loss: teacher 和student hidden state 的余弦相似度,两个模型的相似性;
最终 Loss函数是三者的线性组合:Loss= 5.0*+2.0*
+1.0*
-
-图片:https://nni.readthedocs.io/zh/latest/TrialExample/KDExample.html
-
3.DistilBERT:BERT的简化版本
学生架构。 学生-DistilBERT-具有与BERT相同的通用架构。分词类型的嵌入和池化被移去,模型层数被
压缩一半。而Transformer使用的大部分结构中在现代线性代数框架是高度优化的,我们的研究表明,
张量最后一个维度(隐藏尺寸)的变化对计算效率(对于固定参数预算)的影响比对其他因素(例如层数)
的变化影响小。因此,我们专注于减少层数。
学生初始化。除了前面描述的优化和架构选择之外,我们的训练过程中的一个重要因素是为学生子网收敛
找到正确的初始化方法。利用教师和学生网络之间的共同维度,我们通过从老师的两层中选取一层进行
学生初始化。
蒸馏法。我们应用了最佳实践来训练BERT模型Liu(2019)。这样,在非常大的批次上通过梯度累积
(每批次最多4K个示例)蒸馏DistilBERT, 训练使用了动态遮挡,没有使用下一个句子预测。
数据和计算能力。我们在与原始BERT模型相同的语料库上训练DistilBERT:结合Wikipedia和Toronto Book
语料库(Zhu 2015)。DistilBERT 需要在8x 16GB V100 GPU 训练大约90个小时。作为比较,RoBERTa模型
(Liu ,2019) 需要在1024* 32GB V100上进行为期1天的训练。
性能: DistilBERT 比Bert快71%,训练参数为207 MB 。-
==================================================================
Ref,
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
https://www.reddit.com/r/MachineLearning/comments/9nfqxz/r_bert_pretraining_of_deep_bidirectional/
图解BERT模型, 图解BERT模型:从零开始构建BERT-腾讯云开发者社区-腾讯云
站在BERT肩膀上的NLP新秀们(PART I) 站在BERT肩膀上的NLP新秀们(PART II) 站在BERT肩膀上的NLP新秀们(PART III)
NLP常见任务 https://www.cnblogs.com/databingo/p/10182663.html
BERT fintune 的艺术 BERT fintune 的艺术 - 知乎
Tensorflow Attention Seq2Seq模型 Tensorflow源码解读(一):Attention Seq2Seq模型 - 知乎
BERT 瘦身之路:Distillation,Quantization,Pruning BERT 瘦身之路:Distillation,Quantization,Pruning - 知乎
BERT蒸馏完全指南|原理/技巧/代码 BERT蒸馏完全指南|原理/技巧/代码
BERT Does Business: Implementing the BERT Model for Natural Language Processing at Wayfair
About Wayfair | BERT Does Business: Implementing the BERT Model for Natural Language Processing at Wayfair
-