上一次我们已经从BERT代表四个词的角度宏观去了解了一下BERT,那这一步是不是要开始学习BERT原论文和原码了呢?不,考虑到综合的难道,这次从一个入门方向学习,对各个环节进行一些初步了解先。BERT从零详细解读,看不懂来打我_哔哩哔哩_bilibili
目录
1.BERT1整体模型架构
基础架构来自于Transformer的encoder层:(多个encoder叠在一起,没有decoder)
而transformer里面则是6个encoder作为编码端,6个decoder作为解码端:
下面来关注BERT的输入部分:
首先上图是transformer的encoder,分两部分,第一个是input embedding:做词的词向量,比如随机初始化或者word2vec(但是BERT最后没有w2vec),然后是positional encoding:位置编码(用正余弦函数去代表它)。
但是在BERT中的encoder分为了三个部分,token+segment+position embedding:
先看input粉色这一行,分为两种词,第一种是[CLS][SEP]这两个特殊词汇,第二种就是正常词汇(#ing是分词中产生的不用管),[CLS][SEP]的存在是因为BERT模型的预训练任务中有一个叫NSP任务(next Sentence Prediction),这个任务是处理两个句子之间关系的,所以[SEP]的任务是表示在之前的是一个句子、后面是另一个句子;预训练时[CLS]的输出向量会去接一个二分类器,去做一个二分类任务(约等于实现融合两个句子语义的任务)
但是注意:CLS是一个二分类任务,和编码句子信息的任务有一点区别,并不完全等同
不过苏剑林有篇文章把它应用于白话文的,效果还可以,所以真的还得看人怎么去做。
然后看三个部分:第一个部分:token embedding,就是对input的所有词汇包括正常、特殊词汇,都去做embedding,比如随机初始化;第二部分:segment embedding,因为我们处理两个句子,所以要对两个句子进行区分,前面这个句子cls到sep用0来表示,后面he到sep用1表示;第三部分:position embedding,注意,transformer中用正余弦函数,但是在BERT中我们使用随机初始化并且要模型自己去学习出来(参数训练),比如从下标0到511,让模型自己去把每个位置的embedding确定好
2.如何作预训练:MLN+NSP
MLM(mask language model)针对无监督(因为随便选的文本没有标签嘛),然后有两种无监督目标函数比较受重视: AR AE
例子:(AR模型这样显然用的单侧信息)
目的:预训练时让模型去进行文本重建,模型必须从周围的信息中推断出这个mask是什么,并无限接近原本词汇
mask模型缺点:
这里这个概率公式可以看出它认为吃和饭,也就是两个mask之间是相互独立的,但是实际上这两个mask是有关系的。
最后论文对mask处理的方法如下:(效果比较好)
mask代码 :
第一个if,如果随机的出来的(0-1)小于0.8那就把它mask掉,剩下20%中的50%,也就是10%不变,10%随机替换一个单词(注意可能抽取出来的单词和要被替换词本身一样)
下面讲NSP任务。最重要的是去理解样本构造模式
1.连续段落说明来自同一个主题下有序的内容
2.是不同主题下的随机抽取
而主题预测是很简单的任务,这样合并就导致NSP任务简单程度上升,效果不是很好,而改进的说明alBERT中都抛弃了主题预测,同时负样本也在同一个主题中选(就是次序颠倒)
3.如何微调BERT
A句子分类B单个句子分类C问答D序列标注任务
比如D序列标注就是对所有token输出进行一个 softmax,去看属于实体样本哪一个.B对单个文本分类,就是利用CLS进行输出微调,二分类、多分类。A本质是一个文本匹配任务,把两个任务拼接起来,用CLS输出去判断是否相似,1相似0不相似。
4.如何提升BERT下游任务效果
一般做法:
1.获取谷歌中文BERT 2.基于任务数据进行微调
但是想要获得更好性能就需要一些tricks
先介绍一个post-training:(把上面两个步骤分为四个步骤去做)
其中,第一步直接用谷歌中文BERT ,
第二步language model 继续训练,也就是领域自适应和迁移,
第三步就是说大量微博文本中其实有很多不相关数据,所以更聚焦主题,用和任务相关的数据继续去训练LM
第四步,任务数据做微调。
一般经验是先做领域再做任务的再做微调,性能更好,可以提高1-3个点
那在第二步中有什么trick可以用呢?
因为原始模型每次mask的都是同一个地方,所以不太好,要动态mask ,然后实体词没有或者不准确时可以做n-gram的mask,
5.脱敏数据中如何使用BERT