引言
- 本文主要作为个人学习 Bert 原理理论的总结,其核心点从 attention机制以及 transformer 已经聊过,内容仅供参考
- 除了 attention 和 transformer 之外,Bert 作为一个集大成者还包含了 elmo 和 gpt 的一些思想,这两个模型原理会在后面学习中记录。
Bert:Bidirectional Encoder Representation from Transformers
- 两个预训练任务
- 第一个任务是采用 MaskLM (一种训练方法)的方式来训练语言模型,通俗地说就是"完形填空",只是不同的是这个"空"是随机的且要用[MASK]替代""空,任务目标就是让模型去学习这些空该填的词。
- 第二个任务就是一个句子级别的连续性预测任务,即“段落排序”,只是这里更为简单只是预测输入的两句话是否是连续的,任务目标就是为了让模型更好的学到文本内容之间的上下文关系。
- 两个任务做到的优势
- 相较于原来的 RNN、LSTM ,第一可以做到并发执行,第二可以同时提取词在句子中的关系特征,第三是能在多个不同层次提取关系特征,进而更全面反映句子语义。
- 相较于 word2vec,其又能根据句子上下文获取词义,从而避免歧义出现
- 当然,对应缺点就是模型太大,参数太多,数据量太小去微调容易过拟合。
- 两个任务来源的思想
- 其一表示Bert 只使用了 tranformer的 Encode 侧,并未使用 Decode 侧,因为Decoder获取不到要预测的信息(transformer有介绍 decode 侧的输入需要有预测的正确信息,除此之外,encoder 接到的 input 内容也和 transform 是不一致的)。
- 其二是双向的,ELMO和GPT都是单向的(ELMO可以说是双向的,但其实是两个方向相反的单向语言模型的拼接),而结合上下文信息对自然语言处理是非常重要的。Bidirectional也是Bert的主要创新点。
BERT 模型配置
- 假设:1 编码器层数记为L;2 注意力头数记为A; 3 隐藏单元数记为H
- BERT-base/BERT-large包含12/24个(Encode)编码器层。所有的编码器使用12/16个注意头。编码器中的全连接网络包含768/1024个隐藏单元。因此,从该模型中得到的向量大小也就是768/1024维;
- 当然除了标准配置外,也有更小级别的配置:
BERT的输入
- 输入分为三个部分:
- 标记嵌入(Token embedding)
- 片段嵌入(Segment embedding)
- 位置嵌入(Position embedding)
- 标记嵌入:此处是bert 不同于 transform 输入的一个地方,标记就是[CLS],[SEP]
CLS]标记只加在第一个句子前面,而[SEP]标记加到每个句子末尾[CLS]标记用于分类任务,而[SEP]标记用于表示每个句子的结尾- 比如下面两句话如何一起读入呢?(bert 读入句子后使用WordPiece分词器分词,这个分词器可以参考文章 1)
Sentence A: Paris is a beautiful city.
Sentence B: I love Paris.
-- 如下所示
tokens = [ [CLS], Paris, is, a, beautiful, city, [SEP], I, love, Paris, [SEP]]
- 片段嵌入:为了进行区分输入的两句话(上面只是标记了但是未区分是不是两句话)
- 如果只有一句话,那就会分到一个嵌入层里
- 如果只有一句话,那就会分到一个嵌入层里
- 位置嵌入:不同于 transform 的固定位置 cos,sin 函数编码,bert 的位置编码是随机生成且可训练的,维度为
[seq_length, width],其中seq_length代表序列长度,width代表每一个token对应的向量长度。(个人理解就是有初始值,然后随着训练过程的反向传播来调整参数进行学习,这样不仅可以标记位置还可以学习到这个位置有什么用,待续...)
Masked LM
- 在Masked LM之前首先介绍下语言建模的两种方式:
- 自回归语言建模:通俗讲就是一句话,随机把一个词作为待预测的目标,你可以从左往右也可以从右往左的读取然后预测,但是只能单向
- 自编码语言建模:同时从两个方向读入信息(右-->左,左-->右)
- 屏蔽语言建模就属于自编码语言建模,在一个屏蔽语言建模任务中,对于给定的输入序列,我们随机屏蔽15%的单词,然后训练模型去预测这些屏蔽的单词,如下
- tokens = [ [CLS], Paris, is, a beautiful, [MASK], [SEP], I, love, Paris, [SEP] ]
- 此处有个问题就是,预训练使用了 mask,但是等到进行微调的时候输入是没有 mask 的,这样会导致 BERT 的预训练方式与微调方式不匹配,怎么办呢?为了解决这个问题使用了 80-10-10%规则
- 为了预测屏蔽的标记,我们将BERT返回的屏蔽的单词表示R[MASK]喂给一个带有softmax激活函数的前馈神经网络。然后该网络输出词表中每个单词属于该屏蔽的单词的概率
下一句预测 next sentence prediction,NSP
-
NSP是二分类任务,在此任务中,我们输入两个句子两个BERT,然后BERT需要判断第二个句子是否为第一个句子的下一句,如果是下一句就标记为:isNEXT,不是就是 notNEXT,那么如何获取这样的训练集呢?
假设我们有一些文档。对于isNext类别,我们从某篇文档中抽取任意相连的句子,然后将它们标记为isNext;对于notNext类别,我们从一篇文档中取一个句子,然后另一个句子随机的从所有文档中取,标记为notNext。同时我们需要保证数据集中50%的句子对属于isNext,剩下50%的句子对属于notNext。
-
类比如预测 R_MASK,当将input进行编码后输入模型,为了进行分类,我们简单地将
[CLS]标记的嵌入表示喂给一个带有softmax函数的全连接网络,该网络会返回我们输入的句子对属于isNext和notNext的概率: -
BERT使用的激活函数叫作GELU(Gaussian Error Linear Unit)
BERT的其他方面(参考文章 2):
- 比如与word2vec,ELMO,transform,gpt 等模型在各自不同纬度的对比优缺点、自身的局限性,后面学习了这些模型后再单独记录!(待办)
- 针对句子语义相似度/多标签分类/机器翻译/文本生成的任务,利用 BERT 结构怎么做 fine-tuning?对应的公式是什么样的(理解还太浅,弄懂后再补充)
- 比如为啥要 mask?embedding 向量怎么来的?对于空格丢失的数据是否有效?与 CBOW 的异同等等问题都出自参考文章 2,后续会逐步理解。
参考资料:
- 参考 1:【理论篇】是时候彻底弄懂BERT模型了(收藏)-CSDN博客
- 还详细介绍了一些子词Tokenization算法,此处不多赘述
- 子词
Tokenization算法是自然语言处理中用于将文本分割为较小单元(tokens)的一种方法(比如上文中的 WordPiece)
- 参考 2:BERT模型的详细介绍-CSDN博客
- 思维比较发散,但是含金量确实是很高的,只是目前理解较浅不能完全看懂以及提出想法和转化成自己的语言表达
- 参考 3:一文读懂BERT(原理篇)_这是由于bert的 自我注意力机制的二次计算复杂度-CSDN博客
- 主要看了关于 NLP 的一些模型发展史,因为包含内容过多本文未借鉴太多内容,但是感觉总结的比较全面,用于个人以后学习的一个方向指导
- 参考 4:BERT原理和结构详解_bert结构-CSDN博客
- 主要看了其推导数据纬度变化,为下篇代码篇重点参考理解