鸽了很久的NLP入门系列终于在我的努力下又更新了。
上次聊了分类任务的模型与技巧,今天我们就来聊聊句间关系任务。句间关系的输入是一对文本,输出是文本间的关系。常用的判别有语义相似度、语义关系推理(蕴含/中立/矛盾)、问答对等,拿GLUE榜单来说,其中有6个(QQP/MNLI/QNLI/STS/RTE/MRPC)都是句间关系任务。这个任务的应用场景也很广泛,比如搜索推荐的语义相关性、智能问答中的问题-问题、问题-答案匹配、知识图谱中的实体链接、关系识别等,是成为NLPer必须卷的一个方向。
在深度学习中,文本匹配模型可以分为两种结构:双塔式和交互式。
双塔式模型也称孪生网络、Representation-based,就是用一个编码器分别给两个文本编码出句向量,然后把两个向量融合过一个浅层的分类器;交互是也称Interaction-based,就是把两个文本一起输入进编码器,在编码的过程中让它们相互交换信息,再得到最终结果。如下图:
两种框架比较的话,交互式通常准确率会高一些,毕竟编码器能使用的信息更多了,而双塔式的速度会快很多,比如线上来一个query,库里有一百万个候选,等交互式算完了用户都走了,但双塔式的候选可以提前计算好,只用给query编码后去和候选向量进行浅层计算就好了。工程落地的话,通常会用双塔式来做召回,把一百万个候选缩减为10个,再对这10个做更精细的计算。
所以说这两种方式都是实际应用中必不可缺的,两个方向也都有着不少的模型:
下面我们就先讲讲双塔式模型的SOTA发展。这里面通常有三个点可以优化:encoder、merged_vec、classifier,大部分研究都在专注提升encoder的能力。我个人主要将双塔的发展分为词袋、有监督、预训练+迁移三个阶段。
词袋句向量
最简单的就是直接从词向量计算句向量。首先可以用mean、max池化,相比字面n-gram重合度肯定是有提升的。但当句子中的噪声多起来之后,如果两个句子有大量重合的无意义词汇,分数也会很高,这时候就可以考虑加权求和,比如TF-IDF。
ICLR2017论文SIF提出了名为smooth inverse frequency的方法,先由词向量加权平均得到句向量,再对多个句子组成的句向量矩阵进行PCA,让每个句向量减去第一主成分,去掉“公共”的部分,保留更多句子本身的特征。该方法在相似度任务上有10%-30%的提升,甚至超过了一些RNN模型,十分适合对速度要求高、doc相似度计算的场景。
之前提到的相似度任务都适用cosine相似度衡量的,也有学者研究了其他metric。2016年的WMD提出了Word Mover‘s Distance这一概念,用句子A走到句子B的最短距离来衡量两者的相似程度。表示在下图中就是非停用词的向量转移总距离:
上面介绍的两篇文章使用的都是word2vec向量,但实际操作中我推荐使用fasttext(就是加上ngram,但仍用word2vec结构训练),一方面ngram可以增加信息,另一方面也避免了OOV。
千万不要小看词向量,用好了真的是很强的baseline。另外现在很多线上场景因为对速度要求高,或者是toB的业务甲方不愿意买GPU,有不少落地都停留在这个阶段。
有监督句向量
词向量虽然可以经过处理变成句向量,但词袋式的融合也会丢失掉顺序信息,同时在训练时其目标还是word-level的,想要获得「真正的句向量」,还是需要寻找sentence-level的目标函数。
微软在2013年提出的CIKM论文DSSM是相当知名的多塔模型,它对文本进行word hash(也就是表示成ngram,减少词表数),再将ngram转成向量再平均得到句向量,经过三层MLP得到128维的编码,用cosine相似度作为每个Q-D对的分数,经过sofamax归一化后得到P(D|Q),最终目标为最大化正样本被点击的概率。
但BOW式的词向量平均会损失上下文信息,所以之后也有学者提出了CNN-DSSM、LSTM-DSSM,基本上结构都差不多。
Siam-CNN
题目:Applying Deep Learning to Answer Selection: A Study and An Open Task
论文:https://arxiv.org/pdf/1508.01585.pdf
在2015年IBM提出的Siam-CNN架构中,作者尝试了多种孪生架构,使用CNN作为基础编码器,pairwise loss作为损失函数,最后实验发现第二种是最好的:
说实话这个结果有点迷,Query和Answer的表达还是略有不同的,经验上看我觉得第三个结构更靠谱些。不过作者只在一种数据集上进行了尝试,或许换个数据集结果会有变化。
Siam-LSTM
题目:Siamese Recurrent Architectures for Learning Sentence Similarity
论文:http://www.mit.edu/~jonasm/info/MuellerThyagarajan_AAAI16.pdf
2016年的Siam-LSTM在结构上比较简单,就是直接用共享权重的LSTM编码,取最后一步的输出作为表示。有个改进点是作者使用了Manhattan距离计算损失:
后续还有一些模型改成双向、char-level的,这里就不过多赘述了。
Multi-View
题目:Multi-view Response Selection for Human-Computer Conversation
论文:https://www.aclweb.org/anthology/D16-1036.pdf
百度的EMNLP2016论文针对多轮对话问题,提出了Multi-view的Q-A匹配方式,输入的query是历史对话的拼接,分别编码了word sequence view和utterance sequence view两种表示。词级别的计算和Siam-LSTM差不多,都是用RNN的最后一步输出做Q-A匹配,而句子级别的会对RNN每步输出做max pooling得到句子表示,然后再将句子表示输入到GRU中,取最后一步作为带上下文的表示与回答匹配,如下图:
融合了两个level的匹配后比普通方法的R@1要好上4-6个点,提升很明显。
预训练+迁移
有监督、领域内的语料总是有限的,目前很多任务都开始转向预训练+迁移的范式。
Skip-Thought
题目:Skip-Thought Vectors
论文:https://arxiv.org/pdf/1506.06726.pdf
代码:https://github.com/ryankiros/skip-thoughts
多伦多大学的NIPS2015论文Skip-Thought提出了一种无监督句向量训练方法,参考wrod2vec,一句话与它的上下文也是存在关联的,因此我们可以用一个句子的编码去预测它的上下句:
Skip-Thought用GRU作为编码器,条件GRU作为解码器,预测时候只用编码器就可以得到句子表示。
但这种方法训出的decoder不用比较浪费,后续也有学者用同样的思想改成了判别任务,比如Quick-Thought对句子分别编码,过分类器选择上下文,又或者BERT中的NSP,或者ALBERT的SOP。
FastSent
题目:Learning Distributed Representations of Sentences from Unlabelled Data
论文:https://www.aclweb.org/anthology/N16-1162.pdf
代码:https://github.com/fh295/SentenceRepresentation/tree/master/FastSent
2016年的FastSent主要对Skip-Thought的速度进行了改进,其实就是用词袋模型去替换RNN编码,再用中间句子的表示去预测上下文的词。同时也提出了一个FastSent+AE变体,预测目标也加上了自身的词。
最终效果在无监督任务上好于Skip-Thought,但有监督任务上还是略逊色。
InferSent
题目:Supervised Learning of Universal Sentence Representations from Natural Language Inference Data
论文:https://www.aclweb.org/anthology/D17-1070.pdf
代码:https://github.com/facebookresearch/InferSent
前几篇可迁移的encoder都是无监督的,因为学者们一直没有发现更通用的数据,直到InferSent。
EMNLP2017中Facebook提出了InferSent,文中使用NLI数据集来预训练双塔结构,超越了之前众多无监督方法。该文章用了很简单的双塔结构,但在计算loss时先对两个向量用了多种方式融合,再过分类器。同时也提出了多个基于RNN、CNN的编码器,最后实验发现BiLSTM+Max效果最好,在评估的10个任务中有9个达到了SOTA。
InferSent提出的结构到现在还用很多同学在用,包括后文的Sentence-BERT(19年的SOTA)也只是换了个编码器而已。同时用NLI来做预训练这个点也很重要,优质语料对模型提示有很大帮助。
后续也有模型进行了小改进,比如2017年的SSE,使用3层堆叠BiLSTM+Shortcut,效果比InferSent好一些。
GenSen
题目:Learning General Purpose Distributed Sentence Representations via Large Scale Multi-task Learning
论文:https://arxiv.org/abs/1804.00079
代码:https://github.com/Maluuba/gensen
同样是提升可迁移性,微软在ICLR2018上提出了GenSen,使用GRU编码,将encoder下游接上4种不同的任务(预测上下文、翻译、NLI、句法分析),但只在6/10个任务上超越了之前的模型,个别情况下增加新的任务还会使效果下降。
这种多任务的思想后续也被用在其他模型上,比如MT-DNN(狗头。
USE
题目:Universal Sentence Encoder, Learning Semantic Textual Similarity from Conversations
论文:https://arxiv.org/pdf/1803.11175v1.pdf, https://arxiv.org/pdf/1804.07754.pdf
谷歌在ACL2018提出了USE模型,这也是引用量很高的一篇文章(但写的不是很清楚,推荐读第二篇),主要改进如下:
提出了用Transformer和平均池化+MLP作为encoder,分别适用不同的场景
爬取了大量reddit的问答数据,用于无监督Q-A训练,因为query和answer的表示空间不一样,结构上给answer多加一层DNN。并且在问答任务上使用batch negative策略,也就是除了对应的正确答案外batch内剩下的样本都作为负例,用softmax计算P(A|Q)的概率,跟现在对比学习的loss一样。
多任务,在无监督训练Q-A的同时也用SNLI进行有监督训练
这样训练出的模型比InferSent高3-5个点,效果很好。现在这个模型也在一直更新,可以在TFhub上使用,不仅速度快,效果也没比BERT系差太多。
Sentence-BERT
题目:Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks
论文:https://arxiv.org/pdf/1908.10084
代码:https://github.com/UKPLab/sentence-transformers
EMNLP2019的Sentence-BERT是目前最常用的BERT式双塔模型,一是效果真的好,二是作者的开源工具做的很方便,用的人越来越多。结果其实就是把InferSent改成BERT编码,训练语料也不变,做离线任务可以直接用起来。
BERT-flow
题目:On the Sentence Embeddings from Pre-trained Language Models
论文:https://arxiv.org/pdf/2011.05864.pdf
代码:https://github.com/bohanli/BERT-flow
字节在EMNLP2020提出了BERT-flow,主要是基于Sentence-BERT做改动,因为之前的预训练+迁移都是使用有监督数据,而作者基于对原生BERT表示的分析发现,那些表示在空间的分布很不均匀,于是使用flow-based生成模型将它们映射到高斯分布的均匀空间,比之前的Sentence-BERT提升了4个点之多。
但这个模型的缺点是又加了一层机制,在预测时候会降低速度,同时在知乎上看到个别同学在自己任务上的试用反馈也不太好。不过我倒是验证了SentEval上有监督的效果(论文只给了无监督的),效果跟Sentence-BERT差不多。
Cross-Thought
题目:Cross-Thought for Sentence Encoder Pre-training
论文:https://arxiv.org/abs/2010.03652
代码:https://github.com/shuohangwang/Cross-Thought
微软在EMNLP2020提出了Cross-Thought,先用transformer对每个句子编码,再取多个CLS(红点部分)作为句子表示再进行attention,得到一个整体的上下文表示,再回头去预测每个句子被mask的token。相比起NSP来说,该任务的解空间更丰富,相比单纯的BERT表示提升明显,在QA任务上更是提了几十个点。
对比学习
对比学习是20年图像领域火热的表示预训练方法,在训练时会给输入A生成一个数据增强版本B,经过编码器对A和B编码后,如果两个表示还是最接近的(batch内分类),就说明这个编码器抓住了用于区分A与其他样本的本质特征。对比学习目前在NLP领域还没开始大放异彩,从20年下半年的一些新论文来看,在预训练过程、精调中加入对比损失都会轻微提升模型效果并增强鲁棒性、小样本场景的表现。相信用对比做出的优秀文本表示不久就会出现。
!!!我是朋克风分割线!!!
上文讲了众多双塔模型,其主要的重点都在编码器的优化,对速度要求高的召回场景可以用BOW+MLP、CNN,精度要求高的排序场景可以用LSTM、Transformer。同时两个向量的融合方法以及loss也都可以优化,比如做一些轻微的交互、像Deformer一样前面双塔接后面的多层交互,或者根据需要选择pointwise、pairwise(排序场景)损失。
但真要想做句间关系SOTA的话,比如刷榜,光靠双塔模型还是不行的,它有两个问题比较大:
位置信息。如果用BOW的话“我很不开心”和“我不很开心”两句的意思就变成一样了,虽然用RNN、BERT引入位置编码可以减缓一些,但不去让两个句子相互比较的话对于最后的分类层还是很难的
细粒度语义。比如“我开心”和“我不开心”这两句话只有一个字的区别,但BOW模型很可能给出较高的相似度,交互式模型则可以稍有缓解
交互式匹配
比起双塔只能在encoder上下功夫,交互式模型的套路就多多了,其核心思想是将两个句子逐个词比较。比如判断“进击的巨人”和“进击的矮子”语义是否相同时,前三个字在两句话中都能找到,而第二句里没找到跟“巨人”接近的,那分数就会被降低一些。因此得让两个句子有interaction,一般用attention解决,因为没那么在意速度了,在交互前后都可以加encoder,再让向量拼接、做差、点积。。。不说了,请开始让它们表演。
DecAtt
题目:A Decomposable Attention Model for Natural Language Inference
论文:https://arxiv.org/pdf/1606.01933.pdf
Google在EMNLP2016提出了轻量级的交互模型DecAtt,作者的出发点是让句子中的各个元素相互对比,找出词级别的同义和反义。分为三步计算:
Attend:将两个句子中每对次 相互attention,加权后得到对齐的
Compare:将 分别拼接,过一层FFN得到
Aggregate:分别将第二步得到的表示求和得到 ,拼接起来进行分类
比较难懂的主要是第二步,作者的解释是经过第一步attend后可以将问题拆解为子问题,再通过每个词向量的compare解决。
这个模型的缺点是最后一步求句向量时用了求和操作,如果序列过长的话数值会较大,造成梯度大,需要裁剪。但计算还是很轻量的,从结果来看跟LSTM差不多。
MatchPyramid
题目:Text Matching as Image Recognition
论文:https://arxiv.org/pdf/1602.06359.pdf
代码:https://github.com/pl8787/MatchPyramid-TensorFlow
计算所在2016AAAI发表的MatchPyramid主要受图像处理的启发,先对词进行交互得到Matching矩阵,然后通过多层2D卷积抽取更高维度的特征,最后得到表征用MLP分类。作者凭借此模型在2017年的Quora Question Pairs比赛上拿到了全球第四。
相比上文的DecAtt,MatchPyramid通过CNN捕获到了ngram特征。从结果看比DSSM等模型高出了3、5个点。
PWIM
题目:Pairwise Word Interaction Modeling with Deep Neural Networks for Semantic Similarity Measurement
论文:https://www.aclweb.org/anthology/N16-1108.pdf
代码:https://github.com/lanwuwei/Subword-PWIM
ACL2016的PWIM模型主打细粒度交互,模型非常的深,分为以下四个计算步骤:
Context Modeling:用BiLSTM对输入编码
Pairwise Word Interaction Modeling:作者定义了一个对比向量的函数coU(包含cosine、点积、欧式距离),对两句话的词进行两两比较,总共计算了前向向量、反向向量、前后向拼接、前后向相加四种表示的coU,作者将输出称为simCube
Similarity Focus Layer:提出了一个算法,根据simCube的分数排序,计算出一个mask矩阵,其中重要元素的权重是1,非重要为0.1。作者认为如果句子A中的某个词在句子B中也找到了,那这就是一个衡量两者相似度的重要指标。最终mask和simCube相乘得到focusCube
Deep ConvNet:作者把前面产出的三维矩阵看作图像,用19层卷积神经网络的到最后的表征,再过softmax分类
这篇文章真的是花式计算,虽然从结果来看超过了双层BiLSTM 2、3个点,但这计算复杂度让人难以承受。在后文也会被ESIM超越,所以就别用了,当做多学习一些思想吧~
ESIM
题目:Enhanced LSTM for Natural Language Inference
论文:https://www.aclweb.org/anthology/P17-1152.pdf
代码:https://github.com/coetaur0/ESIM
ACL2017中的ESIM也是效果很好的模型,基于DecAtt改动,在两句话交互融合后又加了一层BiLSTM,将效果提升了1-2个点。同时也尝试使用句法树进一步提升效果。它的计算过程有一下四步:
用BiLSTM对embedding编码,得到表示
将两句话的BiLSTM输出进行attention,得到融合的句子表示
将 拼接作为新表示,用BiLSTM进行推理
池化后过进行最终分类
DIIN
题目:Natural Language Inference over Interaction Space
论文:https://arxiv.org/pdf/1709.04348.pdf
代码:https://github.com/YerevaNN/DIIN-in-Keras
ICLR2018的DIIN看起来像PWIM一样花式,比ESIM高出5、6个点。主要有以下改动:
在embedding层除了使用词向量,还使用了字向量、词性特征和英文词根的完全匹配特征
使用Self-Attention编码
HCAN
题目:Bridging the Gap Between Relevance Matching and Semantic Matching for Short Text Similarity Modeling
论文:https://cs.uwaterloo.ca/~jimmylin/publications/Rao_etal_EMNLP2019.pdf
代码:https://github.com/jinfengr/hcan
HCAN是Facebook在EMNLP2019提出的模型,虽然比上文的ESIM、PWIM等模型高上4+个点,但还是被BERT甩了很远。不过这个模型的核心也不只是做语义匹配,而是同时做检索相关性(Relevance Matching),也就是搜索中query-doc的匹配。
模型计算如下:
Encoding层作者提出了三种方法,堆叠的CNN作为Deep Encoder,不同尺寸卷积核作为Wide Encoder,BiLSTM作为Contextual Encoder编码更长距离的上下文
先把两句话交互得到attention score矩阵,之后对于query中每个词,求得doc中最相似的词的分数,作为向量Max(S),按照同样的方法求出Mean(S),长度都为|Q|,再分别乘上query中每个词的tfidf统计,得到相关性匹配向量
用加性attention对query和doc进行交互,得到新的表示,再花式拼接过BiLSTM,得到语义匹配向量
将 拼接起来过MLP,最后分类
通过实验结果来看,Deep Encoder的表现是最好的,在7/8个评估上都超过另外两个。
RE2
题目:Simple and Effective Text Matching with Richer Alignment Features
论文:https://www.aclweb.org/anthology/P19-1465.pdf
代码:https://github.com/hitvoice/RE2
RE2是阿里在ACL2019提出的模型,也是很不错的一个工作,优点是模型轻量且效果好。上文虽然很多模型都用到了交互,但只交互1、2次,而RE2则像transformer一样把两句话交互了多次。
计算逻辑是(图中只展示了双塔的一半):
Encoding:对输入进行embedding得到,拼接上之前的输出,用CNN编码
Alignment:把encoder的输入输出拼接起来,两句话进行attention
Fusion:将encoder的输入输出与attention的结果一起融合,得到的表示进入下一循环或max pooling输出句子表示
将两个句子表示各种拼接后进行分类
这个模型除了多次交互之外,还有个点是一直都把最初的embedding拼接上,从消融实验看可以提升1-6个点。
!!!我是朋克风分割线!!!
一口气讲了7个交互式匹配模型,感觉自己都不会爱了。其实大部分都是为了解之前的思想,因为现在无脑用BERT就够了。
同时老司机们也很清楚,模型只是工具,数据才是天花板,数据质量不好/数量不够,模型再花哨也没用。所以这里分享两个数据洗刷刷经验:
负例的构造。都说句间关系任务负例的构造是很重要的,确实如此。但构造前一定要把正、负界定清楚,明确这个任务的粒度有多细。比如“我很不开心”和“我不太开心”都是不开心,但程度不一样,在自己的任务中到底是算正例还是负例呢?这个界定的越清楚、标注人员培训越到位,数据噪声也就越少。之后才是尽量构造有难度的负例,比如用BOW召回一些再人工标注,让样本们越来越逼近分类边界
数据增强。交互式模型虽然准确,但他们有个缺点是容易过拟合,因为对“交互”看得太重了。比如一对正例里只有一两个字一样,模型可能就会认为这两个字很重要,有些overlap超低的文本对也会给出高得分。这时候就要对正例进行清洗,看看特殊情况是否存在,再尝试用增删改的方法加一些负例,避免过拟合这种极端正例。另外BERT这种交互式模型是不对称的,如果做paraphrase任务也可以镜面构造些新正负例。
总结
可能是文本匹配方面看得比较多吧,终于把我收藏的模型都扒拉出来了,直接像文本分类一样再给大家提供一个选型方案吧:
原文标题:【代码&技巧】21个经典深度学习句间关系模型
文章出处:【微信公众号:深度学习自然语言处理】欢迎添加关注!文章转载请注明出处。
责任编辑:haq
全部0条评论
快来发表一下你的评论吧 !