zoukankan      html  css  js  c++  java
  • 使用jaccard距离计算文本相似度

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

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

    4.1 jaccard系数

    jaccard系数反映了两个向量(元素取值为0或1)间的关系。即对于Avec ABvec B,定义:
    NA0B0N_{A_0B_0} = Avec A中元素值为0且Bvec B中元素值为0的个数
    NA1B0N_{A_1B_0} = Avec A中元素值为1且Bvec B中元素值为0的个数
    NA0B1N_{A_0B_1} = Avec A中元素值为0且Bvec B中元素值为1的个数
    NA1B1N_{A_1B_1} = Avec A中元素值为1且Bvec B中元素值为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)

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

    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)=ABAB=ABA+BAB(3)J(A,B)=frac{|Aigcap{B}|}{|Aigcup{B}|}=frac{|Aigcap{B}|}{|A|+|B|-|Aigcap{B}|}(3)

    4.2 jaccard系数相似度

    jaccard系数值越大,相似度越高,另一种说法是用jaccard距离表示相似度即:1J(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岁以上、浏览时间为早上、浏览时间为中午、浏览时间为下午
    将以上维度作为一个集合,对两个用户AABB,将符合以上维度的指标值置为1,其他置为0。
    假设用户AA=[男性=1, 女性=0, 小于18岁=0, 18岁-40岁=1, 40岁以上=0, 浏览时间为早上=0, 浏览时间为中午=0, 浏览时间为下午=1]
    假设用户BB=[男性=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.5

    即他们的相似度为0.5

    用matlab验证下:

    在这里插入图片描述

    4.2.1 jaccard系数衡量文本相似性

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

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

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

    首先要做的还是分词:

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

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

    J(A,B)=ABAB=24=0.5J(A,B)=frac{|Aigcap{B}|}{|Aigcup{B}|}=frac{2}{4}=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的耗时:

    在这里插入图片描述

  • 相关阅读:
    53. Maximum Subarray
    64. Minimum Path Sum
    28. Implement strStr()
    26. Remove Duplicates from Sorted Array
    21. Merge Two Sorted Lists
    14. Longest Common Prefix
    7. Reverse Integer
    412. Fizz Buzz
    linux_修改域名(centos)
    linux_redis常用数据类型操作
  • 原文地址:https://www.cnblogs.com/cnsec/p/13286607.html
Copyright © 2011-2022 走看看