BERT泛读系列(二)—— BERT论文笔记
一、写在前面的话
BERT模型其实一直想写笔记,但一直没写,主要原因就是在研究完Transformer之后,BERT几乎一读就懂,没有在额外加入太多的东西,但另一方法,BERT在实践上可以说是结合很多深度学习领域有效的方法的一个大礼包,仔细研究BERT模型可以发现很多目前最前沿有效的方法。故这次蹭着论文学习小组需要写笔记,记录了一下自己关于BERT的理解,后续会在这个的基础上加入代码分解。
二、BERT的整体结构
BERT 的模型结构是一个多层双向Transformer 编码器,整体的模型结构其实就是Transformer,但BERT的创新点在于:
- 引入了掩码使得Transformer编码器能够使用双向信息
- 加入两个预训练任务,实现NLP领域的迁移学习
三、输入表示
BERT在预训练阶段输入基本和Transformer结构是相同的,主要的区别是加入了CLS和SEP两个特殊字符,每个序列的第一个标记始终是特殊分类嵌入CLS,该特殊标记对应的最终隐藏状态(即Transformer 的输出)被用作分类任务中该序列的总表示。对于非分类任务,这个最终隐藏状态将被忽略,SEP则是用来区别被打包到一起的句子对输入。
1. WordPiece
BERT在处理输入时,会采用WordPiece方法对输入进行分割。WordPiece字面理解是把word拆成piece一片一片,其主要使用双字节编码(BPE,Byte-Pair Encoding)的方式来实现的。BPE的过程可以理解为把一个单词再拆分,使得我们的此表会变得精简,并且寓意更加清晰。比如"loved","loving","loves"这三个单词。其实本身的语义都是“爱”的意思,但是如果我们以单词为单位,那它们就算不一样的词,在英语中不同后缀的词非常的多,就会使得词表变的很大,训练速度变慢,训练的效果也不是太好。BPE算法通过训练,能够把上面的3个单词拆分成"lov","ed","ing","es"几部分,这样可以把词的本身的意思和时态分开,有效的减少了词表的数量。
2. Segment Embeddings
为了对被打包在一起输入的句子对,除了使用上面的SEP标示之外,BERT会给第一个句子的每个标记添加一个可训练的句子 A嵌入,给第二个句子的每个标记添加一个可训练的句子 B 嵌入,例如A嵌入都是0,B嵌入都是1。
3. Position Embeddings
位置嵌入其实就是对输入的每个位置训练一个向量,在原论文中使用如下公式得到位置嵌入:
但现在的BERT代码中似乎换成和随机生成词向量一样,通过训练得到位置嵌入,这也是一般获得位置嵌入的方法。
四、Transformer编码器
基本上就是从原论文照搬结构,参考之前的笔记:《Attention is All You Need》论文笔记
五、预训练任务
1. 遮蔽语言模型
BERT为了训练拥有双向句子信息的模型采用了一种随机遮蔽一定比例的输入标记,然后预测那些被遮蔽的标记的预训练任务。BERT在每个序列中随机遮蔽 15% 的标记,然后通过最后使用softmax去预测被遮蔽的字,但直接使用这样的预训练任务会有两个问题:
- 预训练和微调之间造成了不匹配,因为 [MASK] 标记在微调期间从未出现过
- 使用 Transformer 的每批次数据中只有 15% 的标记被预测,这意味着模型可能需要更多的预训练步骤来收敛
为了解决问题一(问题二还有待优化),BERT采用了以下的操作:
- 80% 的情况下:用 [MASK] 替换被选择的单词,例如,my dog is hairy → my dog is [MASK]
- 10% 的情况下:用一个随机单词替换被选择的单词,例如,my dog is hairy → my dog is apple
- 10% 的情况下:保持被选择的单词不变,例如,my dog is hairy → my dog is hairy
2. 句子预测
BERT为了训练一个理解句子关系的模型,预训练了一个下一句预测的二元分类任务:例如对每一个输入的句子对(句子A和句子B),50% 的情况下 B 是真的在 A 后面的下一个句子,50% 的情况下是来自语料库的随机句子。
六、微调
可以看到,BERT的微调非常简单,通过对最后一层的简单改造即可迁移到自己的NLP任务中。