BERT的出现使我们终于可以在一个大数据集上训练号一个深的神经网络,应用在很多NLP应用上面。
Deep Bidirectional Transformers
for Language Understanding深的双向Transformer
与ELMo的区别:ELMo基于RNN,双向,在运用到下游的任务时需要做出一些调整。BERT基于Transformer,只需要改最上层。
与GPT的区别:GPT基于Transformer解码器,单向,用左边的上下文信息预测。BERT基于Transformer编码器双向。
BERT的好处:简单且效果好,在11个NLP任务上都比较好。
在使用预训练模型做特征表示的时候,通常有两种策略:
基于特征
ELMo,对于每一个下游任务,构造一个与之相关的神经网络,RNN架构,将预训练好的(比如一个词嵌入矩阵)作为额外特征一起作为输入,输入到模型里面,达到训练模型比较容易的目的。
简单来说:这是大多数NLP最常用的使用预训练模型的方法,把学到的特征和输入一起放进去。
基于微调
GPT,引入了最小的特定于任务的参数,预训练好的参数进行微调
这两种方法在预训练及之后都使用相同的目标函数(GPT也不全是吧),且都使用单向的语言模型进行学习。(预测未来)
Bert主要想法:预测未来---->完形填空,用masked language model,带掩码的语言模型
除此之外,Bert还关注了句子层面的信息:给两个句子,判断这两个句子是不是相邻的。(NSP)
贡献点:双向信息的重要性(句子从左看到右,从右看到左)
在BERT上做微调
效果很好
代码开源
无监督
的预训练很重要(在计算机视觉领域,在没有标签的数据集上做训练比在有标签的数据集上做训练效果会更好);
主要贡献是将这些发现进一步推广到深度双向架构,使相同的预训练模型能够成功处理一系列的 NLP 任务。
在本篇论文的结论中最大贡献是双向性(在写一篇论文的时候,最好有一个卖点,而不是这里好那里也好)。
选了选双向性带来的不好是什么?做一个选择会得到一些,也会失去一些。
缺点是:与GPT(Improving Language Understanding by Generative Pre-Training)比,BERT用的是编码器,GPT用的是解码器。BERT做机器翻译、文本的摘要(生成类的任务)不好做。
但分类问题在NLP中更常见。
完整解决问题的思路:在一个很大的数据集上训练好一个很宽很深的模型,可以用在很多小的问题上,通过微调来全面提升小数据的性能(在计算机视觉领域用了很多年),模型越大,效果越好(很简单很暴力)。
2.1非监督的基于特征的一些工作如词嵌入,ELMo
2.2非监督的基于微调 的一些工作如GPT
2.3在有标注
的大数据集上训练好的模型,做迁移学习(CV上用的很多,在ImageNet上训练好,应用到其他任务,但NLP上还不是很理想)
注:BERT和后面的文章说明了在无标注
的大数据集上训练的效果要比在有标注
的数据集上训练出来的效果更好。同样的思想现在也在CV中应用了。
预训练
在一个无标注的数据集上进行训练
微调
同样使用一个BERT模型,但其参数初始化成预训练中的BERT模型,所有的权重在微调时都会参与训练(用有标注数据集)
每个下游任务都会创建一个新的BERT模型
multi-layer bidirectional Transformer encoder
多层双向Transformer 编码器,和原始的Transformer没什么区别。
细节:改了三个参数
L:Transformer 块的个数
H:FC的隐藏层大小
A:多头注意力头的大小
BERT-BASE(12,768,12)
BERT-LARGE(24,1024,16)
BERT模型的复杂度和L是线性关系,和H是平方关系,L变成2倍,(1024 * 1024)/(768 * 768)≈ 2
怎么通过超参数L、H、A计算出可学习参数的大小,顺便回顾一下Transformer
参数主要来自于两块:
输入有两种
Wordpiece切词:
空格切词,一个词当作一个token会导致词典很大,所以对于出现概率不大的单词,只保留它的子序列(词根),切完只有30000个
如何合成两个句子?
每一个Sequence的第一个词都是[CLS],BERT希望最后的输出代表的是整个句子层面的信息,这就是Attention厉害的地方了。
两个句子合在一起怎么进行区分呢?
每一个词元(token)进入BERT之后如何被表示成Embedding呢?
Token:词嵌入
Segment:在那个句子中
Position:位置 (Transformer中位置编码是人定的,BERT中是学出来的)
上述的都是预训练和微调相同的部分
下面是不同的部分
在预训练的过程中,他们以15%的概率把一个词变成[Mask]([CLS]和[SEP]除外)也即一个带掩码的语言模型,然后进行训练。但在微调的过程中,也没有Mask这个东西啊。
个人理解:预训练采用拿出一篇完型填空让机器学的方式,然后微调用在其他任务中。两个阶段的目标函数都不一样。
所以预训练和微调所看到的数据会有一点不一样。
咋解决呢?
80%的概率是真的变成了[Mask]
10%随即替换成了一个别的词(噪声)
10%什么都不变,但是标记一下这是我要预测的词(和微调时的情况一样)
输入两个句子,判断这两句话是不是连着的
BERT这种只有编码器的结构,相比于编码器解码器结构也有好处:编码器解码器两个输入互相看不见,但是BERT可以,但缺点也有,不能像Transformer做机器翻译。
应用在在下游任务
拿到[CLS]后,学习一个输出层 W W W, s o f t m a x ( C W T ) softmax(CW^T) softmax(CWT)
问题描述:给一段话,问一个问题,答案隐藏在这段话中。
所以就是截取片断,对每个词元判断是不是答案的开头和答案的结尾。具体公式略
略
和预训练差不多
接下来讲了模型中每个模块对整体的影响以及参数个数对模型的影响,企图增强模型的可解释性。
再接下来试了一下不微调,发现效果没有微调好。。。