区别于传统低效标注,两种基于自然语言解释的数据增强方法

本秂侑毒 提交于 2020-10-01 23:16:45

本文内容整理自 PaperWeekly 和 biendata 在 B 站组织的直播回顾,点击文末阅读原文即可跳转至 B 站收看本次分享完整视频录像,如需嘉宾课件,请在 PaperWeekly 公众号回复关键词课件下载获取下载链接。

作者简介:秦禹嘉,清华大学电子工程系本科生,大二开始在清华大学自然语言处理实验室学习。导师刘知远副教授。主要研究方向为义原知识体系的完善与应用。

尽管深度学习模型已经在许多自然语言处理任务上取得了非常好的效果,它们通常依赖于大量的训练数据;然而在实际应用场景下,标注能力、训练数据并不充足的情况经常出现,因此如何让标注者高效率地标注是一个十分有意义的问题。

传统给出标签的标注方式在一定程度上限制了标注者能够提供的信息量,很多情况下我们不仅关注标注者打出的标签,更加关注于其打出该标签的理由。因此一种更加高效的做法是让标注者在给出标签的同时给出相应的自然语言解释来解释其做出该决定的原因。

本文将分享应用自然语言解释的一些挑战,并介绍目前应对这些挑战做出的探索和最新工作。


自然语言解释的概念与背景

如开篇所讲,深度学习的技术已经在许多自然语言处理的任务上取得了很好的效果,但是仍然还有两个问题没有解决。第一个是模型通常需要大量的数据。第二个是模型缺乏可解释性。

先看 data hungry 的问题,很多情况下我们并没有那么多的数据能够喂给模型,那么这个模型的鲁棒性就会受到一定的影响。同时即使模型能够达到非常高的准确率,我们也不能 100% 确定它就是在以正确的方式来做出判断。

比如说它很可能完全不是按照我们设想的、它应该这么做的方式去给出了一个正确的答案。我们更期待的是模型能够在给出一个标签的同时,能够提供一个模型的可解释性。

我们先看一下传统的标注方式的整体的流程:首先让标注者看一个例子,对例子彻底分析后,他就可以给出一个标签。这样一个流程看似简单,但暗藏很多的问题,如果一个标注者看完一个例子,他只能给出标签的话,他提供的信息是非常少的。这也就是为什么我们常常会觉得标注者的效率非常低。

我们如何能让标注者对每一个例子提供更多的信息?我们认为鉴于他已经对这个例子有了一个透彻的理解与分析,在允许标注者在提供标签之后,再给出一段自然语言的解释,去解释是如何做出这样一个标签的决定的。


基于自然语言解释的数据增强两大方向

目前来说基于自然语言解释的数据增强,总共有两个大的方向。第一个方向我归纳为隐式方法 implicit way,这类方法通常需要大量地去标注一个非常大的自然语言解释的数据集,用比如说 language model 的方式去进行一个大规模的训练,从而让模型能够在分类的同时,解码出自然语言的解释。


第二类是直接方法 explicit way,这一类方法它就不需要大量的自然语言解释,它更加强调数据标注的效率。这一类方法通常会用 semantic parsing 也就是语义解析,将无结构的自然语言解释转换成结构化的可标注函数,再利用这些可标注函数应用到下游任务上。

这两个方法我会分别介绍几篇最近的工作,其中前三篇我会简单介绍一下他们的思路,我会详细的介绍第四篇文章 Learning from Explanations with Neural Execution Tree 。这篇是我们在 ICLR 上发表的一篇工作,是南加州大学 INK 实验室与清华大学自然语言处理实验室合作完成的一篇工作。

首先我们来介绍隐式方法,来看第一篇文章,也就是 e-SNLI: Natural Language Inference with Natural Language Explanations。

我们知道人类不仅仅从老师提供的带有标签的例子中去学习,相反他们通过演示和解释去寻求对任务的概念性理解、简单的训练以获得高精度的机器学习模型,但这通常会严重依赖浅层输入统计信息,从而使模型的鲁棒性不好。

为了使机器学习获得更加广泛的应用,模型必须能够为他们的决策提供强大的可解释性,并在训练时从人类的提供的解释中去学习。

自然语言解释在这样的任务下,我认为有三大优势。首先自然语言对于需要维护模型可靠性的最终用户来说是非常容易理解的。其次,对人类而言,提供自由形式的语言也是最容易的,从而省去了去学习一个正式的语言所需要的额外工作。

所谓正式语言,比如说它可以是一种类似编程性的语言,如果我们只是一个普通老百姓,其实我们很难人人都能掌握一套编程语言。最后自然语言解释最终可能会从现有的大规模的自由格式的文本中挖掘出来。

来看第一篇论文。在上图这项工作中,作者对斯坦福自然语言推断数据集也就是 SNLI 的每一个例子,去标注了一个自然语言的解释,相当于在原来的 SNLI(Natural Language Inference)的基础上发布了一个新的数据集。自然语言推断是一项至关重要的自然语言理解的任务。

它的任务大概是这样的:我们给定两个句子,这个任务需要判断这两个句子之间的关系,而这个关系总共有三种,第一种是 contradiction,表示这两个句子是有矛盾的。第二个关系是 entailment,也就是说往往是第一个句子表述的信息能够推出第二个句子。第三种情况是 neutral 中立的,也就是说这两个句子其实没有什么关系,它们既不是互相矛盾的,也没有任何能够推出的关系。

看上图第一个例子。Premise 是第一个句子,Hypothesis 是第二个句子。他说 An adult dressed in black holds a stick。第二句说 An adult is walking away, empty-handed。这两个句子明显是互相矛盾的,第一句话说人拿着根棍子。

第二个说他手里是没有东西的,所以他们就是矛盾的。看 Explanation,就是作者给它标注的一个解释,说 Holds a stick implies using hands so it is not empty-handed。很好地解释为什么这两句话是一个矛盾的关系。

我们再去看第三个例子,第一句话说  A man in an orange vest leans over a pickup truck。第二句说  A man is touching a truck。leans over 和 touching,某种程度上可以勉勉强强说它们是在形容同一件事情,所以我们的标签可以给出一个 entailment 的关系。

我们看它所标注的一个解释,Man leans over a pickup truck implies that he is touching it。那么解释的核心思路是想指出 Premise 中的某一个短语或者说某一个词语,以及 Hypothesis 中的某一个短语或者词语之间存在什么关系,比如 holds a stick implies using hands so it is not empty-handed。这里的  implies,相当于构建了一个从 Premise 到 Hypothesis 一个桥梁。

再看 SNLI 数据集,作者如果能给 57 万个例子全部标一个自然语言的解释,那么我们很容易就可以用 language model 去训练,从自然语言的解释中找到  Premise 对应的、highlight 强调性的短语,以及 Hypothesis 中对应的一个强调性的短语,然后再从 Explanation 中去学他们到底是不是在说同一件事情,还是说有 contradiction, neutral 或者 entailment。

这篇工作的数据集是在一个叫 Amazon Mechanical Turk 的工具平台上标的,标完之后,作者做了一些实验去论证了他的五个观点。

第一个观点是他证明了依靠 SNLI 中的浅层信息提供正确标签的模型,将无法轻易地去提供正确的解释。这个什么意思呢?

作者之前有一篇论文,证明了如果有一个模型,不给它喂这两个句子,只喂给它第一个句子 Premise 让它去做分类,它一样能够达到将近 67% 的准确率。这个是一个非常奇怪的数字,因为像这样一个任务,如果你不能看到这两个句子,完全就只能瞎猜,因为这个任务是说这两个句子有什么关系。

为什么会有这样的一个实验结果?准确地说就是数据集标得不够好,比如,有可能所有 Premise 中含有 holds a stick 这样的短语,全部都是 contradiction。这就是所谓表层的信息,这些 Premise 中的一些特定的词语,往往被认为是某些标签的有利指标。

因此,他们对经过 SNLI 训练的模型是否是真正的学习理解自然语言是表示怀疑的。这篇文章作者其实想说即使有一个模型能够从这些浅层信息中学到一个正确标签,但是它不能提供一个正确的解释,这是一个非常自然而然的想法,毕竟我只看一个句子,确实没有办法说出它到底为什么有这个标签,因为我要得到这样一个标签,一定是要用两句话。

第二个实验证明了先让这个模型去预测一个标签,然后让它去生成对这个标签的解释,这一套是可行的。怎么去评测这个解释符不符合呢?他找人去评测,找了另一批标注者去看生成的这一段解释,看这段解释有没有语法错误,连不连贯,以及能不能够正确地解释这个标签的原因。

第三个实验其实是一个更加自然的想法,就是我们去做出这样一个判断,通常不是先给出一个标签再去给出一段解释,而是心里先有一段解释以后,再根据这个解释去生成一个标签。他发现先生成解释再得到标签,加上这个数据集的结果,可以比原来的那个效果好一些。

第四个实验用一个模型,在一个 BiLSTM 之上加一个 max pooling 的 encoder,在这样的一个 SNLI 以及它标注的这些解释上,可以学习到更好的句子表示。之前有一篇工作,用了 BiLSTM+max pooling 这样一个模型,只在 SNLI 上这么大的数据做一个 pretrain,然后 fine-tune 到其他的一些句子分类的任务上,可以得到一个非常好的效果。

pretrain+fine-tune其实是最近几年 NLP 的一个老套路了,这篇其实做的也比较早。这篇 ELCLR 作者想说明的是,现在不止在 SNLI 上 pretrain,还在我的 Explanation 上 pretrain 可以得到更好的句子表示。

第五个实验是在 SNLI 上以及我的这个数据上做,可以传 transfer 到其他的 SNLI 数据集当中去。它这个模型大概是怎么设计的呢?如下面图表 9 所示,这是它主要的模型,可以看到它是把这两个句子分别用一个 share 的 encoder 去把它 encode,得到了一段句子表示。

这两段句子表示去分类,就可以得到一个标签。因为标签总共只有三个,是 contradiction、neutral,以及 entailment,它可以把这三个标签都给一段 embedding,随机初始化,在训练中自己 fine-tune,然后它会把这样的一个标签的 embedding,传递给它这边的另一个模型。

这个模型其实就是一个解码的模型。模型输入来自于两个,一个是上文说的 label embedding,另一个是 encode,这两个句子得到一段表示。这里所有的东西都非常像我们说的 machine translation,也就是它一个词一个词地解码,Explanation 中的每一个词,然后得到一段 Explanation。这个 f 是 encoder,右边是一个 BiLSTM,它把第一个句子、第二个句子全部变成 U 和 V 这样两个句子表示。

如上图,第一个是 U 的表示,第二个是 V 的表示,第三个是 U 和 V 的差的绝对值element wise,第四个是 U 和 V 的点击也是 element wise,这样就得到四段 embedding,把它这四段 concat 起来,送到一个 fully-connected 和 layers。如果需要分类,它就送给一个 softmax,如果不需要分类就是送给 decoding。

第二篇工作是 Explain Yourself! Leveraging Language Models for Commonsense Reasoning。和第一篇工作总体思路非常相似,差别在于本篇作者关注的是常识推理任务。常识推理涉及模拟人类,对人类每天遇到的普通情况的类型和本质进行推测。

常识推理实际上是比较艰巨的任务,尽管已经有很多工作在 commonsense reasoning 上取得了非常好的进展,但是我们仍不清楚这些模型到底是如何进行推理的,以及在多大程度上是基于世界知识进行推理的,这点和第一篇工作非常相似。

作者也针对一个常识推理的数据集收集了大量的自然语言的解释,我们可以来看这样一个例子,比如说他的问题是 While eating a hamburger with friends,what are people trying to do?备选项有三个,第一个是 have fun,第二个是 tasty or indigestion。

这样一个问题,其实我们人类看来就很容易得出答案是 have fun,因为你和朋友吃汉堡其实都是挺开心的一件事情。

CoS-E 就是给它标注的一个解释:Usually a hamburger with friends indicates a good time。其实你可以看到它在这边标解释的套路跟之前那篇文章是非常相似的,它会从 question 里面找一个关键词或者关键的短语。怎么把 choices 中的某一个答案去连接起来,比如说 a hamburger with friends indicate 或者 implies 都可以 a good time。

因为 a good time 其实和 have fun一样。如之前所说,如果我们能够标一个大量的数据集,让 language model 去训练,他就是可以从这样的一个解析中学到怎么去 highlight,怎么去把两个 highlight 的东西连接起来。

模型设计其实跟第一篇工作也非常像,比如说这是一个 language model,它怎么训练呢?它把 question 和三个 answer 全部先 concat 起来,比如说我已经解码出了自然语言解释中的前 i 个词,我要解码第 i 个词 ,我就以它们作为先验去解码出它,这里的训练方式就是一个 language model,解码都是老套路了。

比如说在测试的时候,我已知 Q、,我先用我的 language model 去做一个解码,得到一段自然语言的解释。我把 Q、A,以及这样自然语言解释,同时送到一个模型中去分类,得到一个结果,就是其中之一。其实我们可以看到,如果我们在这里把这一部分去掉,其实它就是一个普通的 Q、A 的分类模型了,这是第二篇论文工作的主要内容。

前两篇工作总的来说是自然语言解释隐式的应用方法,需要标注一个足够大的自然语言解释的数据集,用 language model 进行大规模的训练。

自然语言解释和自然语言理解不是同一个意思,自然语言理解是偏向一种任务式的定义,自然语言解释就是主要讨论的一个类似于额外的监督性的信息来源。刚才说的是前两篇工作方法,需要标注一个足够大的自然语言解释的数据集,用 language model 进行大规模的训练。第二种方法就是直接的方法,它不需要大量的标注自然语言来解释。


我们看第三篇文章,Training Classifiers with Natural Language Explanations,之前已经提到过,我们标注的做法通常是让标注者先看一个例子,让他评估例子的相关性,最后再提供标签,但是这样标只能提供很少的信息,所以就引出这样一个问题:如果标注者已经花了很多力气阅读和理解的一个例子,我们如何才能从每个例子中去获得更多的信息?

作者在这篇文章中提出了一个框架,标注者为每个例子的标签提供一个自然语言的解释,这些解释会被解析用 semantic parsing 变成解析函数和注释标注函数,这些标注函数可以在许多其他还没有经过标注的数据上去执行一个标注功能,从而就能整体生成一个大型的弱监督的数据集。

当然这个大的数据集就可以用来训练分类器。比如说我们看上图的例子,做的是一个 relation extraction,也就是关系抽取的一个任务,要判断某个化学物质是不是能够导致一种疾病。

首先标注者会选一个 yes or no,选完之后去给解释,如果我们看到这两个中间有一个 due to,明显就是因果关系,是因果式的。words “due to” 出现在这两个东西中间,这样一种解释,我们怎么去把它变成一个标注函数呢?

我们是用 semantic parsing 的方式,大家可以看出标注函数大概长什么样。其实这是一个很 python 的一个写法,他说如果 due to 出现在 chemical 和 disease 中间,它就返回 1,其实我们可以直接拿来在其他的一些 dataset 上进行标注。

例如我们还有一个例子,也是两个 due to 出现在 chemical 和 disease 中间。但它跟这个例子不一样,对于这样的一个例子,我们就完全不需要再找人标注,我们有了这样一个labeling function,就可以把所有的这些例子全部标注得到。


这里简单讲一下是怎么把 Explanation 变成 labeling function 的。作者在这里用的是一个基于规则的 semantic parsing,也就是语义解析的一个工具。比如说对于这样一个句子,label false because x and y are the same person。他首先把这样每一个词去映射到一个他预先设定好的 predicate 谓语。

这些谓语,我第一遍全部映射好了,因为他是一个基于规则的,他就人为先验地去定义许多的规则,比如说 ARG、AND、ARG 这三个谓语可以组合成一个新的谓语 ARGLIST,is equal 可以组合成一个新的谓语 ISEQUAL,一步一步组合,直到组合到一个顶节点,这样它就变成了一个 parsing tree。

这个 parsing tree 其实和这样一个 labeling function 是等价的。我们可以直接把它转化成上面这样的一个形式。


看一下上图中整体的框架。对于这样一个任务,我们要标注是否第一个人嫁给了第二个人。对这样的例子,标注者先标是的,然后给出一段自然语言的解释,我们用这边用 semantic parsing,把所有这样的东西都变成可标注的函数 labeling functions。

然而得到这些函数后并不是说 100% 都是有效的,一方面它可能标的就有问题,另一方面这个 rule based parser 也不是说它 100% 就能把我所有的自然语言解释都转化成正确的 labeling function,所以他这里做一个 filter,把那些明显错误的 labeling function 也去掉。

去掉之后,剩下的 labeling function,我就可以在其他那些大量的去进行标注,在那些没有标注过的数据上,比如说 X1、X2、X3、X4,都是未经标注的一些数据,我的这些 labeling function 能给它打出 1 或者 -1,1 代表确实是,-1 代表不是,这样可以看出一个简单的矩阵,它就直接拿这个信息去进行训练。

可以看到它送到一个下游的分类器当中的时候,这个分类器简单到你只要用一个 logistic regression 就可以去实现。它就可以达到一个非常好的效果。


上图给出了主要实验的结果,做了三个数据集,这是一个平均的结果。BL 代表的是用这种标注方式先给标签,再给自然语言解释得到的效果,这里只用了 30 个,就达到了 F1 是 46.6。TS 代表的是传统的只给标签的方式,比如说可以看到 30 个自然语言解释的,46.6 已经接近 3000 个传统标签的效果了。

假设我们标注一个自然语言解释的时间是标注一个标签的两倍,我们这边标注效率的提升就起码是 3000÷30÷2,就 50 倍的效率提升了,46.6 差不多这两个中间。所以总的来说,我们用这种方式可以大大的提高我们的一个标注效率。


来看最后一篇 Learning from Explanations with Neural Execution Tree。也是今年发表在 ICLR 上的一篇工作,由是南加州大学任翔老师的 INK 实验室和清华大学自然语言处理实验室合作。


我们可以看一个简单的例子:对于一个情感分析的任务来说,我们要标一个 term 是积极的还是消极的。我们可以给出一个解释,积极的,因为有 very nice 这样一个词出现在 term 后面,不超过三个词,这是对情感分析来说。

对于关系抽取任务来说,他想去标注这两个是什么关系。比如说标注的结果是他们有雇佣的关系,因为他说主语和宾语之间只有一个词“coach”,就是教练,这样一个词在中间,所以他们有一个雇员的关系。


看到这样一个例子,包括当时我们在进行数据收集的过程中,会发现我们直接去利用自然语言的解释的话,有两个困难。

第一个困难,自然语言解释本身是无结构的,我们需要预先将其转换成可执行的标注函数,才可以将它作用到大量的无标签的数据上,但是这一点其实已经被之前的工作也给解决了。第二点是我们在实验中发现,标注者通常会给每一个例子去给出一个过分细致的解释,这就使得自然语言解释的泛化能力会受到限制。

什么叫泛化能力呢?比如说标注者给出的一个自然语言解释,有这样一个非常严格的限定,某一个特定的词组,出现在句子的某一个特定的位置,这样它确实符合他目前要标的这个例子,但是我们能不能把它利用到其他的数据上呢?其实就很困难,因为能符合这么严格限定的句子非常少。

针对这两个问题,我们就提出了这样一套框架。首先我们也是用 semantic parsing 去解决第一个问题,自然语言无结构的问题。对于第二个问题,我们提出了一个叫 Neural Execution Tree 的执行框架,大大提升自然语言解释的泛化能力。这个思路就是将原先的严格匹配,放宽它的限制,变成一个模糊匹配。


如上图,我们用 hard matching 来代称严格匹配,也就是直接匹配。用 soft matching 来代称模糊匹配。什么是直接 hard matching?比如我们可以看到上图这个例子,对于这样一个例子,以及我们得到了一个解释,说只要 fair 这个词直接在 price 这个词之前出现。

注意,是 directly preceded by,它一定要就在这个词之前。如果说我看到了另一个句子里面 fair 和 price 中间还有一个词,它就不满足 directly 的要求。

还有一种情况,比如说我看到的不是 fair price,我看到的是 cheap price,它也没有办法匹配到。但是刚才我讲的这两种情况,其实总体来说,都是可以被自然语言解释所囊括的。不管是 fair price 也好,还是 cheap price 也好,因为 fair 和 cheap 在语义空间上也是非常像的。

另外,fair 如果和 price 中间还有一个词的间隔,那跟它直接连接起来其实也差不太多。所以我们就想能不能把这样一个严格的限制,在某种程度上稍微放宽一点,让这样的例子也能得到匹配?匹配以后,我们就可以继续把它送给一个下游的模型来进行训练。这就是我们要做的一个整体思路。


来看一下任务概览,我们任务的输入是一个非常大的数据集,且是没有经过任何标注的。开始只从里面随机去选一小部分进行标注,也是既标注标签,也标注一个自然语言的解释,目的是想输出一个分类器,可以看到我们的目标是想用自然语言解释去提高标注的效率。

像之前一样,我们可能只需要 50 个自然语言的解释,就可以击败 2000 个传统的标签的方式。同时,因为我们的工作是基于自然语言解释,我们是得到也是自然语言解释,再把它去利用到无标签的数据上。这样的流程先天的、自然而然的就具有模型的可解释性。




我们再看一下 related work,也就是之前我前文提到的第三篇工作。它其实某种程度上也是先标注的解释,但只做了一个 hard matching。我们和实验中会发现 hard matching 能够匹配的那部分数据集的总数是非常非常小的。所以即使把这些东西送给下游分类集去训练效果也不会太好。

这篇论文中看起来效果很好,但其实所用的这几个数据集非常非常的简单。没有用一些常见的比如说 relation extraction 之类比较难的数据集。我们工作的区别在于也用 semantic parsing,但是我们会走两步。

第一步是 hard matching,第二步是 soft matching。Hard matching 其实跟之前工作非常像,也是 hard matching 得到的,我们就把得到一个标签送给下游任务,我们下游的一个模型,也是让它进行一个纯 supervise 的训练。当然,从这一步过来是没有办法进行 hard matching 的,我们用 soft matching 来进行处理。

对于上图的例子,我们可以给出一个伪标签,什么叫伪标签?因为毕竟它不是匹配到了,所以我们不能够完全确信它就是一个正确的标签。在经过对每一个例子给出一个伪标签的过程之后,我们还会给所打标签一个置信度。

把这部分数据送给下游的模型的目标是学到一个伪标签,前面会加一个权重,代表着置信度。如果我们非常自信说就是一个正确的标签,那他就会多学一点。如果相反不太自信,那我们就少学一点。


再看我们的 semantic parsing,用的 semantic parsing 方式叫 Combinatory Categorial Grammar,我们之后简称 CCG。基于 CCG 语法的语义解析,整体思路也是把一个类似于无结构的自然语言的解释去 parsing 得到一个这样的 logical form,logical form 等价于前文的 labeling function,也就是标注函数变成这样一个形式。


怎么做的呢?我们可以看到我们得到了一个 Explanation,首先把自然语言解释中的每个词语或者词组映射到一个预先确定的位置上。每一个谓语会有一个特定的语法 syntax,得到了每个谓语的 syntax 之后,可以直接利用 CCG 的语法作为输入,输出就是许多的可能的、谓语的组合形式。

用 CCG 的 parsing 可以得到非常多的 logical form,也就是可能的一个谓语组合形式,但是并不是所有的谓语组合形式都是正确的,怎么从中去选出一个正确的呢?我们对每一个谓语组合都会给一段 feature,叫 ϕ(f),它是根据它的 syntax 以及其一些组合的方式来定的 ϕ(f)。我们引入一个可训练的 θ,θ 是一个可训练的一段权重,对于   这样一个解释,我们得到f这样一个 logical form 的概率。

用最大化的、所有执行结果正确的谓语组合的概率之和来训练模型。什么叫执行结果正确?就是这些 logical form 可以看成 labeling function,也就是标注函数,它本身可以直接在原来例子上进行作用。比如说它作用的结果,按道理你既然是解释,作用在原来的例子上肯定要跟原来例子的结果标签是一模一样的。

如果你连这都做不到我们就不会用。我们简单地把所有那些能够在原来的例子上标注得到正确结果的概率全部最大化。在推断的时候,就从这里面选取  argmax,得到的这样一个可标注的函数。


我们主要 contribution 后面的 Neural Execution Tree,我们把它叫做神经元执行树,输入是一个自然语言被解析后得到的谓语组合,以及一个没有办法被直接严格匹配的句子,想输出二者匹配的概率。

因为语义分析已经将自然语言解析成了树的形式,树中的节点都代表着相应的谓语,比如说上图这样一个解释,它已经把它解析成了这样一个树的形式,每个节点都是一个谓语,那这样一个谓语代表什么?代表着不同的执行方式,比如这些执行方式里面有字符串匹配、有距离计算等等,比如说 The words “who died” 出现,其实就有潜在的一个字符串匹配。

occur between 是一个位置的关系,然后 no more than three,是一个数字的比较,放在那棵树里每一个节点都是在做一部分细小的工作,这些节点按树的形式组织起来,就可以得到原先的一个标注函数的形式。

我们总共定义了 4 个模块,分别是:

  1. String matching module,字符串匹配模块;

  2. Soft counting module,也软化技术的模块;

  3. Deterministic function module,决定性的函数模块;

  4. Logic calculation module,逻辑组合的计算模块。

4 个模块会对应到树节点,涵盖了所有可能出现的谓语,不同的模块会作用在不同的谓语上形成不同的效果,输出结果都会在这个节点上,要么输出一个概率,要么输出一个概率的序列。这些概率会沿着这棵树进行组合,一直组合到顶节点,直到输出一个概率,就代表着这样一个句子和我这边的自然语言的解释两者之间的匹配概率。

如前文所述,我们就是要把一个严格匹配的方式变成一个模糊匹配的方式。接下来我就详细的介绍我们的这 4 个模块。


构建四种模块,帮助提升泛化能力


第一个模块 String matching module,也就是字符串匹配模块,核心想法是我们即使要求某一个特定词语出现,我们现在其实不完全要求它严格出现,如果是语义空间上相近的一段词组出现的话,那它其实表达的意思也差不太多。

比如说在上图这个问题里面,query 要求 chief executive of 出现在某个地方,那我在这样一个句子里看不到这样一个词语,但是 Executive director of 出现了,它们两二者其实是在语义空间上是接近的,那我们怎么输出一个高的匹配概率呢?

我们的模型是这么设计的:对 director 这个词我们会编码三样东西,第一个是 director 词本身,第二个是 executive director,第三个是 director of,然后我们把这三样东西送给 child encoder。encoder 我们用的是一个 BiLSTM,上面加了一个 attention and  layer,然后这样就可以得到一段词组的表示,比如说  。

第一个 3 代表它是这句话里的第三个词。0 就代表说这其实是一个 sliding window 了。可以看到我们用这三段东西得到了三段表示。同样,因为这是一个 share 的 encoder,我们对这个 query 也可以把它进行 encoder。得到一个 ,也是一段表示。然后我们分别去计算它们三组之间的一个相似度。

相似度是怎么计算的呢?比如说  和  之间的相似度,我们不仅是直接去算一个 cos 相似度,而是先把它去乘以一个 D,这个 D 是一个可训练的对角矩阵。也就是说它会控制这两个向量每一维的权重,然后再去算一个 cos 相似度。比如说得到了这样三个相似度,

每一位其实都会有这样三个相似度,我们之后再用矩阵方式去乘以一个 1×3 的 B 的向量,这个向量也是需要训练的。也就是说,把这三个相似度给线性组合起来,得到一个最终的相似度,也就是 。这个  就代表着这样一段 query,在我这一句话里的第 3 个位置出现的一个概率。

其实有一些是需要训练的。比如说我们 encoder 就有大量需要训练的东西。包括我们这边的对角矩阵,以及这个 v,都是需要训练的。我们怎么去训练呢?


如上图,我们给出一个 loss ,是总体的一个训练的 loss。它是由两部分组成的,第一部分是 ,第二部分是  ss。是指用  来教这个模型,去学会如何定位一个 query。比如说 query 出现在某个位置,如果 sentence 有一模一样的出现,它就是希望 query 在这边严格找到它。

再比如说我有这样一个句子,abcdefg,我的 query 是 bcd,其实我期望它说出了一个标签,就是 0111000,1 代表 query 在这个地方确实出现过,0 代表着说 query 在这个地方没有出现过。我怎么去得到这样的一个训练的数据呢?其实很容易么,我们有大量的未标注的数据集,根本不需要标签就能把这样一个句子拿出来,在里面随机去找 span。

比如我们可以找长度为 3 的 span,我们随机找到了 bcd,它训练的标签就是 0111000,我们用这个模型去 encoder 得到一段相似度,比如说得到了这样一段相似度。我们的训练的 loss,就是二者的 binary cross entropy,这样他就可以学会如何去准确定位这样一个 query,这就是我们的第一个 loss,教它去准确的定位 query。


但是这样一个 loss 并没有实现我们所追求的泛化能力,仍然没有办法学会怎么去把两个语义相似的东西组合,也给出一个非常高的概率。比如说 chief executive of,它跟 executive director of 不是完全一样的,但它们语义空间上相似,我们怎么去做呢?

我们引入了第二个 loss ,核心思想是说,我们把一些语义相近的东西在表示空间上把看成一个聚类。当然,与它不相似的,不是一类的那些词语解释可以把它给分开。

比如说对于 sentiment analysis 这样的任务,它有两个内容,一个是 positive 类,一个是 negative 类。Positive 类比如说有的自然语言解释说,good 这个词出现在某个位置,有的说 great,有的说 cheap。对于这样一个任务,这三个词就其实是在同一个空间,就是一个正向空间。

有可能对 negative 这样一个类,它有 bad,有 awful。我们这边就是想把这样三个词语的空间聚到一起,这两个聚到一起之间会有一个 margin,其实就是一个聚类的 loss。我们这边其实可以简单看成就是一个聚类的 loss,这是对于 sentiment analysis 来说的。

如果我们对于 relation extraction 这样的任务,比如说某一个数据有 42 个类,每一个类之间其实都可以标注到很多可以用的东西。再比如说因果关系的这样一个类。它可以把 is caused by 和 resulted from 这两个东西在语义空间上把它拉近。

比如说对于 city-of-death 这样一个类,可以把 was killed on 和 was murdered in 给拉近距离。核心思想就是我们要从已经得到那些自然语言解释中,找到一些关键词,完全来自于自然语言解释。所以我们这边说的两个 loss,一个 ,一个 。我们就可以随机从未标注的数据中随便找词向量让  去训练,只要基于那些已经得到的自然语言的解释就可以了。


第二个模块,软化的一个技术模块,作用就是用来软化一些技术的限制,这些限制是被自然语言解释给限定了。比如说我们看到有这样一个限定。The word ‘glad’ precedes OBJECT by no more than 2 words。之前,如果没有进行转化,它比如说小于等于两个词,它就输出 1 的概率。大于两个词,它输出 0 的概率,就是非 1 则 0。

我们现在把它转化成什么样?我们给了一个新的函数,这其实可以看成反向的一个接入。也就是说,2 现在是第 4 个词,我依然可以给一个概率,当然这个概率不可能还是 1。但比如超过 8 个字,就可能太离谱,因此不给概率了,而是软化成上图的形式。这样的函数到底用什么?严格来讲完全看实验结果。你可以找自己觉得还不错的,只要是递减的函数都可以。


第三个模块——Deterministic function module,是决定性的函数模块,用来作用在不能被软化的词语上,比如说它有限定,the subject is a person,对于这样一个限定,主语要么就是 person,要么不是 person,只有 1 和 0 这两种非对即错的这样一种选择。

或者说这个词出现在 A 和 B 中间,它没有办法来出现在其他地方,要么在中间,要么不在中间,也是 1 和 0。对于所有不能被软化的操作,用这个模块来替代。这样,这个节点它输出概率要么是 1,要么是 0。


既然每一个节点都会输出概率,概率和概率怎么组合?毕竟要把每个节点的概率组合起来,才从顶节点输出。这里会采用第 4 个模块:Logic calculation module,它的作用就是把节点和节点之间的概率给组合起来。

比如有节点 1,概率是 ,节点 2 概率是 。用的是一个 Probabilistic soft logic,一个概率软逻辑的结构。比如  和  它们是一个与的关系,就用 max( +-1,0) 来表示,如果是或关系,就是 min( +,1)。如果是否定关系法就是 1-p,这完全就是 probabilistic soft logic。

当然,它不仅可以对两个数值的概率进行处理,还可以对两段概率序列进行处理。比如第一段概率,第一个节点输出一个概率序列,第二个节点输出一个概率,它可以把它拼成一个新的概率序列,然后每一个节点做的事情就是一个 element wise 的一个 soft logic。

给出一个 Gif 来比较生动地看一下整个执行过程。我们会看到,对于上图这样一个自然语言的解释,把它用 semantic parsing 变成了 logical form 之后,需要去匹配所有潜在的一些句子。

匹配第一个句子的时候,subject was murdered on object。把这两样东西——一个是 logical form,一个是 sentence——送到 Neural Execution Tree的模块中,这个模块会输出一个匹配概率,它是怎么做的?

首先,既然得到了 logic form,就已经看到了这个树,先从树的叶子节点入手,因为我之前说了每个叶子节点,都对应着某一个 predicate,也就对应着某一个 module。这些 module 输出的都是概率,或者做概率的组合。每一个节点其实都可以先对句子作用,然后得到一段概率。

比如说这 4 个节点都得到了一段概率事件,它们会进行组合,往上传。比如说叶子结点再往上走,得到另一个节点。这个节点它的作用正好是把这两方概率给组合起来我就得到了一个新的概率。

之后再往上走,又走到一个节点,还会继续把这两段概率给组合起来,得到一个新的概率。直到到了顶节点。这个顶节点输出的这一段概率就是我的自然语言解释和句子的一个匹配概率。大概整体的框架就是这样。


那怎么去训练这样一个模型?比如说对于得到一个 label data 的  和 unlabeled data 的 , label 的能够被直接 hard matching,所有能被直接匹配的,称之为 label data,那些不能被匹配的,需要用 soft matching 来匹配的,称之为 unlabel data。我们目标是输出一个分类器。每次都从 label data 里面选一小部分来,也会从 unlabel 中选一小部分。

对于这些 label data,用纯 supervise 方式去训练。而对于 unlabel data,只能用一些 semi-supervised 方式去训练。首先,比如说有 50 个自然语言解释,每个解释对当前句子都会有匹配概率,取一个 argmax,找到最匹配的概率、最匹配的自然语言的解释,并且当前这个句子的标签就是这个解释所对应的标签,然后我就以它为目标进行训练。

当然,还有置信度的问题,如果匹配概率很高,那我可以相信它很可能接近 label data 了,如果匹配概率很低的话,我可能不太容易去相信它。

那如何实现置信度?需要进行规范化 normalization。 就是所谓的匹配概率, 是一个超参数,用这样的方式就可以在一 个batch 之内做一个 normalization,置信度是 0~1,而且所有的例子加起来是 1,总体的训练 loss 就是  以及 ,这个  即 string matching 的 loss,这样可以勉强称它是一个 joint、 training 的 algorithm。

我们做了两个实验,第一个实验是关系抽取,在 TACRED 和 SemEval 上进行。第二个实验是 sentiment analysis,也就是情感分析,在 SemEval2014 进行 task 4 的实验,其中有两个数据集,第一个是 Restaurant,第二个是 Laptop,是我们收集到数据集,和之前一样,也是在 Amazon mechanical turk 上收集的。

上图右边是整个数据集的数量,左边是利用这些解释直接进行 hard matching 得到的数量,可以看到其实 hard matching 得到的数量是非常少的,只占整个数据集非常少的一部分,有大量的未标注的数据可为我们所利用。


再简单看一个例子。比如对于 TACRED 这样一个数据集来说,得到的解释大概长这样,The term “then known as” occurs between  SUBJ-PERSON and OBJ-PERSON and there are no more than six words between SUBJ-PERSON and OBJ-PERSON。


同样,对于 SemEval 数据集,我们也可以得到很多的解释,比如说 the phrase is caused by the ”occurs between SUBJ and OBJ follows SUBJ。


上文提到,得到一个标注的结果,然后把这些标注的东西同时送给下游的一个分类器,对于不同任务来说,完全可以换一个分类器,所以可以看到这是非常阶段性的工作,先 semantic  parsing,parsing 完之后再去做标注,标注完之后把标注的结果送给一个下游的模型。

对于 relation extraction 我们用的模型是 BiLSTM+attention,即上图最下面的词语,然后用 BiLSTM 去 encode,得到 Attention layer,代表每一段它的权重是多少,最后把它带权的组合一下,再送给一个 SoftMax。


另外,对于 sentiment analysis 任务来说,我们用的是 ATAE 的 LSTM,这篇是 2016 年的黄民烈老师做的工作,发表在 EMNLP,是对于 aspect term level 的  sentiment analysis 任务,每一个句子都有一个所属 aspect,把这一段 embedding 和这样一个 hidden layer 去 contact 起来,然后再去做一个attention,得到一段带权的表示和原来 LSTM 最后一个词的表示同时组合到一起,然后拿到这段 embedding 再去分类。


效果如上表所示。LF 代表只用 logical form,即 labeling function 在整个数据集上作用得到的效果,可以看到 recall 非常低,代表自然语言解释的泛化能力非常差,它只能匹配到非常少的一些句子。这些模型是在 level data 上,是直接 hard matching 到的 data 上训练得到的结果,效果并不是很好。

其实我们还有一系列的 baseline,属于 supervise,我先拿一个模型在 label data 上训练,对于 unlabeled data,可以拿这个模型去打标签,打出来一些 label,再去训练,这样做成 sentiment analysis 的东西。可以看到我们的模型相对于所有这些 baseline 都有非常好的效果。


这是 relation extraction,对于 sentiment analysis 来说,可以看到我们的效果也是非常好的,相对 baseline 都有比较高的提升。


来看几个有趣的 Ablation studies,这个是我们的一个模型的效果,我们想证明,那些提升泛化能力的模块确实是有用的,如果把技术模块的软化去掉,你会发现效果是有下降的。

如果把 string matching 给去掉,原来不是说要做一个模糊匹配,现在就做直接匹配、严格匹配,找词语到底有没有出现,这样它的效果下降是非常明显的,也就是说,对于文本的任务来说,string matching 其实是最重要的。当然 string matching 它其实有两个 loss,一个是 ,一个是 ,可以发现如果任意去掉一个,它的效果都不会好。


其实我们这个工作还在 QA 上做了实验,因为你会发现之前我们做的两个实验,无论是 relation extraction 还是 sentiment analysis,都是偏文本分类的任务,与 QA 任务有非常大的区别。这里做了一个 additional experiments,当然我们并没有声明也在 QA 上做了完整实验,因为它与之前的文本分类还有挺大区别。但从实验结果上来看,效果也还不错。


上图是其他的一些 Ablation studies,不同数量的一个自然语言的解释,它的效果会不会有变化,如果随机取 100 个,或者说最多用了 230 个自然语言解释它的效果,上图蓝线是用我们的模型达到的效果,剩下的线是一些 baseline 的效果。可以看到,不管是什么数量的自然语言的解释,我们模型的效果永远是最好的。


对 sentiment analysis 数据集也是这样的结果。1000 条虚线代表是 1000 个传统的标签,能够达到这样的效果。你会看到我们达到 2500 个标签,差不多有 170 个左右的 explanation。这个标注效率已经算挺高的了。   


还有一些 Ablation studies,我们想看一下 unlabel data 的效果到底怎么样?如果 unlabel data 原来有 100%,现在砍掉 60%,它的效果会有一定下降。

上图蓝线趋势不太明显,是因为整个标签的跨度实在太大了。如果把红线给去掉,单看这条线,它的跨度就会稍微好看一点。当然我们非常关注标注效率问题,  在不同时间的不同标注时间下,红色实线代表是可以标注的传统标签的数量,蓝色虚线代表是可以标注的自然语言解释的数量。

蓝色实线代表利用这些自然语言解释可以达到的效果。红色虚线代表是只利用标签的那些 baseline 最好能够达到的效果。不管在任何时间下,我们的模型相对于这些 baseline,效果都是最好的,效果和标注效率有非常高的提升。


还有一些 Ablation studies,比如说,上图是一个 string matching 的,颜色越深,代表匹配度越高。比如说对上图这样一个句子,要去匹配 chief executive of,可以看到颜色最深的确实就是在这个词周围,说明确实能够找到它的匹配。


上文提到,我们下游的模型是可以直接替换的。其实现在 NLP 的老套路,就是用 RNN 做实验,再把 Bert based 做实验,比如现在最好的是 ALBERT 。我们拿 Bert 做了一下实验,效果也有提升。当然提升没有之前那么明显,因为 Bert 其实已经对这样的任务来说,都已经非常简单了,有一点提升也是很难的了。

之前讲过,我们主要做的是一个文本分类的任务,其实在 QA 上是大有可为的。





比如说对于上图 QA 的任务来说,Question: How is packet switching characterized 和 How is the evacuation tube sealed是非常像的,包括在 Context 里面也是非常像的。总结起来差不多是这样:How is NP VP by…

最后,如果我们能够标注上面这样的一个自然语言的解释,也可以很好对它进行匹配,这也是很有潜力的。我们这项工作之后还有几个可能的方向,一方面是 semantic parser 还有提升的空间,另外之后希望可以做成 cross domain 的 semantic parser。

关于数据实战派

数据实战派希望用真实数据和行业实战案例,帮助读者提升业务能力,共建有趣的大数据社区。

更多阅读

#投 稿 通 道#

 让你的论文被更多人看到 

如何才能让更多的优质内容以更短路径到达读者群体,缩短读者寻找优质内容的成本呢?答案就是:你不认识的人。

总有一些你不认识的人,知道你想知道的东西。PaperWeekly 或许可以成为一座桥梁,促使不同背景、不同方向的学者和学术灵感相互碰撞,迸发出更多的可能性。 

PaperWeekly 鼓励高校实验室或个人,在我们的平台上分享各类优质内容,可以是最新论文解读,也可以是学习心得技术干货。我们的目的只有一个,让知识真正流动起来。

???? 来稿标准:

• 稿件确系个人原创作品,来稿需注明作者个人信息(姓名+学校/工作单位+学历/职位+研究方向) 

• 如果文章并非首发,请在投稿时提醒并附上所有已发布链接 

• PaperWeekly 默认每篇文章都是首发,均会添加“原创”标志

???? 投稿邮箱:

• 投稿邮箱:hr@paperweekly.site 

• 所有文章配图,请单独在附件中发送 

• 请留下即时联系方式(微信或手机),以便我们在编辑发布时和作者沟通

????

现在,在「知乎」也能找到我们了

进入知乎首页搜索「PaperWeekly」

点击「关注」订阅我们的专栏吧

关于PaperWeekly

PaperWeekly 是一个推荐、解读、讨论、报道人工智能前沿论文成果的学术平台。如果你研究或从事 AI 领域,欢迎在公众号后台点击「交流群」,小助手将把你带入 PaperWeekly 的交流群里。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!