文本相似度判断:文本相似度量概述
文本相似度判断:文本相似度量概述对于上述两个句子,我们得到5 /(5 3 2)= 0.5的 Jaccard相似度,它是该集合的交集的大小除以集合的总大小。 Venn关于Jaccard相似性的两个句子的图表句子1: AI is our friend and it has been friendly句子2: AI and humans have always been friendly为了使用Jaccard similarity计算相似度,我们将首先执行lemmatization 以将单词缩减为相同的词根。在我们的例子中,“friend”和“friendly”都将成为“friend”,“has”和“have”都将成为“has”。绘制这两个句子的维恩图我们得到:
在为搜索引擎开发自然语言模型时,我经常会问“这两个词有多相似?”,“这两个句子有多相似?”,“这两个文档有多相似?”。在本文中,我们将更深入地探讨句子或文档相似性的技巧。
我们如何理解我们周围的所有文字?
有几个文本相似度量度,但我们会看看最常见的Jaccard相似度和余弦相似度。
Jaccard Similarity:Jaccard相似或交叉的交集被定义为交集的大小除以两个集合的大小。让我们以两个句子为例:
句子1: AI is our friend and it has been friendly
句子2: AI and humans have always been friendly
为了使用Jaccard similarity计算相似度,我们将首先执行lemmatization 以将单词缩减为相同的词根。在我们的例子中,“friend”和“friendly”都将成为“friend”,“has”和“have”都将成为“has”。绘制这两个句子的维恩图我们得到:
Venn关于Jaccard相似性的两个句子的图表
对于上述两个句子,我们得到5 /(5 3 2)= 0.5的 Jaccard相似度,它是该集合的交集的大小除以集合的总大小。
Python中Jaccard similarity的代码是:
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))
有一点需要注意的是,由于我们使用集合,“friend ”在第1句中出现了两次,但它不影响我们的计算 - 这将随着余弦相似度而改变。
余弦相似度:余弦相似度通过测量两个向量之间角度的余弦来计算相似度。这被计算为:
两个向量A和B的余弦相似度计算
使用余弦相似度,我们需要将句子转换为矢量。一种方法是使用tf(词频)或TF-IDF(词频 - 逆文档频率)的词组。TF或TF-IDF的选择取决于应用,并且对余弦相似性如何实际执行是不重要的 - 这只需要向量。TF一般而言对于文本相似性很好,但TF-IDF对于搜索查询相关性很好。
另一种方法是使用Word2Vec或我们自己的自定义word embeddings将单词转换为矢量。
tf / tf-idf与bag of words和word embeddings之间有两个主要区别:
-
tf / tf-idf每个单词创建一个数字,word embeddings通常会为每个单词创建一个向量。
-
tf / tf-idf对整个分类文档很有好处,但word embeddings对于识别上下文内容很有帮助。
我们来计算这两个句子的余弦相似度:
句子1:AI is our friend and it has been friendly
句子2:AI and humans have always been friendly
步骤1,我们将使用bag of words来计算术语频率:
在两个句子的词形化之后的术语频率
步骤2,上面显示的期限频率计数的主要问题是它支持较长的文档或句子。解决这个问题的一种方法是用各自的量值或L2标准对术语频率进行归一化。总结每个频率的平方并取平方根,句子1的L2范数为3.3166,句子2为2.6458。用这些规范划分词频以上,我们得到:
使用L2标准规范术语频率
步骤3,因为我们已经将两个向量归一化为长度为1,所以我们可以用点积来计算余弦相似度:
余弦相似度=(0.302 * 0.378) (0.603 * 0.378) (0.302 * 0.378) (0.302 * 0.378) (0.302 * 0.378)= 0.684
因此,这两个句子的余弦相似度为0.684,这与完全相同的两个句子的Jaccard相似度是不同的,这两个句子是0.5(上面计算的)
Python中的余弦相似性代码是:
import math
from collections import Counter
def get_cosine_sim(str1 str2):
tf1 = Counter(str1.split()) # Term Frequency
tf2 = Counter(str2.split())
norm1 = math.sqrt(sum([x**2 for x in tf1.values()])) # L2 norm
norm2 = math.sqrt(sum([x**2 for x in tf2.values()]))
vec1 = [float(x)/norm1 for x in tf1.values()] # Vector 1
vec2 = [float(x)/norm2 for x in tf2.values()] # Vector 2
return sum(x*y for x y in zip(vec1 vec2)) # Dot Product
Jaccard相似度与余弦相似度的区别:-
Jaccard相似度仅为每个句子/文档采用唯一的单词集,而余弦相似度则采用向量的总长度。(这些载体可以从词语词频或tf-idf)
-
这意味着如果在句子1中多次重复单词“朋友”,余弦相似性会改变,但是Jaccard相似性不会改变。例如,如果在第一个句子中重复50次“朋友”一词,则余弦相似度下降到0.4,但Jaccard相似度保持在0.5。
-
Jaccard相似性适用于重复不重要的情况,余弦相似性适用于分析文本相似性时重复重要的情况。对于两个产品说明,使用Jaccard相似性会更好,因为单词的重复不会降低它们的相似性。