BERT
BERT的层级结构
BERT类的模型基本都由以下几种层级对接而成.
输入层
Embedding层
主要层, 主要由Transformer结构和FeedForward结构组成
输出层
BERT模型的主要结构, 是由主要层堆叠而成, 例如在bert-base
中就包含12层主要层. Bert类模型的主要层大同小异, 主要由Transformer layer, feed forward layer, layerNormalization等结构组成.
下面分析的是标准的Bert模型中, 每层的结构.
输入层
标准的Bert模型输入层由两部分组成:
token input: 文本序列对应的token ids
segment input: 每个token对应的segment ids
token ids
首先是token ids. Tokenizer原始文本得到token list, 每个token对应唯一的id, 最终得到token id list. 这个list的长度就是输入到模型中的长度.
标准Bert使用的tokenizer, 使用BPE(Byte-Pair Encoding)的编码方法, 将字符串文本分割为一个个的token. BPE是WordPiece的一种常见的方案. 简单来说是将一个单词(特指英文单词)继续划分, 将单词拆分到Byte层面, 也就是单个字符/字母(char)的层面, 然后对常见的byte组合, 得到byte-pair, 以此作为token的粒度.
例如loved
, loving
, loves
三个单词, 如果以词为单位, 那么这三个单词的初始化是完全正交的, 同样的句子将对应位置的单词换成这三个单词, 理解的差异是很大的, 三者只能通过共现关系, 后续训练获得相关性. 但其实我们知道这三个单词是有着共同的意思的, 如果拆分成lov
, ed
, ing
, es
这种形式的token, 三个不同的句子将会共用lov
部分, 直接就得到了语义的共通点. 且ed
, ing
, es
也会出现在其他动词形态中, 不同动词也共享着过去时
, 进行时
, 第三人称现在时
的语法.
另外还有着其他的好处:
同一语系的不同语言往往单词有着共同的词根, 代表着近似甚至相同的意思. 这对多语言任务提供了天然便利
可以起到减少词表大小的作用
然而对于中文, 最小的粒度字已经无法再拆分(拆分成部首甚至笔画的意义不大), 因此BPE也只是对英文作用. Bert的标准tokenizer对中文语句的处理, 基本上是按字进行tokenizer. 而且中文的字表是有限的, 词表却是可以无穷扩大的, 这点正好跟英文相反, 因此使用字的粒度作为token, 是非常合适的.
segment id
在Bert的训练过程中, 使用两个句子, 因此在输入中需要标注每个token所属的句子. 我们将每个句子称为segment, segment id list的长度与上面token id list的长度是相等的, 每个位置是一一对应的.
使用0表示第一个句子, 1表示第二个句子, 依次类推. 一般的任务中最多也就会使用两个句子, 0和1已经够用了.
需要注意的是使用两个句子时, 句子分界处的细节. Bert在将一个句子tokenize时, 会在句子的开始和结束分别补充[CLS]
和[SEP]
两个特殊的token, 代表开始和结束. 但[CLS]
作为特殊token表示整体的开始, 只在第一个位置出现, 因此由两个句子组成的文本序列, tokenize会生成[CLS] s11 s12 ... [SEP] s21 s22 ... [SEP]
的形式.
Embedding层
Embedding层的作用, 就是将输入层的各种id输入, 通过各自的Embedding矩阵, 得到各自向量表达, 混合后输入到后续层中.
标准的Bert模型, embedding由token embedding, position embedding以及segment embedding三部分组成. 其中的token embedding和segment embedding会将上面的输入转换为相同长度的向量. position embedding会将的绝对位置转换为向量.
具体方法为给输入的token按0, 1, ...
的顺序赋给每个token一个绝对位置的id, 然后查表将id转为向量.
然后对于每个的token, 将三种embedding结果相加, 就得到了这个token的混合表示.
需要注意以下几点.
position
位置在Transformer这种结构是必不可少的成分, 否则以Transformer的特性, 将两个token对调, 得到的结果会完全相同.
标准的Bert使用绝对位置, 但在其他的一些Bert类模型中(如T5, Nezha等), 会使用相对位置代替绝对位置. 得到相对位置的方法每种模型不同.
但如果使用相对位置, 就不在是得到id, 然后查表, 通过embedding矩阵转换为向量这种方法了. 而是得到一个的矩阵(是token的数量), 直接作用在attention矩阵中(attention矩阵的大小也是). 可以参考T5模型理解这种操作.
长度限制
模型预训练得到的权重文件中, 包含token embedding, position embedding, segment embedding这三个矩阵的参数值. 因此在使用时, 读取预训练得到的权值作为初始化的值.
但所有开源的Bert预训练权重文件中, 对应的position embedding都只包含长度范围为512的权重, 对于更长的序列, 对应的position id就超出了范围, 因此无法得到对应的位置向量表示.
即使另外初始化超出范围的位置对应的embedding, 也会造成pre-training和fine-tune不一致的问题, 较大程度的影响模型的表现.
因此标准的Bert类模型, 只能处理长度不大于512的序列. 如果要处理更长的序列, 就需要另找办法处理.
主要层
主要层是Bert最重要的部分, 也是优秀表征的来源.
标准Bert模型的主要层, 是按照如下的顺序拼接而成的.
MultiHead Attention
>>> Add
>>> Layer Normalization
>>> Feed Forward
>>> Add
>>> Layer Normalization
其中的Add
指的是将上一层得到结果与进行上一层转换之前的输入相加. 而Feed Forward
层其实就是两个Dense
层叠加, 其中第一个Dense
的放大size, 且激活函数如relu
, 第二个Dense
缩小size, 并且没有激活函数.
输出层
输出层输出的内容是多种多样的, 应对不同的任务需要灵活使用不同的输出.
logit output
最基础的, 就是输出每个位置token的表达向量, 输出一个的矩阵, 其中表示序列长度, 表示表征向量的长度.
注意标准Bert这部分的输出是没有经过softmax
作用的, 因此得到的是logit, 而非probability
.
pooler output
Pooler部分其实指的就是第一个token, [CLS]
对应的向量, 并没有进行如果CNN一般的池化操作.
很多分类任务多使用这个向量构建下游结构. 因此在标准的Bert中, pooler output在输出前, 可以进行一个向量长度不变的Dense, 并作用指定的激活函数, 默认是使用tanh
函数进行激活.
nsp output
Next Sentence Prediction任务需要的输出, 基本只在Bert的预训练中使用. 将两个句子合并在一起输入, 判断两个句子是否有顺序关系. 作为一个简单的分类任务, 组成预训练中loss的一部分.
nsp output其实就是对pooler output(经过激活的)再经过一个Dense
层映射为长度为2的向量, 并经过softmax
函数激活, 因此每个位置表示二分类的一个概率预测结果.
mlm output
Masked Language Model输出. 这部分作为预训练loss的主要成分, 转换稍微复杂些. 预测被mask的token具体是什么, 就需要对应位置的一个概率向量, 长度为字典的大小, 表示每个token的概率.
将logit output首先经过Dense
层映射, 并经过relu
激活, 转换为向量长度不变的新表征. 然后再通过Layer Normalization
正则化输出, 得到一个的矩阵, 其中表示序列长度, 表示表征向量的长度.
将这个矩阵与Embedding层中token embedding
矩阵权值相乘, 得到的矩阵, 其中表示字典大小. 再经过softmax
按相应为维度进行激活, 就得到了每个位置token对应的每个可能token的概率值. 这就是mlm output, 一个大小为的矩阵.
需要注意的是:
这里有着参数的共享. 共享使用了Embedding层中
token embedding
矩阵权值使用
Layer Normalization
的原因是大致将向量归一化, 后面与token embedding中每个向量点乘的结果, 更多的由夹角确定, 排除模长的影响
预训练的权值
需要注意的是, 输出层里的很多输出结果都引入了额外的参数, 如Dense
, Layer Normalization
等, 不同的预训练权值文件中, 有的可能没有包含输出层的这些参数, 因此只能使用随机数初始化这些权值, 无法享受预训练带来的结果. 特别是在预测mask位置token的任务时, 影响尤为显著.
对于中文预训练模型, 哈工大开源的large版本RoBERTa-wwm-ext-large是不包含MLM权重的, 但base版本却包含. 腾讯开源的UER是都包含MLM权重的.
参考资料
最后更新于