BERT 实际上是一个 tranformer encoder,输入一串向量输出相同个数的向量。
以下以句子为例,句子可以认为是一串向量。
pre-train
如何训练 BERT 呢(事实上应该是预训练,pre-train)?一个常用的方法是做填空题。即,随机挖去一些字,让模型学习如何去填空。其中这个 “挖去” 也有好几种方法(如:将挖去的字设成某个 special token,或者随机设)。
在盖住的字对应的输出后面接一个 linear 层,经过 softmax 之后得到了一个 distribution,和标准答案对照,loss 即为 cross entropy,从而将 BERT 和 linear 层进行学习(实际上 linear 层做的为一个分类问题,需要将 bert 输出进行正确分类)。
此外,还可以进行 next-sentence predicition 等。next-sentence prediction 指的是把两个句子连接起来,中间插上间隔符 [SEP],开头插上 [CLS],然后在 [CLS] 对应的 bert 的输出向量再连一个 linear 层,输出 yes/no 表示两个句子是否是前后文。为什么只需要 [CLS] 的输出呢?因为 bert 实质上是 transformer 的 encoder,而 encoder 包含很多层的 self-attention,而注意力机制就考虑了整个序列的信息了。
在实作中发现 next-sentence prediction 的效果并不好,可能的原因是考虑的信息太少。
通过以上两种方法,我们就训练出来了 bert。这个过程就叫做 self-supervised learning。个人理解:通过 pre-train 让 bert 来“理解”语言,从而能完成对应的下游任务。
在 bert 通过微调之后可以对下游任务进行处理(如作业中的 question-answering)其中下游任务的训练是需要一些标注的数据的
bert 的下游任务
- 情感分析(sentiment analysis)
和上面提到的类似,[CLS] 对应的输出连上一个 linear 层,linear 层和 bert 作为整个模型进行训练,通过有标注的数据训练,进行 gradient descent。其中 linear 层的初始参数是随机的,而 bert 的参数是预训练的。 - 词性标注(POS tagging)
- 自然语言推断(natural language inference)
- 问题回答(extraction-based question answering)
这是 HW7 的内容,简单写写。
给你一个问题,答案是文档中的原文。如何训练?注意到我们实际上只要得出原文的 start_pos(s) 和 end_pos(e) 即可。
一个问题和对应的文档连接起来扔到 bert 里面,训练两个向量S、E(初始随机),大小和 bert 的输出向量大小相同,分别和 document 对应的输出向量做点乘,再 softmax 得到分布,和训练资料中的答案的 one-hot vector 做 cross entropy 训练 S+E+bert(实际上相当于做了 2 个分类)
还有一点是输入的 document 是要截取的(如可取长度=512),否则长度过长的话,self-attention 的效率很低。