作者 | 周俊贤 整理 | NewBeeNLP
百度21年语言与智能技术竞赛落下帷幕,本人利用空余时间参加了机器阅读理解的赛道,虽然分数不高,但还是有很多想法想跟大家分享。主要的想法就是围绕「如果造更鲁棒的数据」。
比赛的数据集叫DuReader_checklist,我想是受到一篇论文的启发,所以在介绍比赛之前,我想分享一下这篇论文。
CheckList
这篇论文获得 ACL 2020 的最佳paper奖。
论文全称及链接:《Beyond Accuracy: Behavioral Testing of NLP models with CheckList》[1]
论文开源工具链接:https://github.com/marcotcr/checklist
请大家想想一个问题:我们日常是怎么评估模型效果的?如现在做一个文本分类的任务,有1K条标签数据,大部分人的做法就是进行数据集划分,按7:1.5:1.5的方法划分成训练集、验证集、测试集,当我们的模型最后在测试集上准确率98%以上,我们就可以跟产品经理说:模型的准确率是98%。
实质上,这有个弊端就是,假如测试集跟线上应用的数据分布不一致,我们这样计算出来的准确率是有偏差的,所以一种更严谨的表述应该是:模型在这批测试集的准确率是98%。无论如何,把模型的效果用一个单一的准确率指标来评价都是非常危险的。
本人就有亲身经历,线下测试指标很漂亮,但推到生产的时候,错漏百出,本质原因是,线下测试考虑的情况是远远cover不了真实场景的。
论文受到软件测试中"黑箱测试"的启发(这里可以跟你们公司的测试工程发交流一下,问问他们平时是怎么做做软件测试的hh),"黑箱测试"只关心输入-输出的表现,不关心软件内部实现的细节。借鉴了思想,作者提出「CheckList」这样一种新估方法帮助我们更综合地评估NLP模型的能力。请注意,这是一种通用的方法,与任务无关,作者还做了个工具,这个工具帮助我们创建大量CheckList需要用到的数据集。
下图是一个情感分析模型的评估案例,评估用一个矩阵的形式呈现,行是【模型的能力】,列是【测试的类型】,只需填满这个矩阵,就能综合评估模型的缺陷和综合效果。下面我们就从【模型的能力】、【测试的类型】、【如何填充这个测试矩阵】三个方面进行展开。
CheckList三要素
能力-Capabilities
不同于现代NLP模型仅关注特定的任务,如如果一个情感分析的模型,我们只关注模型在测试集上的准确度这种粗粒度的指标,CheckList则希望去评估更细粒度的能力,这些能力有的是NLP模型都通用的,如下面所列的能力:
- Vocabulary POS:是否掌握任务相关的词汇和词汇类型
- Taxonomy:是否理解同义词、反义词
- Robustness:是否能识别错别词或不相关的变化
- NER:是否正确理解命名实体z
- Fairness:这个没搞懂是什么意思
- Temporal:是否理解事情发生的顺序
- Negation:是否理解否定词
- Coreference:是否理解指代关系
- Semantic Role Labeling:是否理解各种角色
- Logic:是否能处理对称性、一致性及连接词
测试类型-Test Types
对于每种能力,可以从三种测试类型进行测试:
- 最小功能测试—Minimum Functionality test(MFT):通过大量简单且有针对性的样子对目标能力进行测试。如上图的测试案例A,用模板生成大量简单的样例来测试模型的Negation能力。
- 不变性测试—Invariance test(INV):给输入一些扰动,看模型输出是否保持不变。如上图的测试案例B,把样本中的地点进行替换,观察模型输出是否改变,来测试模型的NER能力。
- 方向期望测试—Directional Expectation test(DIR):修改输入,期望模型输出是往某个方向变化。如上图的测试案例C,我们在本来是消极的句子后,再加入消极的句子,期望模型输出是往"更消极"的方向进行变化。
其中,INV和DIR测试是不需要标签的,就是一种无监督的测试方法,因为这两种测试方法我们关注的不是模型预测出来的label,而且加入扰动前后输出结果的变化。
批量生成测试用例-Generating Test Cases at Scale
上面只是提到要测试的能力和测试类型,但说到底,还得根据这两个来生成一批测试用例,怎么生成呢?
论文提出可以从头创建测试用例,也可以通过对训练集增加扰动来创建测试用例,具体的,论文介绍了两种方法:
- 模板法—Templates:通过定义模板,然后根据模型批量创建测试用例。举个例子,定义模板"I {NEGATION} {POS_VERB} the {THING}",这里用花括号{}围住的是待填充的词性,如{NEGATION}={didn't, can't say I, ...},{POS_VERB}={love, like, ...},{THING}={food, flight, service ...},然后对所有候选集求笛卡尔集合,这样就可以得到一大批测试用例;
- 扩展模板法—Expanding Templates:模型法虽然好,但弊端在于我们要绞尽脑子去填空我们挖空了的待填补的词性。论文又提出一种方法,我们可以将模板将模板的某些部分遮挡起来,然后用预训练好的RoBERTa对被遮挡的部分进行预测,从而可以得到候选词,扩展模板法相当于做选择,模板法相当于创造,毫无疑问,「做选择比创造要简单不少」。
- 如模板"I really {mask} the flight",用RoBERTa对mask部分进行预测,得到{enjoyed, liked, loved, regret, ...},先对候选词进行过滤,再把这些候选词分成积极、中立、消极用于后面的测试;
- 有时候,我们不需要过滤,如模板"This is a good {mask}",这里对mask进行预测,会得到不同的名词,我们就不需要进行过滤,因为无论是什么名词,这句话的label就是积极;
- 这方法也可以用来对已有数据进行扰动,如对句子中的that、the这种中性词进行替换,"Virgin should I be concerned that I'm about to fly ..."中的that替换成when;
- RoBERTa的生成建议也可与WordNet结合,输出一些特定的近义词或反义词列表;
- 论文也提供了一些现成的常用填充词语,如姓名和地点的命名实体。
作者随论文还发布了开源的工具,用可视化的方式更傻瓜地实现上面所提的CheckList三要素【能力】、【测试类型】、【批量生成测试用例】,而不用我们手敲代码去实现。
实验结果
论文里测试了三个NLP任务:情感分析、重复问题检测、机器阅读理解。
这里只POST情感分析的测试结果出来,参与测试的模型有:
- 微软情感分析API接口;
- 谷歌情感分析API接口;
- 亚马逊情感分析API接口;
- 在SST-2数据集上fine-tunning后的BERT-base(在SST-2测试集上,acc达到92.7%);
- 在SST-2数据集上fine-tunning后的RoBERTa两个模型(在SST-2测试集上,acc达到94.8%)
前三者很明显,都是大厂声称已经"很成熟"的商业应用接口,而BERT-base和RoBERTa是学术界效果较好的模型,按道理来说,商业接口应该比学术上在实际使用中更鲁棒,但测试结果却不是这样的,虽然BERT-base和RoBERTa在CheckList上表现得也没有多好。
具体的,大家可以把上面提到的【能力】、【测试类型】与上图进行对比,加深理解。
- 例子1:测试模型的Vocabulary POS能力,采用最小功能测试,用模板法或扩展模板法创建一大批针对性的测试案例,如图里的"The company is Australian"、"That is a private aircraft"。
- 例子2:测试模型的NER能力,采用方向不变性测试类型,替换输入中出现的地点,而这种输入的扰动,模型的输出应该是不变的,如""@JetBlue I want you guys to be the first to fly to Cuba"(把Cuba改成Canada)。
- 例子3:测试模型的Vocabulary POS能力,采用方向期望测试类型,如在label是消极的输入中,再加入一些消极的短语,我们期望模型输出应该是「更消极」,如"USAirways your service sucks.",我们在最后加多一句"You are lame",我们期望模型输出是往消极的方向,如不是,那模型在这个案例上就是fail了。
论文总结
论文提出了一种与模型无关(不关心模型结构是怎样的)、任务无关(不关心是文本分类任务、情感分析任务或其它任务),一种更通用、更综合的评估方法CheckList,还开源了相应的工具,帮我们更轻松地创建CheckList数据集。但目前这个工具只有英文版,期望有类似的中文工具出现。
百度Lic机器阅读比赛
说完论文,我们说说竞赛。比赛代码链接:https://github.com/zhoujx4/DuReader-Checklist-BASELINE
本次比赛提供的训练集是in-domain训练集,测试集却包含有out of domain的案例(即测试集和训练集的数据分布是不一致的),包括测试【词汇理解】、【短语理解】、【语义角色标注】、【容错性】、【推理】五大类,每大类下又有小类。
我尝试把这五大类跟论文里提到的NLP模型通用能力对号入座,
- 词汇理解:名词、动词、形容词、副词、数词、单位就是论文里提到的Vocabulary POS能力;命名实体就是论文里提到的NER能力;
- 短语理解:这里应该对应的是论文里提到的争对具体任务的能力,并非通用能力;
- 语义角色理解:对称、非对称等同于论文里提到的Logic能力;
- 容错性;等同于论文里提到的Robustness能力;
- 推理:等同于论文里提到的Negation能力。
如何通过数据增强进行上分?
最直接的方法就是「根据测试集上提到的这5大类,根据论文CheckList上的三要素生成一批"增强数据"加入到训练集中」(虽然CheckList是用于生成测试案例来评估模型,但换种思路,我们也可以把生成的测试用例加入到训练集中,让学习出来的模型更有针对性)。
我在参加比赛的时候,还没好好研究CheckList这篇论文,采取的是比较笨的方法——拿question去百度知道进行搜索,把搜索出来的第一页和第15页的内容爬下来(通常第一页的都是语义相似的问题,第15页是词汇相似,但语义不相似的问题),如下图的例子。
本来,训练集的question是问【生花生一天吃多少合适】,从百度爬的第一页中选择语义相似的问题进行增强(如这里选了【生花生一天宜吃多少】),根据百度爬的第15页作为参考,根据比赛提到的5大类生成一个语义不一样的问题(如这里生成【熟花生一天吃多少合适】,对应上面提到的词汇理解中的形容词)。
这样,大概生成了1K多个样本作为增强样本数据集,与原始训练集一起进行训练。大概就是这样半自动半人工的方式吧(起码比要自己从头开始创造问题这种全人工的方法要好)。现在反思,采用CheckList论文里提到的方法能「更高效」地创建有针对性的数据。
其它上分策略
模型采用的就是很传统的mrc模型,具体的可以上开头的github链接。
除此之外,也尝试过以下优化策略
- 继续预训练
- 对抗训练
- 模型融合
但这些策略都不在本次参赛的重点中,本次比赛的重点个人认为就在于「造数据」,个人起码花了90%以上的时间在思考如果做「数据增强,如何增对DuReader_checklist生成更有针对性的数据」,感觉生成更多数据会比其他优化策略性价比来得更高。
我们期待看到获奖团队的报告。
比赛感想:80%的数据 20%的模型=更好的机器学习
这次比赛让我对数据又有更深入的认知,发顶会论文,大部分心思当然花在如何设计模型结构中,但在做实际项目或参加竞赛过程中,有时真的不要太过于纠结模型结构等的问题,相反,我们应优化考虑是否用于训练的数据覆盖面不够广、不够丰富这些问题上。
吴恩达老师说过:「80%的数据 20%的模型=更好的机器学习」。吴恩达老师认为一个机器学习团队80%的工作应该放在数据准备上,确保数据质量是最重要的工作,每个人都知道应该如此做,但没人在乎。
也许,我们面对的是一个冷启动的任务,我们需要自己去造数据,爬数据,我们能否根据CheckList这篇论文的思想去扩充我们的数据集。
也许,我们认为我们训练出的模型已经能满足业务的场景,能否在上线前,再用CheckList方法评估一下模型,做到成竹在胸。
总结来说,我的比赛感想就是,一定要多了解数据,多从更综合的维度去评估你的模型。
本文参考资料
[1]《Beyond Accuracy: Behavioral Testing of NLP models with CheckList》: https://arxiv.org/abs/2005.04118
- END -