Bidirectional Encoder Representations from Transformers,即Bert;
文本嵌入模型Bert,在许多自然语言处理任务上表现优秀,本节主要包括:
问答任务、文本生成、句子分类的自然语言处理任务重都有良好表现,其成功在于它是基于上下文的嵌入模型(有别于通过建立词在语言空间中的向量映射的模型);
有上下文嵌入模型 vs 无上下文嵌入模型
而Bert就是一个基于上下文的模型,先理解语境(Bert会将词与句子中的所有单词联系起来),然后根据上下文生成该词的嵌入值;
BERT是基于Transformer模型的,可以把BERT看做是只有编码器的Transformer;
我们已经知道Transformer编码器会输出句子中每个词的特征值,且Transformer编码器是双向的,它可以从两个方向读取一个句子;
一个句子送入编码器,编码器就会利用多头注意力层来理解每个单词在句中的上下文,并输出特征值;每个单词的特征向量大小是前馈网络层的大小(即隐藏神经元的个数),假设是768,那么每个单词的特征向量大小也是768
,这个768同样也应该是用于生成QKV矩阵的权重矩阵中权重向量的维度;
Bert的两种标准配置:
BERT-base:
每层编码器都使用12个注意力头
;BERT-large:
其他的一些小型配置:
更小配置的BERT可以适配到更有限的资源,但标准BERT可以得到更准确的结果;
对模型m使用一个大型数据集针对某个具体任务进行训练,并保存训练模型;再对一个新任务,使用已经训练过的模型权重来初始化m(不使用随机初始化从头训练),并根据新任务调整(微调)其权重;
BERT模型在一个巨大的语料库上针对两个特定任务进行预训练:掩码语言模型构建、下句预测;训练得到的模型,在一个新任务中,比如问答任务,载入预训练参数,微调权重即可;
一种特殊的词元分析器,遵循子词词元化规律;
示例:Let us start pretraining the model,使用WordPiece标记的结果为:
tokens = [let, us, start, pre, ##train, ##ing, the, model]
具体过程:
BERT词表有3万个标记,本例中词表中没有pretraining这个词,因此将该词进行拆分,##
表示该词是一个子词,其前面还有其他的词;
在将数据输入BERT前,需要使用3个嵌入层将输入转换为嵌入:标记嵌入层、分段嵌入层、位置嵌入层;
标记嵌入层:
[CLS]
标记到第一个分词并掩码
后的句子开头(只在第一个开头加);[SEP]
标记到每个分词并掩码
后的句子末尾(每一句结尾都要加);[CLS]
用于分类任务,[SEP]
表示每个句子结束;分段嵌入层:
如果只有一个句子,句子的所有标记都将被映射到嵌入EA;
位置嵌入层:
输入 | [CLS] | Pairs | is | a | city | [SEP] | I | love | it | [SEP] |
---|---|---|---|---|---|---|---|---|---|---|
+标记嵌入 | E[CLS] | EPairs | Eis | Ea | Ecity | E[SEP] | EI | Elove | Eit | E[SEP] |
+分段嵌入 | EA | EA | EA | EA | EA | EA | EB | EB | EB | EB |
+位置嵌入 | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8 | E9 |
现在就可以将结果送入BERT了;
BERT模型在一个巨大的语料库上针对两个特定任务进行预训练:
语言模型构建:
语言模型构建任务是指通过训练模型来预测一连串单词的下一个单词,可以把语言模型分两类:
自动回归式语言模型有以下两种方法:
举例:Pairs is a city. I love it.
自动回归式语言模型本质上是单向的,它只能沿着一个方向阅读句子;
自动编码式语言模型:自动编码式语言模型是双向的,可以同时利用正向预测和反向预测的优势,预测时同时从两个方向阅读句子;这样能更清晰地理解句子,能输出更好的结果;
掩码语言模型构建:
BERT是自动编码式语言模型,在掩码语言模型构建任务中,给定一个输入句,随机掩盖其中15%的单词,并训练模型来预测被掩盖的单词;
工作原理:
[MASK]
替换了city,就可以训练BERT模型来预测被掩盖的词;这里会引入一个小问题:
[MASK]
来训练BERT,但在下游任务微调时,输入中不会有任何[MASK]
标记,这将导致BERT的预训练方式和用于微调的方式不匹配;解决办法是使用80-10-10规则:
[MASK]
标记来替换实际词标记;在分词和掩码
后,将标记列表送入标记嵌入层、分段嵌入层和位置嵌入层,得到嵌入向量;再将嵌入向量送入BERT,BERT将输出每个标记的特征向量
输入 | [CLS] | Pairs | is | a | city | [SEP] | I | love | it | [SEP] |
---|---|---|---|---|---|---|---|---|---|---|
输入 | [CLS] | Pairs | is | a | [MASK] | [SEP] | I | love | it | [SEP] |
+标记嵌入 | E[CLS] | EPairs | Eis | Ea | Ecity | E[SEP] | EI | Elove | Eit | E[SEP] |
+分段嵌入 | EA | EA | EA | EA | EA | EA | EB | EB | EB | EB |
+位置嵌入 | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8 | E9 |
输出标记 | R[CLS] | RPairs | Ris | Ra | Rcity | R[SEP] | RI | Rlove | Rit | R[SEP] |
若使用BERT-base配置,12层编码器、12个注意力头、768个隐藏神经元,输出的每个标记的特征向量大小也是768;
那么如何使用这些特征向量来预测被掩盖的词呢?
R[MASK]
送入使用softmax激活函数的前馈网络层,输出词表中所有单词为掩盖单词的概率;掩码语言模型构建任务也被称为完形填空任务
;除了对输入标记进行掩码处理,还可以使用另一种方法,即全词掩码
;
全词掩码:
下句预测:
下句预测(next sentence prediction)是一个用于训练BERT模型的策略,它是一个二分类任务;
在该任务重,我们想BERT模型提供两个句子,预测第二个句子是否是第一个句子的下一句;通过执行下句预测任务,BERT模型可以理解两个句子之间的关系;
可以从任何一个单一语言语料库中生成数据集:
输入句子对,预测标签;
具体过程:
[CLS]
第一个句子分词 [SEP]
第二个句子分词 [SEP]
;将[CLS]标记的特征值通过softmax激活函数将其送入前馈网络层
,然后返回句子对分别是isNext和notNext的概率;这里之所以只需要取
[CLS]
标记的嵌入,是因为该标记基本上汇总了所有标记的特征,所以它可以表示句子的总特征;
同样需要通过多次训练迭代,更新优化BERT的前馈网络层和编码器层权重,使之最优,这样模型才能返回正确的概率;
BERT使用多伦多图书语料库(Toronto BookCorpus)和维基百科数据集进行预训练,我们已将了解了两种训练任务:掩码语言模型(完形填空)和下句预测任务,现在需要准本数据集;
512
;[CLS]
标记在第一句开头,将[SEP]
标记在每句结尾;同时
对句子B是否是句子A的下一句进行分类;BERT使用256个序列批量(Batchsize=256)进行100w步的训练,使用Adam优化器,lr=1e-4、β1=0.9、β2=0.999,预热步骤设置为1w;
关于预热步骤:我们知道在训练的初始阶段可以设置较高学习率,使最初迭代更快接近最优点,后续迭代中,则调低学习率使结果更加准确,因为在最初,权重值远离收敛值,较大幅度的lr变化是可接受的,但后续如果已经接近收敛值,仍采样相同的变化幅度,就容易错过收敛值,这就是学习率的调整策略;而预热步骤,是通过1w次迭代,将学习率由0线性的提高到1e-4,1w之后的迭代,再随着误差接近收敛,线性地降低学习率;
在训练中还对所有层使用了随机节点关闭(dropout),每层关闭节点概率为0.1,激活函数使用GeLU(即高斯误差线性单元Gaussian Error Linear Unit);
看着有点像relu,但是在小于0的一部分x轴的y值是较小的负值,实际曲线像一个对号;
预训练后,BERT模型就可以应用于各种任务;
子词词元化算法:BERT所使用的,在处理未登录词方面非常有效;
假设有一个训练数据集,更具它我们创建一张词表(分词 添加):
代替;#
号,表示和前面的词相关联;常见的三种子词词元化算法:
对于出现最频繁的符号对(合并),检查每个符号对的语言模型(在给定的训练集上训练)的相似度,合并相似度最大的符号对;
算法步骤:
词表构建后,就可以用来做文本标记。