## 70 BERT微调

### 目录

* [1.intro](#1intro)
* [2.具体应用](#2具体应用)
  + [2.1句子分类](#21句子分类)
  + [2.2命名实体识别](#22命名实体识别)
  + [2.3问题回答](#23问题回答)
* [3.总结](#3总结)
* [4.QA](#4qa)



### 1.intro

与图片分类不同，BERT预训练时使用的两个任务没有什么实际应用场景，所以使用BERT时多需要进行微调。

BERT对每一个token都返回一个特定长度的特征向量（课堂演示为128，bert-base是768，bert-large是1024），这些特征向量抽取了上下文信息。不同的任务使用不同的特征。

### 2.具体应用

#### 2.1句子分类

将句首的\<CLS\>token对应的向量输入到全连接层分类。对于一对句子也是同理，句子中间用\<SEP\>分开但仍只用第一个\<CLS\>对应的向量。

关于为什么要使用\<CLS\>是因为预训练中判断句子是否连续任务中使用的是\<CLS\>，因此模型会“知道”\<CLS\>是句子级别分类用的向量，表示的信息应与句子整体有关。当然我们也可以不使用\<CLS\>选定自己想要的token，之后在微调中更新bert的权重即可。

#### 2.2命名实体识别

命名实体识别即识别一个词元是不是命名实体，例如人名、机构、位置。其方法是将每一个非特殊词元的向量放进全连接层分类（二分类多分类均可）。

#### 2.3问题回答

给定一个问题和描述文字，找出一个判断作为回答，微调方法为对片段中的每个词元预测它是不是回答的开头或结束。

总体而言，无论是句子级别还是词级别的分类任务，都只需要在bert的基础上加全连接层，bert中的权重是可以直接从预训练模型得到的，真正需要自己从头训练的只有全连接层的权重。

### 3.总结

- 即使下游任务各有不同，使用BERT微调时均只需要增加输出层
- 但根据任务的不同，输入的表示，和使用的BERT特征也会不一样

在BERT的基础上微调使得多数任务都变的简单许多且效果相比从零开始训练要好很多，至此自然语言处理也向计算机视觉一样转向微调路线。

### 4.QA

Q1: BERT微调的时候固定预训练模型的参数吗？

> 一般不固定，所有权重都进行训练。也可以固定住底部一些层来加速训练，但通常来说不固定效果更好。可以自行尝试固定哪几层在训练速度更快的前提下效果更好

Q2: 为什么没讲YOLO？

> YOLO的较新版本已经跟之前版本很不一样了，且里面的技术细节很杂多。纯Python实现的yolo效果不见得比其他算法好，之所以表现出众是因为加入了大量的技术细节。只给大家实现一个本身大家可能不会太感兴趣。

Q3: BERT在实际应用中怎样部署？用C++写代码吗？

> 一般不需要用C++，可以将模型编译到C++（框架通常有支持）。但搬到C++也不能解决速度问题，BERT本身比resnet之类慢很多。

Q4: 如果设备性能不高是不是不建议用BERT？

> 可以用简化版本的BERT，如蒸馏版的BERT大约只有原模型十分之一大小。