机器学习之旅

文本相似性的总结

2020-09-07  本文已影响0人  slade_sal

文本相似性的应用场景会有很多,在工业界我粗略遇到过:

说到文本相似性可以有很多种划分的方式,从文章的长短可以分别处理,从计算的方式可以分为深度学习和机器学习方式,从实现目的上可以分为去重和匹配...

以下面两个例子举例:

0 伟大祖国让我们过的非常幸福
1 伟大的祖国让我们过的非常幸福
2 伟大的祖国是我们过的非常幸福原因
3 中国人民现在的日子真的很幸福

Hash方法

我们可以说0和1是相似的,因为它们之间只差了一个“的”,通常通过SimiHash或者MiniHash我们就可以解决这类问题

分词、hash、加权、合并、降维,这个是它们在常规流程。总结一下就是,根据各种权重赋值方式(比如tfidf)给出每个词的权重,通过hash的方式给每个词一个01表征方式,通过权重和表征结果得到加权结果,再根据加权结果map到0或者1,得到一串签名结果Fingerprints,再通过分段比对或者其他什么方式进行两句话的比对,看下差异是否在可接受的范围内,得到两句话是否一致。

这种方式通常用作去重,比如如果我们有一份非常庞大的样本集合,要去做去重,大家通常的做法就是在写hive sql或者spark sql的时候distinct一下,在做后续的自然语言处理任务,通过这种方式可以去除掉一些真·近似的文本,加快速度且干掉一些异常点非常有效,最重要的是超级快。

词袋方法

1和2由于相差的字数比较多,可能不是以一种hash方式去做能识别多出的。但是细心的朋友回发现,它们之间重合率非常高,通过分词后的比对也是可以识别的。

这边点名一下常见的倒排索引、杰卡德相似、onehot的cosine、切词后的词交集个数,句法依存,编辑距离等等,都可以实现,而且其中不乏一些非常高效的解决方案,相似框架faiss,l2正则化后稀疏矩阵点积,tire树做文本内容的存储以匹配词交叉的情况等等。

这种方式通常是应用在业务场景中了,它们通常不会作为一个自然语言理解必备的preprocessing工作去做,而是解决一系列要求高时效或者要求高相似的文本判断的场景下。

匹配方法

刚才为说到要求高相似,很多朋友可能不理解什么叫做高相似,对比1和2,2和3就会发现,大家对相似的标准其实是不一致的,在某些场景,比如热点榜单生成,1,2,3就是一件事情,大家都不喜欢在自己的热榜排序结果中重复出现1,2,3中的任意2条;而在信息流推荐中,2,3或者,1,3就是两件不同的事情,可能它们的文章有不同的侧重点。

如果需要识别出1,2,3是同一件事情,可能词袋方法也不适用,因为它们没啥重复的词,词袋就失效了。

以上6种方式是工业界最常用的6种思路,不乏会有一些奇思妙想没有列出来,但是各大厂主力的方法一定包含在其上。

LDA

LDA是一个nlp工程师必会的技能,这边不展开讲,这边主要讲它能带来什么。LDA这个方法对一段文本的表征,它优秀在于考虑了当前文本和全局之间的关系,我在做文本匹配的时候,我不简简单单的立足在这个两篇文本是否一致,而是把它放在了全部数据集中,拼的是文本1、文本2在全量数据集中到底是个什么地位,在全部的文档库中这两个文本讲的到底是不是一类事情。

LDA提供的是两篇文本的主题的分布,得到这个量化后的分布后如何去比呢?cosine?其实大家在高代学习过程中一定听过相对熵这个逻辑,从这个角度上来看,是不是text1对text2的相对熵和text2对text1的相对熵的加权平均很合适,因为它们都是衡量的两个分布上的一致性,而主题恰巧是text本文的分布。对,这个方法就是JS散度。另外一种方式是Hellinger Distance,它的中文名叫概率分布之间的距离--海林格距离,话不多说,同理易得。

这边补充一下,百度的Familia就集成这两种方式去算相似度,异常好用。

TWE

用过LDA的人应该知道:LDA 产生的主题往往被高频词占据,这种现象导致低频词在实际应用中的作用非常有限。

知道LDA原理的人应该知道:LDA通常假设同一个句子里的词产生自同一主题,对句子内的词进行了进一步的建模。

显而易见,这些都是不合理的。

Topical Word Embedding (TWE) 利用 LDA 训练获得的主题为词向量的训练提供补充信息,进而得到词和主题的向量表示。也就是说,我得到了主题向量,我也得到词向量,我结合两者一起来补充信息,这样我既照顾到了句的主题,也没有损失词的多样性信息。

如何去生成:

法1精度差但是好实现,法2训练时间长但是效果更可接受,法3给单词embedded学习过程中引入了主题向量的影响。我现在一般用3,但是我觉得2是也是可接受的。

WordEmbedding

这段比较无脑,是个nlp工程师都用过的方式。GloVe,FastText,W2V,DSSM生成词的向量化表征结果,然后通过SIF,加权,Attention,平均,求和,Pooling等各种花里胡哨的方法然后在计算Cosine相似度。

这个方法一定是baseline,效果非常可观,这边不多说。只是给大家分享一些我使用的心得

word embedding会带来一种问题,苹果和香蕉相关,“我下午想吃香蕉”和“我下午想吃苹果”,word embedding认为是一件事,但是实际可能并不是。

SentenceEmbedding

Sentence Embedding认为既然一个词可以是一个向量,一句话也可以是。这边的论文一堆,方法也一堆:doc2vec,Infersent,Sentence2Vec,skip-thought,Quick-Thought,FastSent。

以上这些是我看过还没忘的,我觉得比较有价值的。它们基于不同的思想,也有不同的作用,我这边谈几个比较经典的。

句向量来补充词向量衡量一个句子的相似度会有明显的提升,我日常做baseline就是wordembedding+sentenceembedding来算cosine的

Bert

原理就不讲了,一万个人写过bolg了,这边给大家整理了一份易错知识点Bert知识点

主要注意的是:

supervised method

有监督的方式大概有两种思路:

正儿八经的人用infersent或者fasttext这种就行了,越复杂的设计带来的风险在工业界也是难以hold住的。

以上这些,匹配方法可以得到2和3这种语句的聚合,但是需要考虑使用场景和收益率。

总结

讲道理,上面这些方法可以覆盖日常工作中的绝大多数文本相似度计算的方法,剩下就是如何去融合成一个适合场景的解决方案了。代码按大家的需要后续给大家开源。

上一篇 下一篇

猜你喜欢

热点阅读