Kaggle Tweet Sentiment Extraction 第七名复盘

这是前段时间结束的Kaggle比赛,之前在文档问答的文章中我也有提到过,最终我们队获得了第七名,这篇文章分享一下我的参赛收获和感受。

首先感谢队友曹老师和Morphy老师,特别是曹老师,如果没有曹老师我肯定中途就弃赛了。我的代码已经传到Github上了,感兴趣的朋友可以看一看,里面包含了我所有的commits,可以完整看到我方案的演进。

https://github.com/thuwyh/Tweet-Sentiment-Extraction

Leaderboard截图
Leaderboard截图

赛题回顾

比赛叫做Tweet Sentiment Extraction,对于给定的tweet和情感极性,需要选手从文本中找出支撑情感的部分。例如下面这条数据

"My ridiculous dog is amazing." [sentiment: positive]

模型应该返回amazing这个词。比赛的评价指标是word-level Jaccard score,它的含义看下面的实现就一目了然了。

def jaccard(str1, str2):    
    a = set(str1.lower().split())     
    b = set(str2.lower().split())
    c = a.intersection(b)
    return float(len(c)) / (len(a) + len(b) - len(c))

Baseline及一些改进

在比赛的初期讨论区和kernel分享区基本就定下了解题思路的基调,即用机器阅读理解(MRC)的方法来做span prediction。具体的说,就是把数据提供的情感词作为question,把tweet作为context,把预测对象作为answer。

模型也很简单,在RoBERTa后面接一个QuestionAnswering head预测start和end位置就可以了。这道题一个比较神奇的地方就是RoBERTa的效果比普通的BERT要好一些。

在这个框架下,大家也都做了一些改进,例如:

  • 在语言模型输出后面加dropout
  • concat语言模型的多层输出结果
  • 引入FGM等对抗训练方法

以上都是一些比较常规的操作,也比较容易实现,而且其中的对抗训练是比较稳定能提分的。还有一些稍微复杂一点的trick,例如:

  • 在词级别进行数据增强,例如同义词替换,随机删词
  • 在token级别的增强
  • label smoothing
  • 蒸馏

因为是span prediction任务,数据增强如果做成随机动态的,需要考虑到改词后对label的影响,这是实现的一个小难点。英文的同义词替换可以使用wordnet来做,相比中文的一些同义词库来讲质量是比较高的。我实验下来这部分也能提一些分,但不是特别显著。

label smoothing和蒸馏是很相关的两个技术,因为他们都需要用到KL散度作为损失函数。做QA任务通常是对位置用CrossEntropyLoss,但是如果label不是一个确定的位置而是平滑过或者是teacher model预测得到的分布,就需要使用KLDivLoss。我也是趁这个比赛补了一补相关的知识,感觉还蛮有趣的,感兴趣的朋友可以参考这篇文章[1]

标签平滑在论坛里被吹得挺神,在曹老师的模型上也确实有不错的表现。我在做的时候遇到了一个小问题,蛮值得思考的。我们知道早先Google在Inception网络上就使用过这个技巧,对于Imagenet这个分类问题标签的种类是确定的K=1000类,所以在Inception论文[2]里直接用一个系数来控制平滑的强度,即平滑后的标签

但是如果用同样方法在这些长短不一的句子上做平滑,其实是不合适的。每个位置的平滑概率反比于句子的长度,也就是K,所以我认为更好的确定平滑强度的方法是先确定一个单位平滑强度,再根据句子总长来确定原标签的权重。

针对数据特点的方法

这次的数据总体质量很差,噪声(其实是错误)很多,给参赛者带来了很多困扰。主要的噪声模式有两种,一种是把整个句子都标注成了支撑情感的selected_text,第二种是数据中有大量“断头词”出现在标签中。下图给出了一些例子。

第一行和第三行都是噪声数据,第一行整句都被选成了selected_text,第三行的字母y无法在word层面被预测
第一行和第三行都是噪声数据,第一行整句都被选成了selected_text,第三行的字母y无法在word层面被预测

对于第一种整句都是标签的情况,早期很多参赛者就发现了对于neutral类型的情感,绝大部分selected_text都和text一样,所以一直流行直接将text作为预测结果的粗暴后处理方法(jaccard值可达0.96);但对于其他情感,我们在人工审阅数据之后并没有发现什么规律。我只好硬着头皮设计了一个辅助的分类任务让模型自己学习,实测下来有些微的提升,但并不明显。

对于“断头词”的情况,我们在比赛的末期终于发现了其规律,即所谓的Magic。这种情况应该是由于标注流程的失误导致的。例如Twitter数据里有很多@用户的情况,也许是出于隐私的考虑,这份比赛数据集会把相关的文本删除,但由于删除脚本的问题会导致文本中多出一个空格。我们猜测标注者看到的数据应该是没有多余空格的,类似于使用' '.join(text.split())处理过。这就会导致标出来的span相对于原text的位置产生了位移。且位移的大小就等于多余空格的数量。

在发现这个规律后,我先是采用规则平移标签修复了selected_text,获得了不含“断头词”的标签,再用干净的模型进行预测,最后再用规则反向平移标签。曹老师则仍然使用原始标签训练,只在预测时加入平移后处理。

这部分只能对这个比赛适用,不能对其他任务的处理提供太多的启发,如果读者感兴趣可以参考我开源的代码,我就不展开说明了。在赛后发现前排队伍使用了更“智能”的方法来建模这个问题。他们在普通的token level模型基础上套了一层char level模型,让机器自行学习这个前后处理的过程,非常fancy。感兴趣的朋友可以去讨论区看他们的方案。

关于比赛的一些感想

不知不觉Kaggle账号注册也快三年了,大大小小参加了20多个各种类型的比赛。从这些比赛里我收获了很多,认识了很多朋友,也学到了很多知识。但现在已经明显感觉到比赛的边际效用在大幅的减小。

很重要的一个原因是我感觉比赛的质量下降了。以这个比赛为例,主办方居然连标签数据都搞错了,而且在长达几个月的赛程中,没有人去修复它。我完全无法理解这种过拟合错误标签的意义是什么,所以越做越痛苦,大概做了一个多月就不想做了,一度弃赛。后面在曹老师的鼓励下才坚持到最后,发现了trick,用正确的标签训练了模型。虽然这个比赛有点极端,但即使数据没有错,比赛的目标是错的或不可达到的情况近来屡见不鲜。越来越多的比赛会有巨大的Shakeup,很多选手辛辛苦苦搞几个月最后结果还不如最开始讨论区放出的baseline kernel。这一方面提醒我们算法不是万能的,很多事情就是无法使用机器学习预测;另一方面这种负反馈很容易给参赛者特别是初学者的学习热情浇上一盆冷水,比赛带来的愉悦感大受影响。

另一个原因是随着工作年限的增加慢慢地会体会到算法只是价值链条中的一环。比赛是在一个相对封闭的环境里解决别人抽象好的问题,但现实中解决问题的要义可能正是打破这种封闭,例如做更合理的问题定义、改进采集流程获得更高质量的数据等等。之前很多同时期做比赛的GM比如植物、涛神都渐渐淡出了比赛圈更多地投入到工作中可能也是因为这个原因。

但不管怎么样,如果三观摆正,比赛还是一个快速学习提高的有效途径。而能稳定地在多个比赛里做到top1%,应该也是对能力很好的证明。建议初学者在开始投入一个比赛前,可以先进行一下可行性分析,识别出高质量比赛,避免踩坑。

关于这个比赛就写到这,大家有什么问题可以去github提issue或者加我们的微信群交流。

参考资料

[1] 交叉熵、相对熵(KL散度)、JS散度和Wasserstein距离: https://zhuanlan.zhihu.com/p/74075915

[2] Rethinking the Inception Architecture for Computer Vision: http://arxiv.org/abs/1512.00567

跨模态语言模型

今天聊一聊近年来挺火的“多模态”任务。其实这不是我们第一次聊到多模态了,之前发的Kaggle PetFinder比赛方案其实就在解决一个多模态预测的问题。准确地说今天介绍的模型都是“双模态”,即同时处理文本数据和图像数据。

多模态任务

虽然生活中需要处理多模态输入的场景比比皆是,但众所周知,目前的AI水平还比较低,只能处理一些特定的任务。在介绍模型之前,我们先介绍几个在当前研究中常见的多模态问题。

视觉问答

比较有名的是视觉问答VQA,简单的说就是针对图片提问题让计算机回答。有一个叫VQA的著名数据集,发布于2015年,2017年发布了最新的2.0版本。数据集包含大约二十万张图片、一百多万个问题以及一千多万个标注答案。就像之前的ImageNet一样,每年都有针对这个任务的挑战赛,2020年第一名的accuracy已经达到了76.36%,2017年这一数字是69%。

VQA数据集样例
VQA数据样例
继续阅读“跨模态语言模型”

跨语种语言模型

感谢清华大学自然语言处理实验室对预训练语言模型架构的梳理,我们将沿此脉络前行,探索预训练语言模型的前沿技术,红框中为已介绍的文章,今天介绍一个可能大家比较少接触的分支——多语种语言模型(multilingual language model)。

在著名的科幻电影《银河系漫游指南》里有一种叫巴别鱼的神奇生物。将它塞进耳朵里你就能听懂任何语言。多语种语言模型做得事情和巴别鱼很像,人们希望这个模型能用来处理所有的语言。举个例子,大家常用的中文bert有很强的中文处理能力以及一定的英文处理能力,但基本也就只能处理这两种语言;而目前的SOTA多语种模型XLM-RoBERTa能够处理104种语言。

巴别鱼,体型很小,黄色,外形像水蛭,很可能是宇宙中最奇异的事物。它靠接收脑电波的能量为生,并且不是从其携带者身上接收,而是从周围的人身上。它从这些脑电波能量中吸收所有未被人察觉的精神频率,转化成营养。然后它向携带者的思想中排泄一种由被察觉到的精神频率和大脑语言中枢提供的神经信号混合而成的心灵感应矩阵。所有这些过程的实际效果就是,如果你把一条巴别鱼塞进耳朵,你就能立刻理解以任何形式的语言对你说的任何事情。

巴别鱼剧照
巴别鱼剧照
继续阅读“跨语种语言模型”

表格问答3:落地应用

我们前面的两篇文章介绍了表格问答相关的数据集模型,今天介绍两个表格问答技术的应用。

Excel Ideas (创意)

不知道大家还记不记得,上一篇文章中的X-SQL和HydraNet都是来自微软的模型。微软作为一个老牌科技公司近年不仅在云计算领域迎头赶上,在AI方面也有很多优秀的技术创新和应用。依托于强大的Excel,他们在表格问答方面也有很好的落地土壤。

MSRA去年底发表了一篇题为智能数据分析技术,解锁Excel“对话”新功能[1]的文章,介绍他们在Excel中如何构建所谓“对话式数据分析”。他们认为这个场景中有下面几个核心问题:

  • 理解和识别表格数据,例如表头、类型等元信息;
  • 表格知识增强,例如实体识别和常识注入;
  • 自然语言理解;
  • 面向分析的渐进式对话,让用户可以用多轮对话进行数据探索(EDA);
  • 交互能力,这一点和3比较接近。

而NL2SQL应该是覆盖了上面几个领域的集大成者。

对话式数据分析的研究问题[1]
继续阅读“表格问答3:落地应用”

表格问答2:模型

今天介绍两个NL2SQL模型,X-SQLHydraNet。它俩都来自微软,分别推出于2019年和2020年。X-SQL跟它之前的方案比如SQlNETSQLOVA都比较像,很有代表性;HydraNet对前人解决问题的大框架做了一些修改,变得更加简洁,也更符合预训练语言模型的使用习惯,应该会给大家一点启发。

为了方便大家阅读,我们先来回顾一下WikiSQL的预测目标。WikiSQL数据集进一步把SQL语句结构化(简化),分成了condsselagg三个部分。

  • sel是查询目标列,其值是表格中对应列的序号;
  • agg的值是聚合操作的编号,可能出现的聚合操作有['', 'MAX', 'MIN', 'COUNT', 'SUM', 'AVG']共6种;
  • conds是筛选条件,可以有多个。每个条件用一个三元组(column_index, operator_index, condition)表示,可能的operator_index共有['=', '>', '<', 'OP']四种,condition是操作的目标值,这是不能用分类解决的目标。
继续阅读“表格问答2:模型”

表格问答1:简介

在公众号的第一篇文章中我们介绍了一个厉害的开放域问答系统 REALM,它可以根据自然语言问题从知识库中找到相关文章并从文章中找到问题的答案。REALM 这种直接从文章中获取答案的设定在问答领域称为非结构化文档问答,接下来我们将用几篇文章介绍一下与之相对应的结构化文档问答中的一个重要分支表格问答

什么是表格问答

表格大家都不陌生,谁电脑里没几个excel文件呢。它其实是一种信息密度很高的文档类型,与文章相比,更加适合作为电商、查询等场景的知识源。用表格来提供信息不仅方便业务端梳理知识,而且结构化的数据给算法端进行信息聚合、比较甚至推理提供了更肥沃的土壤。

下图是 MSRA在2018 年底发的一篇文章的插图,里面对表格相关 NLP 问题有一个比较完整的呈现。其中涉及了检索、语义解析、生成和对话等多个方向。

如图所示,表格问答就是针对一个自然语言问题,根据表格内容给出答案。

继续阅读“表格问答1:简介”

叫我如何相信你?聊一聊语言模型的校准

模型校准这个话题可能比较小众,但却真实地困扰了我们很长时间。碰巧最近看到arxiv上这篇论文[1],就决定写一篇文章跟大家交流。论文很新,十天前作者刚更新了一版。

论文截图

什么是校准

在实际的NLP业务场景中,我们经常遇到一个问题就是调阈值。因为我们需要把模型输出层sigmoid函数或者softmax函数给出的连续的预测概率转化成离散输出,所以需要一个阈值来决定你如何相信你的模型。特别是当应对的领域(domain)复杂多样,而训练数据来源比较单一的时候,如何选择一个比较平衡的阈值是一个尤为棘手的问题。

如果模型给出的概率值和经验概率是匹配的,即模型是“已校准的(calibrated)”,则会大大方便模型的使用和部署。举一个直观的例子,如果在2分类任务里取出100个模型预测概率为0.7的样本,其中有70个的真实标签为1,则称为模型的后验概率和经验概率是匹配的。这这个情况下,使用者可以对模型给出的概率值的误判风险有直接的判断。

继续阅读“叫我如何相信你?聊一聊语言模型的校准”

解读Beam Search (2/2)

在上一篇文章中我们介绍了基础版的beam search,这篇文章是对它的一个扩展,可以在模型不改的情况下获得更好的生成结果。今天的介绍围绕的也是一篇蛮新的论文,《The Curious Case of Neural Text Degeneration》,根据这篇论文的版面内容,它应该已经被ICLR 2020接收了。

论文截图
论文截图
继续阅读“解读Beam Search (2/2)”

解读Beam Search (1/2)

最近研究了一下用基于BERT的encoder-decoder结构做文本生成任务,碰巧管老师昨天的文章也介绍了以生成任务见长的GPT模型,于是决定用两篇文章大家介绍一下在文本生成任务中常用的解码策略Beam Search(集束搜索)。

解码及贪心搜索

生成式任务相比普通的分类、tagging等NLP任务会复杂不少。在生成的时候,模型的输出是一个时间步一个时间步依次获得的,而且前面时间步的结果还会影响后面时间步的结果。也就是说,每一个时间步,模型给出的都是基于历史生成结果的条件概率。为了生成完整的句子,需要一个称为解码的额外动作来融合模型多个时间步的输出,而且使得最终得到的序列的每一步条件概率连乘起来最大。

在文本生成任务中,每一个时间步可能的输出种类称为字典大小(vocabulary size,我们用\(v\)表示),进行T步随机的生成可能获得的结果总共有\(v^T\)种。拿中文文本生成来说,\(v\)的值大约是5000-6000,即常用汉字的个数。在如此大的基数下,遍历整个生成空间是不现实的。

继续阅读“解读Beam Search (1/2)”

Kaggle TensorFlow 2.0 Question Answering 16名复盘

比赛
比赛题图

这是Kaggle春节前结束的一个阅读理解的比赛,我和管老师曹老师最终获得16/1233的成绩。成绩来自于管老师的提交,我自己的最好成绩大概排在23名的样子。

数据集

这次比赛的数据集来自于Google,名为Natural Questions,简称NQ。数据集早在19年初就已经公布,在官网上还有排行榜。

这个数据集和SQuAD挺像的,关于SQuAD的介绍大家可以在这篇文章中找到。NQ的训练集包含30多万个样例,每个样例包含一篇来源于维基百科的文章和一个问题。每篇文章可以被分为多个“候选长答案”,所谓候选长答案,可能是一个段落、一张表格、一个列表等等。候选长答案有可能有包含关系,但大部分的标注出来的长答案(95%)都是顶层候选长答案。在所有样例中,有大约一半样例的问题可以用候选长答案来回答。对于有的问题,还可以用更加简短的文章区间来回答,这种区间称为短答案。大约有三分之一的样例可以用短答案来回答。短答案并不一定是一个连续区间,有可能是多个离散的区间。

继续阅读“Kaggle TensorFlow 2.0 Question Answering 16名复盘”