jaccard相似度_Jaccard与cosine文本相似度的异同

be5e77364c6e1d2196bdbfcd168a7990.png

工作过程中,常常其他业务的同学问到:某两个词的相似度是多少?某两个句子的相似度是多少?某两个文档之间的相似度是多少?在本文中,我们讨论一下jaccard与cosine在文本相似度上的差异,以及他们适用的场景。在介绍二者的异同之前呢,我们首先介绍一下,jaccard相似度和cosine相似度的定义。

(想直接看结论的,请关注文末的加粗部分)

Jaccard相似度

Jaccard相似度的定义很简单,两个句子词汇的交集size除以两个句子词汇的并集size。举个例子来说:

  • 句子1: AI is our friend and it has been friendly.
  • 句子2: AI and humans have always been friendly.

为了计算Jaccard相似度,我们首先使用英文nlp中常用的技术Lemmatization,用词根替换那些具有相同词根的词汇。在上面的例子中,friend和friendly具有相同的词根,have和has具有相同的词根。我们可以画出两个句子词汇的交集与并集情况,如图所示:

f6ee025317ec018881902950920c3411.png

对于上面两个句子,其Jaccard相似度为5/(5+3+2)=0.5,即两个句子词汇的交集5个词汇,并集10个词汇。

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

值得注意的是,句子1中包含了两个friend,但这并不影响我们计算相似度,但这会影响cosine相似度。先让我们回忆一下cosine相似度的定义,公式如下。

bf65d3482312ba83d0e9a3cfa7cfbd06.png

cosine相似度是通过计算两个向量之间的夹角,来评价两个向量的相似度。

既然cosine相似度是使用向量计算的,我们就要先将句子文本转换为相应的向量。将句子转换为向量的方式有很多,最简单的一种就是使用bag of words计算的TF(term frequency)和TF-IDF(term frenquency-inverse document frequency)。哪一钟转换方法更好呢?实际上,两个方法各有各的应用场景。当我们要大概估计文本相似度时,使用TF就可以了。当我们使用文本相似度进行检索的类似场景时(如搜索引擎中的query relevence的计算),此时TF-IDF更好一些。

当然,我们也可以使用word2vec或者使用自定义的词向量来讲句子转换成向量。这里简单介绍一下tf-idf和word embedding的异同: - 1. tf/tf-idf为每一个词汇计算得到一个数字,而word embedding将词汇表示成向量 - 2. tf/tf-idf在文本分类的任务中表现更好一些,而word embedding的方法更适用于来判断上下文的语义信息(这可能是由word embedding的计算方法决定的)。

对于如何计算cosine similarity,我们还是试用上面的例子:

  • 句子1: AI is our friend and it has been friendly.
  • 句子2: AI and humans have always been friendly.

计算cosine similarity的过程,分位以下几个步骤:

第一步

使用bag of words的方式计算term frequency,下图展示了word frequency的统计结果。

19fe761b6c20cf6416172b9022bcd927.png

第二步

term frequency的问题在于,较长的句子里的词汇term frequency会更高一些。为了解决这个问题,我们可以使用归一化的方法(Normlization,如L2-norm)来去掉句子长度的影响。操作如下:首先对各个词汇的frequency平方求和,然后再开方。如果使用L2-norm,那么句子1的值为3.3166,而句子2的值为2.6458。用每一个词的term frquency除以这些norm的值,就可以得到如下结果:

927aa9e9d97f67cbdb3bdfefd1e79436.png

第三步

上一步中,我们将句子向量的模归一化为1,就可以受用点乘的方法计算得到cosine相似度: Cosine Similarity = (0.3020.378) + (0.6030.378) + (0.3020.378) + (0.3020.378) + (0.302*0.378) = 0.684

所以两个句子的cosine相似度为0.684,而Jaccard相似度的结果是0.5。计算cosine相似度的python代码如下:

from 

总结一下,Jaccard和cosine相似度的区别是什么呢?应该有以下几点:

- Jaccard使用的是集合操作,句子的向量长度由两个句子中unique的词汇数目决定,而cosine相似度使用的向量大小由词向量的维度决定。

- 上面的结论意味着什么呢?假设friend这个词汇在句子1中重复了非常多次,cosine相似度会发生变化,而Jaccard相似度的值不会变。让我们做个简单的计算,若句子1中的friend一词重复50次,cosine相似度会降为0.4,而Jaccard相似度保持0.5不变。

- 基于上述的结论,Jaccard相似度适用于什么场景呢?假设某个业务场景的文本包含了很多重复性的词汇,而这些重复是否与我们想做的任务关系不大,那么在分析文本相似度时,使用Jaccard计算相似度即可,因为对于Jaccard相似度来说,重复不会产生影响;假设这种重复对我们想做的任务影响很大,那么就要使用cosine相似度。

最后,这里列举了两个具体的应用场景,供大家思考。仅仅对Jaccard和cosine相似度来说:

1. 在京东、天猫的商品搜索栏,使用什么相似度最好呢?

2. 对语音转写文本的相似度,哪个更好呢?

本文译自: Overview of Text Similarity Metrics in Python,略有改动。

如果觉得文章对您有帮助,可以关注本人的微信公众号:机器学习小知识

2988c7f1f26bbaff3f3bc7e24d290d4c.png
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值