70 BERT微调【动手学深度学习v2】

BERT 微调
- 对于自然语言处理应用可以设计不同的模型,比如基于循环神经网络、卷积神经网络,注意力和多层感知机,这些模型在有空间或者时间限制的情况下是有帮助的,但是为每个自然语言处理任务都设计一个特定的模型实际上是不可行的
- BERT 预训练模型可以对广泛的自然语言处理任务进行最少的架构更改
- BERT 模型的提出改进了各种语言处理任务的技术水平
- 原始 BERT 模型的两个版本分别带有 1.1 亿和 3.4 亿个参数,因此,当有足够的计算资源时可以考虑为下游自然语言处理应用微调 BERT
- 和图片分类的不同之处在于,图片分类训练好了 ResNet 之后,可以用来做图片分类,也是一个正常的任务;但是 BERT 本身的两个任务是没有意义的,很少会有做完形填空和预测两个句子是否相邻的情况,因此 BERT 主要用于做微调
- 自然语言处理应用可以分为序列级和词元级:序列级包括单文本分类任务和文本对分类(或回归)任务;词元级包括文本标注和回答
- 在微调期间,不同应用之间的 BERT 所需的“最小架构更改”是额外的全连接层
- 在下游应用的监督学习期间,额外的参数是从零开始学习的,而预训练 BERT 模型中的所有参数都是微调的
微调 BERT

1、在训练好 BERT 之后,句子(含分类标识符、句子和分隔符)进入 BERT ,BERT 会对每一个 token 返回一个长为 128 (BERT-Base:768;BERT-Large:1024)的特征向量(因为是 transformer ,所以可以认为这些特征已经包含了整个句子的信息的特征表示)
- BERT 对每一个词元返回抽取了上下文信息的特征向量
2、不同的任务使用不同的特征
例:句子分类
1、如何将文本输入的 BERT 表示转换为输出标签?将 <cls> 对应的向量输入到全连接层分类
2、单句子分类:单文本分类将单个文本序列作为输入,并输出其分类结果
- 特殊分类标记 <cls> 用于序列分类
- 特殊分类标记 <sep> 用于标记单个文本的结束或者分隔成对文本
- 将句子输入到 BERT 模型中,然后只将句子开始的 <cls> 标识符输出对应的特征向量,然后将这个特征向量输入到一个二分类(或者是 n 分类)输出层中做 softmax 进行分类
- 单文本分类应用中,特殊标记 <cls> 的 BERT 表示对整个输入文本序列的信息进行编码,作为单个文本的表示,它将被送入到由全连接(稠密)层组成的小多层感知机中,以输出所有离散标签值的分布

3、句子对分类:以一对文本作为输入但输出连续值
- 对于句子对也是一样的,将句子输入到 BERT 模型中,也是只将句子开始的 <cls> 标识符输出对应的特征向量,然后将这个特征向量输入到一个二分类(或者是 n 分类)输出层中做 softmax 进行分类
- 与单文本分类相比,文本对分类的 BERT 微调在输入表示上有所不同

2、为什么使用句子开始的标识符 <cls> ,而不是用别的东西?
- 在做预训练的时候,判断两个句子是不是相邻的时候使用的是 <cls> 这个标识符,所以也是在告诉 BERT 这个标识符是在做句子级别上分类所使用的向量,所以尽量将它对应输出的特征向量做得便于做分类
- 其实换成其他的也可以,反正最终需要进行微调,在训练的时候会更新 BERT 的权重,所以可以改变 BERT 的权重,使得最终输出的特征向量包含自己所想要的特征
例:命名实体识别
1、识别一个词元是不是命名实体,例如人名、机构、位置
2、BERT 如何表示输入并转换为输出标签?将非特殊词元放进全连接层分类
- 句子输入到 BERT 模型之后,将非特殊词元(丢弃掉 <cls> 、<sep> 等特殊词元,只留下真正的 token)放进全连接层进行分类,对每一个词进行词级别的分类判断(二分类或者是多分类)
- 与单文本分类的相比,唯一的区别在于,在命名实体识别中,输入文本的每个词元的 BERT 表示被送到相同的额外全连接层中,以输出词元的标签

问题回答
1、给定一个问题和它的描述文字,找出一个片段作为回答
- 给定一段话,然后提出一个问题,将描述中对应的词或者是句子截取出来作为回答
- 问答反映阅读理解能力
2、如何实现?BERT 如何表示输入并转换为输出标签?

- 首先将问题和描述性文字做成两句话(如果描述性文字是一段的话也不要紧,可以做成一个很长的序列,这也是为什么 BERT 长度通常可以做到 1024 ,因为它输入的数据可能确实比较长):第一句话是问题,问题不需要进行输出;第二句话是问题的描述文字,可能会比较长
- 分类器的作用:对于问题的描述性文字的每一个词,预测它是答案开始的那个词、结束的那个词还是什么都不是(这是一个三分类的问题),即对片段中的每个词元预测它是不是回答的开头或者结束(开始、结束或者其他)
总结
1、对于问题回答、句子分类或者词分类,虽然想要的东西不太一样,但是对于 BERT 来讲都是做成一个句子对输入到模型中,最后连接一个全连接层进行分类
- 全连接层所要看的 token 对应的特征向量可能不太一样,但是整体来讲,最后 BERT 模型所有的权重都是可以直接使用预训练好的模型
- 只有最后的输出层是真的需要从零开始训练的
2、即使 NLP 的任务各有不同,在使用 BERT 微调的时候都只需要增加输出层就可以了,而不需要在意怎样表示句子信息、段落信息、词信息,这些已经假设 BERT 已经提前做好了,只需要加一个简单的输出层就可以了
3、根据任务的不同,输入的表示和使用的 BERT 特征也会不一样,但是整体来讲,使用了 BERT 之后,使得整个微调相比于之前简单很多,而且 BERT 对于整个任务的提升也是非常显著的(比从零开始训练可能效果会好很多)
4、现在在 NLP 领域基本上也是转向微调的路线
5、对于序列级和词元级自然语言处理应用,BERT 只需要最小的架构改变(额外的全连接层)
6、在下游应用的监督学习期间,额外层的参数是从零开始学习的,而预训练 BERT 模型中的所有参数都是微调的
7、可以针对下游应用对预训练的 BERT 模型进行微调,在微调过程中,BERT 模型成为下游应用模型的一部分,仅与训练前损失相关的参数在微调期间不会更新
Q&A
- 1、请问 bert 微调的时候,是固定预训练模型的参数吗?fine tuning 的时候,预训练的 model 的参数也会调整吗?
- QA P4 - 00:00
- 2、老师,请问为什么我尝试把之前训练的 d2l.train_char6 中的图形化的东西删掉后反而训练不了?
- QA P4 - 00:31
- 3、老师,请问 YOLO 的代码可以也分享到课程当中吗?
- QA P4 - 00:49
- 4、请问老师,bert 在实际应用的时候,一般如何部署呢?用 C++ 写预测代码吗?
- QA P4 - 01:49
- 5、如果设备性能不是很高,是不是不建议使用 bert ?
- QA P4 - 03:26
----end----
其他参考
1、《动手学深度学习》,课程 PPT ,https://courses.d2l.ai/zh-v2/assets/pdfs/part-4_7.pdf
2、《动手学深度学习》,教程,https://zh-v2.d2l.ai/chapter_natural-language-processing-applications/finetuning-bert.html
3、《动手学深度学习》,教程,https://zh-v2.d2l.ai/chapter_natural-language-processing-applications/natural-language-inference-and-dataset.html
4、《动手学深度学习》,教程,https://zh-v2.d2l.ai/chapter_natural-language-processing-applications/natural-language-inference-bert.html