天天看点

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

1. 使用simhash计算文本相似度

2. 使用余弦相似度计算文本相似度

3. 使用编辑距离计算文本相似度

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

4.1 jaccard系数

jaccard系数反映了两个向量(元素取值为0或1)间的关系。即对于A⃗\vec AA和B⃗\vec BB,定义:

NA0B0N_{A_0B_0}NA0​B0​​ = A⃗\vec AA中元素值为0且B⃗\vec BB中元素值为0的个数

NA1B0N_{A_1B_0}NA1​B0​​ = A⃗\vec AA中元素值为1且B⃗\vec BB中元素值为0的个数

NA0B1N_{A_0B_1}NA0​B1​​ = A⃗\vec AA中元素值为0且B⃗\vec BB中元素值为1的个数

NA1B1N_{A_1B_1}NA1​B1​​ = A⃗\vec AA中元素值为1且B⃗\vec BB中元素值为1的个数

则 jaccard系数可以表示为:

J(A,B)=NA0B0+NA1B1NA0B0+NA1B0+NA0B1+NA1B1(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)=NA0​B0​​+NA1​B0​​+NA0​B1​​+NA1​B1​​NA0​B0​​+NA1​B1​​​(1)

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

J(A,B)=NA1B1NA1B0+NA0B1+NA1B1(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)=NA1​B0​​+NA0​B1​​+NA1​B1​​NA1​B1​​​(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)=∣A⋃B∣∣A⋂B∣​=∣A∣+∣B∣−∣A⋂B∣∣A⋂B∣​(3)

4.2 jaccard系数相似度

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

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

4.2.1 jaccard系数衡量维度相似性

jaccard系数很适合用来分析多个维度间的相似性,也多被用于推荐系统中用来给用户推荐相似的产品或业务。

举个例子,要计算某网站的两个用户的相似性,可以从性别、地区、年龄、浏览时间等等维度进行分析,我们把这些维度再进行细化:

男性、女性、小于18岁、18岁-40岁、40岁以上、浏览时间为早上、浏览时间为中午、浏览时间为下午

将以上维度作为一个集合,对两个用户AAA和BBB,将符合以上维度的指标值置为1,其他置为0。

假设用户AAA=[男性=1, 女性=0, 小于18岁=0, 18岁-40岁=1, 40岁以上=0, 浏览时间为早上=0, 浏览时间为中午=0, 浏览时间为下午=1]

假设用户BBB=[男性=1, 女性=0, 小于18岁=1, 18岁-40岁=0, 40岁以上=0, 浏览时间为早上=0, 浏览时间为中午=0, 浏览时间为下午=1]

即他们只有年龄不同,则根据计算公式,得到的jaccard系数值为:

J(A,B)=NA1B1NA1B0+NA0B1+NA1B1=24=0.5J(A,B)=\frac{N_{A_1B_1}}{N_{A_1B_0}+N_{A_0B_1}+N_{A_1B_1}}=\frac{2}{4}=0.5J(A,B)=NA1​B0​​+NA0​B1​​+NA1​B1​​NA1​B1​​​=42​=0.5

即他们的相似度为0.5

用matlab验证下:

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

4.2.1 jaccard系数衡量文本相似性

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

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

样本1:今天天气真好

样本2:今天天气不错

首先要做的还是分词:

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

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

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

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 总结

网络上志同道合,我们一起学习网络安全,一起进步,QQ群:694839022