近日,智言科技AI团队刷新CommonsenseQA数据集世界纪录,位列榜单第一。本文介绍来了该团队的解决方案。
CommonsenseQA 任务排名结果:https://www.tau-nlp.org/csqa-leaderboard
长期以来,机器常识或机器对开放世界的理解和推理能力一直被认为是自然语言理解的重要组成部分。而机器推理,其目的是使用已有的知识和推断技术对未见过的输入信息作出判断。常识问答是机器推理上的一个重要的应用方向。
当前对机器而言,如何基于常识和背景知识进行推理以获得答案仍旧是一个巨大的挑战。人们在回答问题时,除了特定的上下文外,还经常利用其丰富的世界知识。最近的研究工作主要集中在回答一些给定相关文件或上下文的问题,并且只需要很少的一般背景。
为了调查具有先验知识的问答,Talmor等提出了CommonsenseQA:常识性问答的一个富有挑战性的新数据集。为了捕捉关联之外的常识,Talmor等从ConceptNet(Speer等人,2017)中提取了多个目标概念,这些目标概念与单个源概念具有相同的语义关系。要求人群工作者提出多项选择题,提及源概念,并在每个目标概念之间进行区分。这鼓励工作人员创建具有复杂语义的问题,这些问题通常需要先验知识。通过此过程,Talmor等创建了12,247个问题,并通过大量可靠的基准模型演示了任务的难度。最佳基准模型是基于BERT-large(Devlin等人,2018),并获得56%的准确度,远低于人类的89%的准确度。
数据与任务
CommonsenseQA是一个新的多项选择题回答数据集,需要不同类型的常识知识才能预测正确的答案。它包含12247个问题,其中一个正确答案和四个干扰因素答案。数据集分为两个主要的训练/验证/测试集。
数据下载地址:
https://s3.amazonaws.com/commensenseqa/train_rand_split.jsonl
https://s3.amazonaws.com/commensenseqa/dev_rand_split.jsonl
https://s3.amazonaws.com/commensenseqa/dev_rand_split.jsonl
训练集:训练数据是以json格式给出。主要字段是标识符(id),答案选项(answerKey),问题或题干(stem),问题选项(choices)
测试集:测试数据也是以json格式给出。主要字段是标识符(id)问题或题干(stem),问题选项(choices)
评价指标:给出题干和多项候选答案,要求预测正确答案的准确率(Accuracy)。
实验方案
1.Baseline
我们选择BERT作为baseline。关于模型输入格式,我们原先采取<cls>Q:question<sep>choice1....<sep>choice5,即问题和对应五个答案拼接的单句模式,实验效果不是很好,后来换用Multiple-Choice的输入格式。例如question_tokens = 'Q: ' + question,choice_tokens = 'A: ' + choice,每个选项是都是问题和答案的拼接形式,具体如下图所示:
图一:基于BERT的Baseline模型
先利用BERT计算问题与五个候选答案的语义关联程度,然后再用softmax层归一化得到各个答案的相应概率。
我们的实验结果如下所示:
图二:BERT实验结果
通过实验结果我们可以看出相对于随机结果20%,BERT无疑效果好很多,但是,相对于人类水平88.9%,差距还是非常大的。BERT通过MLM预训练目标得到上下文相关的双向特征表示,但是,一是同时也引入噪声[MASK],训练过程大量看到[mask]标记,而在微调阶段模型并不会看到[MASK]标记。这就造成了预训练-精调两阶段之间的差异。后面虽然做了改进,但问题依然存在。二是没有考虑预测[MASK]之间的相关性,是对语言模型联合概率的有偏估计。
CommonsenseQA任务的关键是让模型学到更多的先验知识,这样在一些给定相关文件或上下文的问题(只需要很少的背景知识)上,模型获得的先验知识越多,给出正确预测答案的概率越大。
其实,预训练本质上是通过设计好一个网络结构来做语言模型任务,然后把大量甚至是无穷尽的无标注的自然语言文本利用起来,预训练任务把大量语言学知识抽取出来编码到网络结构中,当手头任务带有标注信息的数据有限时,这些先验的语言学特征当然会对手头任务有极大的特征补充作用,因为当数据有限的时候,很多语言学现象是覆盖不到的,泛化能力就弱,集成尽量通用的语言学知识自然会加强模型的泛化能力。[3]
所以,针对CommonsenseQA任务主要有两大改进方向,一是采用更强大,引用更多高质量、大规模数据集训练的预训练模型--xlnet、roberta、albert等。越强大的预训练语言模型其特征抽取能力越强,能更好的引入大量无监督数据中包含的语言学知识,其推理能力也就越强大。二是引入外部知识。针对常识问答在问题中只给定很少的背景知识,而预训练模型本身蕴含的知识不足以让模型“推理”出正确答案,于是,引入跟答案或者问题关联的外部知识就成了关键。
这可以为预训练模型提供很好的特征补充,增强模型的推理能力。
接下来,我们依次介绍xlnet,roberta,albert。
XLNET
XLNet是一种广义自回归语言模型,它很好地结合了自回归语言模型和自编码语言模型的优点,在不引入噪声的同时又能获得上下文相关的双向特征表示。
XLNET相比BERT,它解决了BERT的两个缺点:预测目标独立性假设、预训练阶段和微调阶段不一致。另外,xlnet加大增加了预训练阶段使用的数据规模;Bert使用的预训练数据是BooksCorpus和英文Wiki数据,大小13G。XLNet除了使用这些数据外,另外引入了Giga5,ClueWeb以及Common Crawl数据,并排掉了其中的一些低质量数据,大小分别是16G,19G和78G, 这样加起来一共126G。可以看出,XLNet在预训练阶段极大扩充了数据规模,并对质量进行了筛选过滤。
我们将xlnet应用于CommonsenseQA任务。模型输入格式、架构与BERT一致。
实验结果如下:
图四:XLNET实验结果
XLNet-Large 与 BERT-Large 拥有相同的结构超参数,模型规模相当。实验结果比BERTLarge(0.6225)高出约13个百分点。这说明改进后的xlnet预训练模型能得到更好的上下文相关的双向特征表示,使用更大规模的高质量数据能让模型学到更多的先验知识,因而拥有更强的推理能力。
RoBERTa
RoBERTa 模型是BERT的改进版(A Robustly Optimized BERT,即强力优化的BERT方法)。作者发现BERT训练并不充分,于是在BERT基础上主要做了四点优化:(1)在更多数据上以更大的批次训练模型更长的时间;(2)删除下一句预测目标;(3)使用更长序列训练;(4)使用动态mask。[4] 在GLUE、SQuAD和RACE取得了SOTA的结果。
将RoBERTa应用于CommonsenseQA任务。模型输入格式、架构与前面一致。实验结果如下:
图五:RoBERTa实验结果
RoBERTaLarge的实验结果0.7740比XLNet-Large(0.7494)高出约2.5个百分点。在微调实验中,BERTLarge,RoBERTaLarge, XLNETLarge都采用一样的网格参数:L = 24,H = 1024,A = 16,参数总量大概3.55亿。在训练数据上,Bert使用的预训练数据是BooksCorpus和英文Wiki数据(13G)。XLNet使用 BooksCorpus 和英文Wiki数据(13G)、Giga5(16G)、ClueWeb 2012-B(19G) 、Common Crawl(78G)语料库,一共126G。RoBERTa 采用 160G训练文本,包括BooksCorpus 和英文Wiki数据(13G)、CC-NEWS(76G)、OPENWEBTEXT(38G)、
STORIES(31G)。然后我们对比下三个实验的结果:
图六:BERT、XLNET、RoBERTa实验对比
再对三个预训练模型做个总结。XLNet通过引入permutation language modeling,解决了BERT预训练阶段和微调阶段差异性,消除了BERT的预测目标独立性假设,同时数据规模扩充到了126G。RoBERTa在BERT基础上主要做了四点改进:使用动态mask;移除NSP任务;更大的batch size;更长的输入序列。同时,它使用了更大规模的数据集(160G)。这或许证明不了这三个模型的内部机制谁更为优秀,但至少证明了一点:引入更大规模,更高质量的数据集能更好的提升模型表现。
毕竟,本质上预训练是通过设计好一个网络结构来做语言模型任务,然后把大量甚至是无穷尽的无标注的自然语言文本利用起来,预训练任务把大量语言学知识抽取出来编码到网络结构中。这样,引入的数据集规模越大,质量越高,模型学到的先验的语言学特征越多,集成更多的通用的语言学知识,模型的泛化能力也就越强。[3]
在CommonsenseQA任务上,目前由于并没有引入外部数据,并且需要正确预测只需要很少背景知识的问答,所以预训练模型本身蕴含的知识就成了关键。相比之下,RoBERTa引用了最大规模、更高质量的数据集(160G),故而目前效果最好。
ALBERT
通常而言,在预训练自然语言表征时增加模型大小可以提升模型在下游任务中的性能。但在某些情况下,由于 GPU/TPU 内存限制、训练时间延长以及意外的模型退化等原因,进一步增加模型大小的难度也随之增加。为了解决这些问题,
谷歌提出了ALBERT(A Lite BERT),通过两种参数精简技术来降低内存消耗,提高BERT的训练速度。[5]
ALBERT主要有三点改进:
- Factorized Embedding Parameterization。研究者通过将大的词汇嵌入矩阵分解为两个小的矩阵,从而将隐藏层的大小与词汇嵌入的大小分离开来。这种分隔使得在不显着增加词汇表嵌入参数大小的情况下更容易增加隐藏层的大小。
- Cross-layer Parameter Sharing。研究者共享了所有层的参数,这一技术可以避免参数量随着网络深度的增加而增加。
- 为了进一步提升 ALBERT 的性能,研究者还引入了一个自监督损失函数,用于句子级别的预测(SOP)。SOP 主要聚焦于句间连贯,用于解决原版 BERT 中下一句预测(NSP)损失低效的问题。
我们将ALBERT应用于CommonsenseQA任务。还是以前的输入格式和模型架构。
1.拼接ALBERT最后四层输出
BERT的不同层编码非常不同的信息,因此适当的池化策略将根据应用的不同而改变,因为不同的层池化编码不同的信息。BERT的作者通过将不同的向量组合作为输入特征输入到一个用于命名实体识别任务的BiLSTM中,并观察得到的相应的F1分数。如下所示:
可以看出,最好的效果是拼接最后四层的隐藏层向量。
ALBERT默认输出最后一层隐状态的序列中的CLS (classification token)向量,然后再经过一个线性变换和Tanh激活函数,最后再输出。经过我们实验,取最后四层拼接的方式,模型收敛更快,更稳定,效果最好。
- 引入wiki数据
前文我们提到,常识问答旨在回答需要背景知识的问题,而背景知识并未在问题中明确表达。关键是让模型学到更多的先验知识。所以针对CommonsenseQA任务主要有两大改进方向,一是采用更强大,引用更多高质量、大规模数据集训练的预训练模型--xlnet、roberta、albert等。越强大的预训练语言模型其特征抽取能力越强,能更好的引入大量无监督数据中包含的语言学知识,其推理能力也就越强大。二是从结构化或非结构化知识库引入外部知识。
第一个方向我们已经做过实验。接下来探索第二个方向:引入外部知识。我们从排行榜注意到比较有用的是结构化知识库(ConceptNet)和Wikipedia纯文本数据。考虑到Talmor等制作数据集时用到的就是结构化知识库(ConceptNet),
并且规定使用ConceptNet的暂时不列入正式排行榜。所以,我们放弃了使用ConceptNet,只使用了Wikipedia纯文本数据进行实验。
使用的 Wikipedia 版本信息:enwiki-20190101
下载地址为:https://dumps.wikimedia.org/enwiki/latest/
下载后的文件有70.5G,然后使用ElementTree解析xml文件,清洗整理为131M的句子,对于每个训练样例,我们以"<s> Q:question </s> choice </s>"拼接问题和选项作为检索查询,使用bm25算法对检索查询和所有句子之间进行排序,
召回前10个句子返回,每个句子的形式是 "word: definition"。
模型输入:我们之前的输入格式是
question_tokens = 'Q: ' + question
,choice_tokens = 'A: ' + choice
引入Wikipedia后的输入格式:
question_tokens = 'Q: ' + question
,
choice_tokens = 'A: '+ choice + Cancat 10 recalle
d word of definition。
下面是我们总的实验结果:
图六:ALBET实验结果
之前的实验结果:
对比两表的实验结果我们可以看出,ALBERT_base(0.4734)相比BERTBase(0.5242),XLNETBa-se(0.6061),RoBERTaBase(0.6577)效果是最差的。这说明,ALBERT_base经过三大改造(嵌入向量参数化的因式分解、跨层参数共享、以SOP替换NSP),虽然参数量大大减小(从108M降至12M),但是模型性能也下降了。即使加大模型规模-ALBERT_xlarge(隐藏层H从768增至2048)的结果(0.6904)也比XLNETLarge(0.7494)、RoBERTaLarge(0.7740)效果更差。直到更进一步加大模型规模,即ALBERT_xxlarge(隐藏层H增至4096),得到结果0.8124,才超过RoBERTaLarge(0.7740)。
ALBERT为什么能超越BERT、XLNET、Roberta呢?这几年深度学习圈子里一直出现了一些“怪象”,就是堆数据,让模型更复杂,训练出来的效果更好。但真正的智能应该是用更简单的模型,用更少量的数据,得到更好的结果。回顾
我们之前实验过的模型引入数据规模的大小,BERT(13G)、XLNET(126G)、
RoBERTa(160G),还有参数规模,BERT、RoBERT、XLNET都采用了BERTLarge的网络参数:L=24,H=1024,A=16, 参数总量大约3.55亿。这些模型虽然都做了各式各样的改进,但是,模型复杂度并没有改变,而且引入的数据规模越来越大,很难不让人怀疑模型效果全是靠堆数据堆出来的。
在ALBERT的论文中,其实刚开始也试着增大模型规模(BERT-xlarge),但模型效果反而下降,出现某种degradation(退化)。
当前的 SOTA模型常常包含数亿甚至数十亿参数,扩展模型时便很容易受到可用硬件的内存的限制,从而出现退化现象。ALBERT通过两大参数削减技术(嵌入向量参数化的因式分解、跨层参数共享)可以充当某种形式的正则化,使训练更加稳定,而且有利于泛化。然后为了进一步提升 ALBERT 的性能,研究者还引入了一个自监督损失函数,用于句子级别的预测(SOP)。SOP 主要聚焦于句间连贯,用于解决原版 BERT 中下一句预测(NSP)损失低效的问题。[5]正是由于这些改造技术,能让ALBERT在很大程度上降低内存消耗,从而能够扩展为更大的版本。尤其要注意到ALBERT_xxlarge的隐藏层已经扩展到4096规模了(BER-TLarge隐藏层H为1024),这是模型能够进一步提升的重要原因。同时,由于所有层共享一样的参数,不断加深ALBERT的网络结构,无法获得持续的性能提升,所以ALBERT_xxlarge只有12层(BERTLarge为24层)。
ALBERT通过一系列改造,大大降低了内存消耗,从而能够扩展为更大版本-
ALBERT-xxlarge,成功地提升了模型的规模并且减少了参数(规模为BERTLarge的70%)。ALBERT_xxlarge超过RoBERTa也不奇怪了,毕竟,这两者“规模”不一样。
另外,我们再来看看引入wiki数据的情况。引入wiki数据结果为0.8157,
相比不引入的结果0.8124,提升了约3个千分点。提升幅度并不是很大。我们之后在验证集做了实验,引入wiki数据的和不引入wiki数据的分为两组,采用图六ALBERT_xxlarge的参数,分别跑一样的5个随机种子,再对比下实验结果,发现两者区别不大。考虑到引入wiki数据内存消耗太大且推理时间也更长(引入wiki数据句子长度为256,不引入为80),而且提升不明显,我们后面放弃加入wiki数据。
所以,我们最后采取的方案是只用ALBERT_xxlarge模型,沿用表六相应的参数,在验证数据集上,具有单个模型的五个不同种子的准确率分别为80.9%、80.0%、 80.5%、 81.2%、 80.4%。最后进行模型融合,在验证/测试集的准确率是83.7%/76.5%。具体也可访问https://github.com/ZhiyunLab/CsQA/blob/master/desc.md
参考文献:
[1]CommonsenseQA: A Question Answering Challenge Targeting Commonsense Knowledge
- Ming Zhou, Nan Duan, Shujie Liu, Heung-Yeung Shum. Progress in Neural NLP: Modeling, Learning and Reasoning. Accepted by Engineering, 2019.
- 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史
- RoBERTa: A Robustly Optimized BERT Pretraining Approach
- ALBERT: A Lite BERT for Self-supervised Learning of Language Representations