1. 了解BERT模型
BERT(Bidirectional Encoder Representations from Transformers)模型是一个双向、基于上下文的嵌入模型。相比传统的word2vec,BERT模型的优势是双向和上下文相关,原因在于BERT模型使用了多头注意力的Transformer编码器结构。通过多头注意力,句子中的单词可以注意到整个句子前后的上下文,而传统word2vec则不能,例如:
- 句子A:He got bit by Python(他被蟒蛇咬了)
- 句子B:Python is my favorite programming language(Python是我最喜欢的编程语言)
传统的word2vec在两个句子中Python的嵌入是相同的,而通过BERT编码后两句句子中Python的嵌入是不同的,会根据上下文发生改变。
2. BERT的配置
几个常用配置,L是编码器层数;A是注意力头数,通常一头默认是64维;H是前馈网络隐藏层维度:
- BERT-large:L=24,A=16,H=1024
- BERT-base:L=12,A=12,H=768
- BERT-medium:L=8,A=8,H=512
- BERT-small:L=4,A=8,H=512
- BERT-mini:L=4,A=4,H=256
- BERT-tiny:L=2,A=2,H=128
通常参数越多,效果越好。
3. BERT模型预训练
BERT模型在一个巨大的语料库上针对两种特定的任务进行预训练。这两种任务是:
- 掩码语言模型构建(masked language model(MLM))
- 下句预测(next sentence prediction(NSP))
3.1 输入数据
- 标记嵌入层
- 分段嵌入层
- 位置嵌入层
例
- 句子A:Paris is a beautiful city(巴黎是一个美丽的城市)
- 句子B:I love Paris(我爱巴黎)
3.1.1 标记嵌入层
步骤:
- 分词:[Paris, is, a, beautiful, city, I, love, Paris]
- 起始添加[CLS]标记,用于MLM任务:[[CLS], Paris, is, a, beautiful, city, I, love, Paris]
- 每个句子末尾添加[SEP]标记:[[CLS], Paris, is, a, beautiful, city, [SEP], I, love, Paris, [SEP]]
- 将标记转化id,然后通过嵌入层转化为嵌入
3.1.2 分段嵌入层
注意:[CLS]被分在第一个句子中。
[[CLS], Paris, is, a, beautiful, city, [SEP], I, love, Paris, [SEP]]
[ 0, 0, 0, 0, 0, 0, 0,1, 1, 1, 1]
将以上id转化为分段嵌入
3.1.3 位置嵌入层
[[CLS], Paris, is, a, beautiful, city, [SEP], I, love, Paris, [SEP]]
[ 0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10]
将以上id转化为位置嵌入
3.2 预训练策略
- 语言模型构建
- 掩码语言模型构建
- 下句预测
- 预训练过程
3.2.1 语言模型构建
- 自动回归式语言模型:从左向右或从右向左读取所有单词,然后预测下一个单词。即使是ELMo模型,本质上还是单向的语言模型
- 自动编码式语言模型:能够从两个方向同时阅读句子,预测空白处单词。例如BERT
3.2.2 掩码语言模型构建
例:
Paris is a beautiful _city. I love Paris(city是要预测单词)
步骤:
- 分词:[Paris, is, a, beautiful, city, I, love, Paris]
- 添加[CLS],[SEP]标识:[[CLS], Paris, is, a, beautiful, city, [SEP], I, love, Paris, [SEP]]
- 使用[MASK]标记替换city,然后用80-10-10规则再处理
3.1 80%概率保持使用[MASK]标记替换city:[[CLS], Paris, is, a, beautiful, [MASK], [SEP], I, love, Paris, [SEP]]
3.2 10%概率使用一个随机词替换city:[[CLS], Paris, is, a, beautiful, love, [SEP], I, love, Paris, [SEP]]
3.2 10%概率不再使用[MASK]标记替换city:[[CLS], Paris, is, a, beautiful, city, [SEP], I, love, Paris, [SEP]] - 把句子输入到BERT编码,使用city位置的嵌入预测是city的概率
80-10-10规则的目的是:减小预训练和微调任务之间的差距,因为下游的微调任务中是没有[MASK]标记的。
全词掩码
BERT使用的是WordPiece的分词方式,当标记产生下列句子时:
- [[CLS], let, us, start, pre, ##train, ##ing, the, model, [SEP]]
其中,##train, ##ing中的##符号表示,train和ing是和前面一个单词连在一起的,即pre,train,ing都是pretraining的子词。
步骤:
- 选中了let和##train进行掩盖:[[CLS], [MASK], us, start, pre, [MASK], ##ing, the, model, [SEP]]
- 由于##train是子词,所以对整个pretraining单词进行掩盖:[[CLS], [MASK], us, start, [MASK], [MASK], [MASK], the, model, [SEP]]
- 掩盖超过了15%,忽略对let的掩盖:[[CLS], let, us, start, [MASK], [MASK], [MASK], the, model, [SEP]]
- 把句子输入到BERT编码,预测所有被掩盖的单词
3.2.3 下句预测
例:
- 句子A:She cooked pasta(她做了意大利面)
- 句子B:It was delicious(它很美味)
- 标签:isNext
目标:判断句子B是否是句子A的下句
步骤:
- 分词:[[CLS], She, cooked, pasta, [SEP], It, was, delicious, [SEP]]
- 使用[CLS]的编码后的特征值送入softmax激活的前馈网络层预测isNext和notNext的概率
3.2.4 预训练过程
预料:多伦多图书语料库和维基百科数据集
采样:句子A和句子B长度不超过512,句子B是句子A下一句的概率是50%
例:
- 句子A:We enjoyed the game(我们很享受比赛)
- 句子B:Turn the radio on(打开收音机)
预训练步骤:
- 将句子A和句子B拼接后分词、添加[CLS]和[SEP]标记:[[CLS], We, enjoyed, the, game, [SEP], Turn, the, radio, on, [SEP]]
- 使用80-10-10规则掩盖:[[CLS], We, enjoyed, the, [MASK], [SEP], Turn, the, radio, on, [SEP]]
- 通过BERT编码,使用[MASK]位置的特征预测game的概率,通过[CLS]的特征预测isNext的概率
预训练超参:
- batch size=256
- Adam优化器,lr=1e-4,beta1=0.9,beta2=0.999
- 所有层进行dropout=0.1
- 使用GeLU函数激活
3.3 子词词元化算法
- 传统词汇表
- 字节对编码(BPE)
- 字节级字节对编码(BBPE)
- WordPiece(BERT使用的子词词元化算法)
3.3.1 传统词汇表
例:
vocabulary = {game, the, I, played, walked, enjoy}
当给定句子I enjoyed the game时,由于enjoy的过去时不在词汇表中,会用<UNK>替代,所以传统的词汇表需要足够大,导致内存和性能问题。
3.3.2 字节对编码(BPE)
例:
对于给定数据集,统计每个单词出现次数:(cost, 2)、(best, 2)、(menu, 1)、(men, 1)、(camel, 1),假设构建大小为14的词汇表。
构建步骤:
- 把所有非重复的11个单个字符加入词汇表:{a,b,c,e,l,m,n,o,s,t,u}
- 从当前词汇表中找出出现最频繁的符号对st(cost和best中分别出现2次,共4次)加入词汇表:{a,b,c,e,l,m,n,o,s,t,u,st}
- 重复步骤2直到词汇表大小
3.3.2 字节对编码(BBPE)
例:
- 字符序列:bset,字节级序列:62 65 73 74
- 字符序列:你好,字节级序列:e4 bd a0 e5 a5 bd
构建步骤同BPE,不过不再是单个字符而是单个字节。适用场景:多语言环境,理解多语言共享词。
3.3.3 WordPiece
例:
对于给定数据集,统计每个单词出现次数:(cost, 2)、(best, 2)、(menu, 1)、(men, 1)、(camel, 1),假设构建大小为14的词汇表。
构建步骤:
- 把所有非重复的单个字符加入词汇表:{a,b,c,e,l,m,n,o,s,t,u}
- 在给定的数据集上构建语言模型
- 选择合并具有最大相似度:的符号对
- 重复步骤3直到词汇表大小
参考资料
[1]. BERT基础教程Transformer大模型实战
[2]. 深入理解NLP Subword算法:BPE、WordPiece、ULM:https://zhuanlan.zhihu.com/p/86965595