10.9 BERT问题选择模型#

经过10.8节内容介绍之后,我们对于如何在下游任务中使用BERT预训练模型已经有了一定的认识。在本节内容中我们将会介绍如何利用BERT模型来完成推理问答选择任务,同时给模型输入一个问题和若干选项的答案,最后需要模型从给定的选项中选择一个最符合问题逻辑的答案。

通常来说,在NLP领域的大多数场景中模型最后本质上完成的都是一个分类任务。例如文本蕴含任务本质就是将两个序列拼接 在一起,然后预测其所属的类别;基于神经网络的序列生成模型(翻译、文本 生成等)本质就是预测词表中下一个最有可能出现的词,此时的分类类别就是词表的大小。因此,从本质上来看本节内容将要介绍的问答选择任务以及在后面将要介绍的问题回答任务其实都是一个分类任务,而关键的地方就在于如何构建模型的输入和输出。

10.9.1 任务构造原理#

正如上面所说,对于问答选择这个任务场景来说其本质上依旧可以归结为分类任务,只是关键在于如何构建这一任务以及整个数据集。对于问答选择这 个场景来说,其整体原理如图10-30所示。

图 10-30 问题选择任务构造原理图

如图10-30所示是一个基于BERT预训练模型的4选1问答选择模型的原理图。从图中可以看出原始数据的形式是1个问题和4个选项,模型需要做的是从4个选项中给出一个最合理的答案,于是本质上也就变成了一个4分类任务。同时,构建模型输入的方式就是将原始问题和每一个答案拼接起来构成一个序列并且中间用[SEP]符号隔开;然后再分别输入到BERT模型中进行特征提取得到4个特征向量,此时输出形状为[4,hidden_size];最后再经过一个分类层进行分类处理得到预测选项。通常情况下这里的4个特征都是直接取每个序列经BERT编码后的[CLS]向量。

10.9.2 数据预处理#

根据上面的内容可知,对于问答任务来说其接受的输入也分为两个部分:一是由问题和每个选项这两个句子所组成的索引序列,并且需要在两个句子的开始位置加上一个[CLS]符号,以及两个句子之间和结尾分别加上一个[SEP]符号;二是句子编码部分的输入用于确定两个句子的所属部分。最后将两者均作为模型的输入即可。以下完整示例代码可参见Code/Chapter10/C04_BERT文件。

同时,这里需要注意的是虽然对于BERT模型来说“问题 + 1个选项”构成的序列就是一个样本,但是我们在构造数据集的时候还是需要将“问题 + 4个选项”看成一个整体,然后在输入模型之前再变形为对应的形状。

1. 语料介绍

在这里我们使用到的是生成对抗场景数据集(The Situations With Adversarial Generations, SWAG)[1] [2],即给定一个情景(一个问题或一句描述),任务是模型从给定的4个选项中预测最有可能的一个。

如下所示便是部分原始示例数据:

1 ,video-id,fold-ind,startphrase,sent1,sent2,gold-source, ending0,ending1, ending2,ending3,label
2 0,anetv_NttjvRpSdsI,19391,The people are in robes. They,The people are in robes.,They,gold,are wearing colorful costumes.,are doing karate moves on the floor.,shake hands on their hips.,do a flip to the bag.,0
3 1,lsmdc3057_ROBIN_HOOD-27684,16344,She smirks at someone and rides off. He,She smirks at someone and rides off.,He,gold,smiles and falls heavily.,wears a bashful smile.,kneels down behind her.,gives him a playful glance.,1

在上述示例中一共有12个字段(第1行)包含两个样本(第2~3行),这里需要用到的是sent1, ending0, ending1, ending2, ending3和label这6个字段。例如对于第1个样本来说,其形式如下:

1 The people are in robes. They
2   A) wearing colorful costumes. # 正确选项
3   B) are doing karate moves on the floor.
4   C) shake hands on their hips.
5   D) do a flip to the bag.

同时,由于该数据集已经做了训练集、验证集和测试集的划分,所以后续也就不需要我们手动划分。

2. 数据集预览

在正式介绍如何构建数据集之前我们先通过一张图来了解整个大致的构建流程。假如我们现在有两个样本构成了一个小批量,那么其整个数据的处理流程将如图10-31所示。

图 10-31 问题选择任务数据集构建流程图

如图10-31所示,首先对于原始数据的每个样本,即1个问题和4个选项,需要将问题同每个选项拼接在一起构造成为4个序列并添加上对应的分类符[CLS] 和分隔符[SEP],即图中的第①步重构样本。接着将第①步构造得到的序列转换得到索引并进行填充处理,此时便得到了一个形状为[batch_size, num_choice, seq_len]的3维矩阵,即图10-31中第②步处理完成后的结果,形状为[2,4,19]。同时,在第②步中还要根据每个序列构造得到相应的掩码向量和句子编码输入(图中未画出),并且两者的形状也是[batch_size, num_choice, seq_len]

进一步,将第②步处理后的结果变形成[batch_size * num_choice, seq_len]的2维 形式,因为BERT模型接收的输入形式便是一个二维矩阵。在经过BERT模型特征提取后将会得到一个形状为[batch_size * num_choice, hidden_size]的二维矩阵,最后再乘上一个形状为[hidden_size,1]的矩阵并变形成[batch_size, num_choice]即可完成整个分类任务。

3. 重构样本

对于数据预处理部分我们可以继承上一节文本分类中的LoadSingleSentenceClassificationDataset类,然后再稍微修改其中的部分方法即可。同时,由于在上一节内容中已经就词表构建等内容做了详细的介绍所以后续将不再赘述。如图10-31所示,需要对原始样本进

52