传统的预训练方法存在一些问题,如单向语言模型的局限性和无法处理双向上下文的限制。为了解决这些问题,一种新的预训练方法随即被提出,即BERT(Bidirectional Encoder Representations from Transformers)。通过在大规模无标签数据上进行预训练,BERT可以学习到丰富的语言表示,从而在各种下游任务上取得优秀的性能。
BERT与之前的语言表示模型不同,BERT的设计目标是通过在所有层中联合考虑左右上下文,从无标签文本中预训练深度双向表示。因此,预训练的BERT模型只需添加一个额外的输出层,就可以用于各种任务,如问答和语言推理,而无需进行大量的任务特定架构修改。BERT在概念上简单而实证强大,它在包括自然语言处理任务在内的十一个任务上取得了新的最先进结果。
一.输入形式
为了使得BERT模型适应下游的任务(比如说分类任务,以及句子关系QA的任务),输入将被改造成[CLS]+句子A(+[SEP]+句子B+[SEP]) 其中
1.[CLS]: 代表的是分类任务的特殊token,它的输出就是模型的pooler output。
2.[SEP]:分隔符。
3.句子A以及句子B是模型的输入文本,其中句子B可以为空,则输入变为[CLS]+句子A。
在BERT中,输入的向量是由三种不同的embedding求和而成,在以下所举的例子中,每个单词都表示为一个768维的向量。具体形式如下图:
分别是Token嵌入层,Segment嵌入层和Position嵌入层,以下是对其介绍:
-
token嵌入层的作用是将单词转换为固定维的向量表示形式。在将输入文本传递到token嵌入层之前,首先对其进行token化。tokens化是使用一种叫做WordPiecetoken化的方法来完成的。这是一种数据驱动的token化方法,旨在实现词汇量和非词汇量之间的平衡。token嵌入层将每个wordpiece token转换为指定的高维向量表示形式。
-
Segment嵌入层的作用是标记相同句子的每个词以区分不同的句子,假设我们的输入文本对是("I like cats", "I like dogs"),则Segment的标记过程如下图:
- Position嵌入层的作用为允许BERT理解给定的输入文本。例如语句"I think, therefore I am",第一个I和第二个I不应该用同一向量表示。假设BERT被设计用来处理长度为512的输入序列。作者通过让BERT学习每个位置的向量表示来包含输入序列的顺序特征。这意味着Position嵌入层是一个大小为(512,768)的查找表,其中第一行是第一个位置上的任意单词的向量表示,第二行是第二个位置上的任意单词的向量表示,等等。因此,如果我们输入"Hello world"和"Hi there","Hello"和"Hi"将具有相同的Position嵌入,因为它们是输入序列中的第一个单词。同样,"world"和"there"的Position嵌入是相同的。
故综上可得出长度为n的token化输入序列将有三种不同的表示,即:
1.token嵌入,形状(1,n, 768),这只是词的向量表示
2.Segment嵌入,形状(1,n, 768),这是向量表示,以帮助BERT区分成对的输入序列。
3.Position嵌入,形状(1,n, 768),让BERT知道其输入具有时间属性。
对这些表示进行元素求和,生成一个形状为(1,n, 768)的单一表示。这是传递给BERT的编码器层的输入表示。