使用jaccard距离计算文本相似度

本文深入探讨了Jaccard系数的计算原理与应用场景,包括文本相似度与多维度相似性的评估,通过具体实例展示了如何利用Jaccard系数进行有效分析。

1. 使用simhash计算文本相似度
2. 使用余弦相似度计算文本相似度
3. 使用编辑距离计算文本相似度
4. jaccard系数计算文本相似度

4. jaccard系数计算文本相似度

4.1 jaccard系数

jaccard系数反映了两个向量(元素取值为0或1)间的关系。即对于 A ⃗ \vec A A B ⃗ \vec B B ,定义:
N A 0 B 0 N_{A_0B_0} NA0B0 = A ⃗ \vec A A 中元素值为0且 B ⃗ \vec B B 中元素值为0的个数
N A 1 B 0 N_{A_1B_0} NA1B0 = A ⃗ \vec A A 中元素值为1且 B ⃗ \vec B B 中元素值为0的个数
N A 0 B 1 N_{A_0B_1} NA0B1 = A ⃗ \vec A A 中元素值为0且 B ⃗ \vec B B 中元素值为1的个数
N A 1 B 1 N_{A_1B_1} NA1B1 = A ⃗ \vec A A 中元素值为1且 B ⃗ \vec B B 中元素值为1的个数
则 jaccard系数可以表示为:

J ( A , B ) = N A 0 B 0 + N A 1 B 1 N A 0 B 0 + N A 1 B 0 + N A 0 B 1 + N A 1 B 1 ( 1 ) J(A,B)=\frac{N_{A_0B_0}+N_{A_1B_1}}{N_{A_0B_0}+N_{A_1B_0}+N_{A_0B_1}+N_{A_1B_1}} (1) J(A,B)=NA0B0+NA1B0+NA0B1+NA1B1NA0B0+NA1B1(1)

当向量中为0的元素远大于为1的元素的个数时, N A 0 B 0 N_{A_0B_0} NA0B0 需要从计算中移除,而只关注均为1的元素的个数。因为当 N A 0 B 0 N_{A_0B_0} NA0B0较大时,整个计算结果将区域稳定,无明显特征了。所以以上公式变为:

J ( A , B ) = N A 1 B 1 N A 1 B 0 + N A 0 B 1 + N A 1 B 1 ( 2 ) J(A,B)=\frac{N_{A_1B_1}}{N_{A_1B_0}+N_{A_0B_1}+N_{A_1B_1}} (2) J(A,B)=NA1B0+NA0B1+NA1B1NA1B1(2)

另一种用集合表示的方法:

J ( A , B ) = ∣ A ⋂ B ∣ ∣ A ⋃ B ∣ = ∣ A ⋂ B ∣ ∣ A ∣ + ∣ B ∣ − ∣ A ⋂ B ∣ ( 3 ) J(A,B)=\frac{|A\bigcap{B}|}{|A\bigcup{B}|}=\frac{|A\bigcap{B}|}{|A|+|B|-|A\bigcap{B}|}(3) J(A,B)=ABAB=A+BABAB(3)

4.2 jaccard系数相似度

jaccard系数值越大,相似度越高,另一种说法是用jaccard距离表示相似度即: 1 − J ( A , B ) 1-J(A,B) 1J(A,B),本质一样,但jaccard距离越大相似度越小。

一般的 jaccard系数只适用于计算元素取值为0或1的集合,但是要注意的是这里取值为0或1并不是值集合中的值为0或1,而仅仅是集合中元素的取值为0或1,而计算出的jaccard系数是和元素本身相关的。

4.2.1 jaccard系数衡量维度相似性

jaccard系数很适合用来分析多个维度间的相似性,也多被用于推荐系统中用来给用户推荐相似的产品或业务。
举个例子,要计算某网站的两个用户的相似性,可以从性别、地区、年龄、浏览时间等等维度进行分析,我们把这些维度再进行细化:
男性、女性、小于18岁、18岁-40岁、40岁以上、浏览时间为早上、浏览时间为中午、浏览时间为下午
将以上维度作为一个集合,对两个用户 A A A B B B,将符合以上维度的指标值置为1,其他置为0。
假设用户 A A A=[男性=1, 女性=0, 小于18岁=0, 18岁-40岁=1, 40岁以上=0, 浏览时间为早上=0, 浏览时间为中午=0, 浏览时间为下午=1]
假设用户 B B B=[男性=1, 女性=0, 小于18岁=1, 18岁-40岁=0, 40岁以上=0, 浏览时间为早上=0, 浏览时间为中午=0, 浏览时间为下午=1]
即他们只有年龄不同,则根据计算公式,得到的jaccard系数值为:

J ( A , B ) = N A 1 B 1 N A 1 B 0 + N A 0 B 1 + N A 1 B 1 = 2 4 = 0.5 J(A,B)=\frac{N_{A_1B_1}}{N_{A_1B_0}+N_{A_0B_1}+N_{A_1B_1}}=\frac{2}{4}=0.5 J(A,B)=NA1B0+NA0B1+NA1B1NA1B1=42=0.5

即他们的相似度为0.5

用matlab验证下:

在这里插入图片描述

4.2.1 jaccard系数衡量文本相似性

虽然jaccard主要是在维度分析这样的稀疏向量中作用比较大,但是在文本相似度计算时也可用jaccard。

仍然用之前的文本作为输入样本:

样本1:今天天气真好
样本2:今天天气不错

首先要做的还是分词:

A = [今天,天气,真好]

B = [今天,天气,不错]

J ( A , B ) = ∣ A ⋂ B ∣ ∣ A ⋃ B ∣ = 2 4 = 0.5 J(A,B)=\frac{|A\bigcap{B}|}{|A\bigcup{B}|}=\frac{2}{4}=0.5 J(A,B)=ABAB=42=0.5

转化为01向量,用matlab验证下:
在这里插入图片描述

4.3 jaccard系数计算实现(java)

public static double jaccard(String s1, String s2) {
        List<String> words1 = splitWords(s1);
        List<String> words2 = splitWords(s2);

        List<String> temp = new ArrayList<>();
        temp.addAll(words1);
        temp.addAll(words2);
        List<String> union = temp.stream().distinct().collect(Collectors.toList());
        List<String> intersect = new ArrayList<>();

        List<String> a = words1.stream().
                map(x -> words2.contains(x) ? x : null).
                collect(Collectors.toList());

        List<String> b = words2.stream().
                map(x -> words1.contains(x) ? x : null).
                collect(Collectors.toList());

        intersect.addAll(a);
        intersect.addAll(b);
        intersect = intersect.stream().distinct().collect(Collectors.toList());
        intersect.removeAll(Collections.singleton(null));

        return 1.0 * intersect.size() / union.size();
    }

4.4 总结

以上只是简单的从字符出现或者没有出现的角度进行相似度计算,而没有考虑其他因素。实际上,还可以结合词义进行近义词替换,来进一步达到语义层面的相似度计算,这样结果会更为准确。
下面时jaccard的耗时:

在这里插入图片描述

### 使用 Jaccard 系数计算文本相似度 Jaccard 系数是一种用于衡量两个集合之间相似性的指标,其定义为交集大小除以并集大小。在文本相似度分析中,通常会先将文本转换成一组词或 n-gram 的形式,再通过计算它们的 Jaccard 系数得出相似度。 #### 1. 基本原理 假设我们有两个文本 A 和 B,分别将其表示为集合 \(A\) 和 \(B\),则 Jaccard 系数可以通过以下公式计算: \[ \text{Jaccard Similarity} = \frac{|A \cap B|}{|A \cup B|} \] 其中: - \( |A \cap B| \) 表示两集合的交集大小; - \( |A \cup B| \) 表示两集合的并集大小。 如果需要计算的是 Jaccard 距离,则可以使用如下公式[^4]: \[ \text{Jaccard Distance} = 1 - \text{Jaccard Similarity} \] --- #### 2. Python 实现代码 以下是基于 `scipy` 库实现的 Jaccard 相似度计算代码示例: ```python from scipy.spatial.distance import jaccard import numpy as np def calculate_jaccard_similarity(set_a, set_b): """ 计算两个集合的 Jaccard 相似度。 参数: set_a (set): 集合 A set_b (set): 集合 B 返回: float: Jaccard 相似度值 """ intersection = len(set_a.intersection(set_b)) union = len(set_a.union(set_b)) return intersection / union if union != 0 else 0 # 示例文本 text1 = "机器学习是一门多领域交叉学科" text2 = "深度学习是机器学习的一个分支" # 将文本拆分为单词集合 set_text1 = set(text1.split()) set_text2 = set(text2.split()) # 计算 Jaccard 相似度 similarity = calculate_jaccard_similarity(set_text1, set_text2) print(f"Jaccard 相似度: {similarity}") ``` 上述代码实现了自定义的 Jaccard 相似度计算逻辑,并提供了简单的测试案例。需要注意的是,在实际应用中可能还需要考虑中文分词等问题。 --- #### 3. 利用 Scikit-Learn 进一步优化 除了手动实现外,还可以借助 `sklearn.feature_extraction.text.CountVectorizer` 来完成更复杂的文本预处理工作。下面是一个完整的例子: ```python from sklearn.feature_extraction.text import CountVectorizer from sklearn.metrics.pairwise import pairwise_distances def text_to_jaccard_similarity(texts): """ 使用 CountVectorizer 和 Jaccard 距离矩阵计算多个文本间的相似度。 参数: texts (list of str): 输入文本列表 返回: ndarray: 多个文本Jaccard 相似度的距离矩阵 """ vectorizer = CountVectorizer(binary=True) # 只关心是否存在某个词语 X = vectorizer.fit_transform(texts).toarray() distance_matrix = pairwise_distances(X, metric="jaccard") similarity_matrix = 1 - distance_matrix return similarity_matrix texts = [ "自然语言处理技术", "自然语言理解能力", "计算机视觉研究方向" ] result = text_to_jaccard_similarity(texts) print("Jaccard 相似度矩阵:") print(result) ``` 此代码片段利用了二元计数值向量器 (`CountVectorizer`) 并结合 `pairwise_distances` 函数快速得到任意数量文档之间的 Jaccard 相似度矩阵[^3]。 --- ### 总结 以上两种方式均能有效解决如何用 Jaccard 系数计算文本相似度的问题。前者适合简单场景下的单次对比;后者更适合批量数据处理以及复杂环境的应用需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勇敢牛牛_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值