Bert模型预训练和微调(bert中文预训练模型)
一起学习bert预训练技术吧
Part 1 BERT模型和注意力机制
Bert Model
Bert历史简介
2018年谷歌开源了Bert模型
Bert是NLP领域里程碑式的模型,此后各类Bert变体层出不同,Bert模型开始屠榜 SuperGlue Benchmark(最SOTA的模型,需翻墙)
图 NLP发展
新范式:两个趋同(模型{transformer}趋同,预训练-微调趋同)
Bert - 网络架构总览
简单说:BERT网络结构:多层transformer的网络叠加
Transformer 网络架构
推荐直接看李沐大佬读paper\
Transformer 层的网络核心要素:
Multi-head attention (多头注意力)
FFN(全连接层)
LayerNorm(层归一化)
残差链接
图 bert模型(左)transformer模块(右)
Attention 机制
注意力机制的发展
2014年:机器翻译时代,注意力机制受关注
2017年:transformer出世,自注意力受关注
【Attention开山之作】《NEURAL MACHINE TRANSLATIONBY JOINTLY LEARNING TO ALIGN AND TRANSLATE》ICLR2015 --- Yoshua Bengio(三巨头)
开山之作中是如何实现Attention
关于Attention sorce的计算:
Step1: 关于注意力分数计算,简单说就是一个句子表征和每个h的相似度计算(使用点积形式表示相似度)构成的向量表示。
关于Attention distribution的计算:
Step2: 关于注意力分布计算,即使用softmax将Attention sorce映射成为概率总和为1的新表征,该新表征即为注意力权重。
关于Attention output的计算:
Step3: 关于注意力输出,即每个h和step2中计算得到的权重进行加权求和。
上述三幅图是 Seq2Seq中的注意力机制
注意力机制的一般形式(formulation)
开山之作中attention 是在seq2seq模型中的,那么如何抽离其中的注意力机制使用数学语言更加通用的表达注意力机制,这时候我们需要寻找一种一般实现形式,使得我们能更好地理解注意机制的原理,并且应用于其他形式。
【定义】:给定一组向量(key,value)键值对,以及一个向量query,注意力机制就是一种根据query
与key来计算values的加权平均的模块。{query attends to keys --> query注意到了keys 我们可以看成一种数据库的检索,拿query去和数据库里检索的keys进行关联性比较}
我们用大象装冰箱的方法来类比注意力机制的实现过程
Step1把冰箱门打开: 将query和key进行关联性评估,得到关联分数
关联性评估有很多种方法,之前介绍的都是点积形式,还有其他形式,介绍三种最常用的形式:
点积注意力机制(dot-product attention): 【最原始】
乘法注意力机制(multiplicative attention): 【transformer后基本全采用乘法形式,W可学习的参数矩阵】
加法注意力机制(additive attention): 【2014-2015年在机器翻译领域最流行的方式】
Step2把大象塞进去: 将关联分数归一化为分布
Step3把冰箱门关闭: 通过values和分布加权平均
自注意力机制 Self-Attention mechanism
我们能够用注意力机制得到一个句子的表征呢?
Attention建模句子表征
从按单个字角度:e.g. "it_ "的向量表征与句子中的所有词之家安计算注意力,由此更新其向量表征:
attention操作完全并行的使句子中词语两两间有了交互;
\
【矩阵形式】:验证矩阵维度
整个句子的一次self-attention:句子现有的表针记为,则有:
【开源工具】BERTVIZ 可视化bert的表征
Bert前的NLP模型
在2017年前,NLP领域多以LSTM网络为主,那么这一类RNN为什么被嫌弃?
RNN模型:
需要O(L)的复杂度使句子中所有词都有交互:长距离的语义依赖很难学习到(vanishaing gradients 梯度消失)。
并行性不好:前向传播和后向传播受到O(L)限制。
CNN模型:
CNN模型很高效
但是长距离的文本间的依赖很难由CNN建模得到:需要非常多层CNN叠加;
Self-Attention 需要的辅助部分
只有self-attention当然无法完成模型的构建,所以我们需要辅助构造
辅助1:句子顺序
位置编码(position encoding)
位置编码加在哪里?Embedding层 / 也可以每层都加
位置编码具体形式:正余弦位置编码(论文中)/学习驱动的位置编码(实际bert中)Pi随机初始化,同模型一起学习。
辅助2:非线性变换
加入全连接层:
公式:
注意这里的操作时单点的(pointwise):只由决定,而不接受句子中其他信息。
激活函数改进:更平滑的Relu函数(当你的输出为负数时,求偏导也不是零)
辅助3:多头(multi-head):
多头机制:
不同的head去关注不同上下文依赖
模型集成的效果(类似于Google的inception模型)
辅助4:scaling
Scaled dot-product attenrion:
在计算attention 分数时候除去一个因子(这个值一般都为64):
作用:模型维度较高的时候,向量点乘结果会比较大,这个时候由于经过softmax,梯度会变小,训练会变得不稳定。
是否可以证明scaling的作用?
辅助5:残差链接
多头注意力层和FFN都有一层残差连接
残差链接的意义:解决深度网络的梯度消失问题(原文)、改变损失函数形状,使得损失函数更加平滑。
辅助6:层归一化(LayerNormalization)
层归一化:对每个向量求其均值和方差;
CV中常用BatchNom,NLP中用LayerNom的原因是句长不固定
层归一化的意义:与残差连接的作用类似-->损失函数landscape变得更平滑(2018年)、梯度的方差变小了(2019年)
图为 BatchNormalization 和 LayerNormalization的异同
层归一化位置很重要:
对于post-LN,最后一层的参数的梯度满足:
对于pre-LN,则为(2020年,微软亚洲研究院):
梯度上界变小,训练会变得稳定。但文章只证明了位置重要,并尅有一一验证各种不同组合的效果,理论上共有70多种能够不同位置的组合。
层归一化位置:
AutoTrans提出采用自动机器学习的方法寻找layerNorm的最优组合;
E.g,在Mutli-30k上学到的新型transformer结构
网络优化技巧
多头注意力机制
scaling
残差链接
层归一化(LayerNormalization)
\
回顾
只有self-attention当然无法完成模型的构建,所以我们需要辅助构造
scaling的推导
blog.csdn.net/qq_37430422…
Part2 预训练和微调
预训练Knowledge Tree
预训练模型时代
预训练模型组Google提出的bert开始越来越大,参数数量早已突破亿级别,最新的GTP3具有百亿级别的参数,华为的盘古大模型和清华智源研究所的悟道2.0也已达到千亿级的参数,Google最新的switch Transformer更是达到万亿级别的参数量是目前最大的预训练模型。
预训练模型的的确确推动了学界和工业界的发展,带来了新的NLP的范式(缓解数据标注问题)
预训练任务
词向量(Word2vec)回顾
You shall know a word by the company it keeps! -- J.R.Firth (1957)
Pre-BERT预训练:词向量
词汇表;:每个单词对应一个编号;
每个词同时对应一个向量;
通过预测邻居词汇来训练;
skip-gram
CBOW;
Skip-gram:正式的,如果,则为单词的概率为:
s
词向量的局限性:
the complete meaning of word is always contextual,and no study of meaning apart from a complete context can be taken seriously. -- J.R.Firth (1957)
很难解决一词多意问题
固定的,无法表达上下文:
蚂蚁马上要上市了!
蚂蚁上树很好吃!
蚂蚁是群居的。
\
以词向量为基础的模型(word2vec based models)
2017年及以前,NLP模型的普遍形态:
词向量+encoder(如下图):
LSTM或者Transformer 模型通过训练集来学习如何提取上下文信息;
模式有何缺陷?
encoder部分随机初始化面对优化器压力大;
数据集要足够好,足够大,encoder才能学会如何提取上下文信息;
\
引出预训练任务
我们现在想要有效的预训练embedding+编码器。How?On What?
首先排除有标注的任务,利用大量存在的无标签文本数据;
无监督 --> 自监督:
自监督学习是深度学习的暗物质(暗物质很难被观测到,但却是宇宙物质的主要部分80%-95%) -- Yann LeCun(深度学习三巨头之一)
BERT预训练任务 - 掩码预测任务
Masked language modeling (MLM)
掩码预测任务:
(1)遮掩某个词(用"[MASK]"字符替换原词);
(2)句子输入BERT网络;
(3)预测这个词。
掩码预测任务可能存在什么问题?
下游任务,e.g.,预测一个句子的情感,是不会有[MASK]的;
在实现掩码预测任务的时候需要改进:
遮掩的字只占语料全体的字数的一小部分(15%);
在划分出的15%的预料中:
一小部分被遮掩,也就是替换为[MASK];
一部分随机替换为其他词(任然需要预测此处的token应该是什么);
一部分保留原词(仍然需要预测此处的token);
可以发现bert在经过这种语言模型训练后,天生就可以做一些任务,如句子纠错。
BERT预训练任务 - 下句预测
Next sentence prediction (NSP)
判断句子B是否是句子A的下文。
所以BERT句子的输入会使[CLS] A sent [SEP] B sent [SEP]的格式;
上下句关系保存在输入的[CLS]符号中,在预测时使用BertPooler提取整个输入序列的表征:
这里需要注意:不是直接拿【】的向量表这;而是要经过BertPooler这个模块,其中包含MLP,tanh操作得到一个向量表示,再输入到二分类层;
Subword tokenizer 子词标记化
BERT tokenizer
举例
句子“play the song little robin redbreast”再输入模型时变为“[CLS] play the song little robin red ##bre ##ast [SEP]”
为什么要使用subword tokenizer:
传统词表以英文单词为单位,一般较大,尾部词训练不充分
传统词表表示方法无法很好的处理位置罕见的词汇(OOV问题)
传统词tokenization方法不利于模型学习词缀之间的关系
E.g. 模型学到的“old”,“older”,and“oldest”之间的关系无法泛化到“smart”、“smarter”、“smartest”中去。
Character embedding 作为OOV的解决方法力度太细,且推理时候显存开销大
Subword力度在词语字符之间,能够较好地平衡OOV问题
常见的subword模型:Byte Pair Encoding(BPE),WordPiece
BPE算法(2016年):
生成词表:
(1)准备一个语料库;确定期望的Subword词表大小;
(2)将单词拆分为成最小单元。比如英文中26个字母加上各种符号,这些作为初始词表;
(3)在语料上统计单词内相邻单元对的频数,选取频数最高的单元对合并成新的Subword单元;
(4)重复第3步直到:达到第1步设定的Subword词表大小或下一轮迭代中token最高频数为1.
得到Subword词表后,针对每一个单词,我们可以采用如下的方式来进行编码:
将词典中的所有子词按照长度由大到小进行排序;
对于单词w,依次遍历排好序的词典。查看当前子词是否是该单词的子字符串( 贪婪的最长匹配), 如果是,则输出当前子词,并对剩余单词字符串继续匹配;
如果遍历完字典后,仍不匹配,则将剩余字符串替换为特殊符号输出,如”" ;
举例说明:
假设现在语料库中有如下词汇(及其频率):
观察词汇表大小在每一步如何变化
WordPiece算法(Bert采用的方法)
生成词表的步骤与BPE类似;加上“##”前缀表示token不作为一个完整单词的开始部分;
与BPE的最大区别在于,如何选择两个子词进行合并: BPE选择频数最高的相邻子词合并,而WordPiece选择能够提升语言模型概率最大的相邻子词加入词表;
假设假设句子S = (t1, t2... tn)由n个token组成,且假设各个子词之间是独立存在的
句子的语言模型似然值: logP(S)= 21=1 P(t;)
假设把相邻位置的和两个子词进行合并,合并后产生的子词记为z,此时对数似然值的变化为:
很容易发现,似然值的变化就是两个子词之间的互信息。
WordPiece举例:
英文:采用BERT-base-uncased tokenizer
30522个单词;英文转化为小写
E.g.,句子“play the song little robin redbreast” 经过BERT的wordpiece tokenizer后变为[ “play”,“the”,“song”,“little”,“robin”,“red”,“##bre”,“##ast”];
中文:采用Google Chinese BERT-base-uncased
21128个单词;
不区分大小写;
中文汉字拆开(split Chinese character);
E.g.,句子“我很喜欢一首歌:yesterday once more.” 处理为[ “我”,“很”,“喜”,“欢”,“一”,“首”,“歌”,“:”,“yes”,“##ter”,“##day”,“on”,“##ce”,“ more”,“.”];
Bert Eembedding层
嵌入层
Token embedding;
Segmentation embedding;
Position embedding;
常见的BERT版本
谷歌开源了两个版本的英文BERT和一个版本的中文BERT:
BERT-base:12layers,768-dim hidden states,12attention heads,110 million params。
BERT-large:12layers,1024-dim hidden states,16attention heads,340 million params。
中文BERT:
预训练语料:
英文模型:BooksCorpus(800 million words),English Wikipedia(2,500 million words)
中文维基百科:英文维基百科的十分之一;
预训练有多贵?
64 TPUchips for a total of 4 days.
微调相对很快!
微调任务
微调Knowledge Tree
BERT带来的SOTA
需要解决两个问题?
Q1:How to fineturn?
Q2:How to fineturn better?
BERT微调: 句子分类任务
Sentence Classification
分类任务:
将文本按照一定的规则分门别类;
文本分类任务应用场景广泛:
情感分析:评论意见/对话理解
主题分类:新闻舆情/学术文章
意图识别:搜索场景/对话场景
内容管理:不和谐内容鉴别/违规内容鉴别/歧视,暴力等内容鉴别
...
分类任务的为微调:
如何做?与上下句预测基本一致
句子的输入是[CLS]A sent[SEP]。
句子的表征如何转化为一个向量?
BertPlooler:[CLS]的向量表征,经过MLP,tanh操作得到一个向量表示,再输入到多分类层;
其他pooling操作;【max,avg,attention,capsule】
句子对分类
句子改写场景
问答/搜索场景
分类任务的微调:
损失函数:
交叉熵损失函数(CE)
微调的原理与一般的网络训练没有区别;
文本分类任务微调带来的巨大红利:
BERT微调:序列标注任务
Sequence labeling
序列标注任务:
对于待标注的一-段序列我们需要给每个预测-个标签(tag);
先定义Tag集合是;
中文分词:定义为{Begin, Middle, End, Single};
E.g., "风险基因协同的神经生物学作用” 被分词为:风险 基因 协同 的 神经 生物学 作用,转化为序列标注任务就是:风/B 险/E 基/B 因/E 协/B 同/E 的/S 神/B 经/E 生/B 物/M 学/E 作/B 用/E。
命名实体识别:标出句子中的实体;使用BIO标注模式;实体类型包括{PER, ORG}
E.g.乔/B-PER 布/I-PER 斯/I-PER 就/O 职/O 于/O 苹/B-ORG 果/I-ORG 公/I-ORG 司/I-ORG ;
词性标注(Part-of speech, POS tagging) :标注出词语的词性; 使用BIO标注模式;
E.g..jieba给出的:我/B-r 在/B-p 北/B- ns 京/-ns 天/B-ns 安/-ns 门/l-ns
序列标注任务
输入格式:[CLS] A sent [SEP]
方法一:每个token的向量表示经过线性层+softmax;
方法二:CRF层通过学习标签之间转移的模式,来规避“B-PER,I-ORG”这样的问题;
BERT微调:关系分类任务
relation classification
关系分类任务:
从非结构化文本中抽取出结构化知识;具体为区分头实体与尾实体之间的语义关系;
意义:构建知识图谱
方法一:
BERT表征句子;
得到两个实体的向量表示:实体多个词的表征经过pooling得到;
头尾实体向量拼接,再经过线性层分类;
方法二:
BERT的embedding层中加入关系位置编码
方法三:在句子加入新定义的字符,表示出头尾实体位置;字符使用[unused1]
样本不均衡问题初探
Sentence label task
样本不均衡场景:
Zip's law:在自然语言的语料库里,一个单词出现的频率与它在频率表里的排名成反比
二分类场景,正例出现次数少:e.g.,全员核酸检测中,阳性占别数量极小。
重采样(re-sampling):假设C是数据集类别数,n是类别i的样本数量,则从类别i中采样一个样本的概率:
instance-balanced sampling:每个样本被等概率的采到,即
Class balanced sampling:每个类别被抽到的概率相等
一般的重采样(re-sampling),假设,
重加权(re-weighting):以二分类为例
正常的交叉熵损失:
通过增加一个稀疏,来控制少数类别的样本对总loss的贡献:
Focal loss【2017年CV,目标检测】+类别的重加权:
作者:ArmorHTK
链接:https://juejin.cn/post/7035248578469560351