java实现余弦计算相似度度量

余弦计算相似度度量

相似度度量(Similarity),即计算个体间的相似程度,相似度度量的值越小,说明个体间相似度越小,相似度的值越大说明个体差异越大。

对于多个不同的文本或者短文本对话消息要来计算他们之间的相似度如何,一个好的做法就是将这些文本中词语,映射到向量空间,形成文本中文字和向量数据的映射关系,通过计算几个或者多个不同的向量的差异的大小,来计算文本的相似度。下面介绍一个详细成熟的向量空间余弦相似度方法计算相似度

向量空间余弦相似度(Cosine Similarity)

余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,这就叫"余弦相似性"。

上图两个向量a,b的夹角很小可以说a向量和b向量有很高的的相似性,极端情况下,a和b向量完全重合。如下图:

如上图二:可以认为a和b向量是相等的,也即a,b向量代表的文本是完全相似的,或者说是相等的。如果a和b向量夹角较大,或者反方向。如下图

如上图三: 两个向量a,b的夹角很大可以说a向量和b向量有很底的的相似性,或者说a和b向量代表的文本基本不相似。那么是否可以用两个向量的夹角大小的函数值来计算个体的相似度呢?

向量空间余弦相似度理论就是基于上述来计算个体相似度的一种方法。下面做详细的推理过程分析。

想到余弦公式,最基本计算方法就是初中的最简单的计算公式,计算夹角

 

图(4)

的余弦定值公式为:

但是这个是只适用于直角三角形的,而在非直角三角形中,余弦定理的公式是

图(5)

三角形中边a和b的夹角 的余弦计算公式为:

公式(2)

在向量表示的三角形中,假设a向量是(x1, y1),b向量是(x2, y2),那么可以将余弦定理改写成下面的形式:

图(6)

向量a和向量b的夹角 的余弦计算如下

 

扩展,如果向量a和b不是二维而是n维,上述余弦的计算法仍然正确。假定a和b是两个n维向量,a是  ,b是  ,则a与b的夹角 的余弦等于:

余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,夹角等于0,即两个向量相等,这就叫"余弦相似性"。

使用上面的公式(4)

 

public class TTT {

Map vectorMap = new HashMap();  
int[] tempArray = null;  

public TTT(String source,String target ){

for(Character sch:source.toCharArray()){

if(vectorMap.containsKey(sch)){

vectorMap.get(sch)[0]++;
}
                                            //用将字符转化为向量
else{

tempArray = new int[2];  
                tempArray[0] = 1;  
                tempArray[1] = 0;  
                vectorMap.put(sch, tempArray);  
}

}


for(Character tch:target.toCharArray()){

if(vectorMap.containsKey(tch)){

vectorMap.get(tch)[1]++;
}
                                            //用将字符转化为向量
else{

tempArray = new int[2];  
                tempArray[0] = 0;  
                tempArray[1] = 1;  
                vectorMap.put(tch, tempArray);  
}

}


}

// 求余弦相似度  
    public double sim() {  
        double result = 0;  
        result = pointMulti(vectorMap) / sqrtMulti(vectorMap);  
        return result;  
    }  


// 求平方和  
    private double squares(Map paramMap) {  
        double result1 = 0;  
        double result2 = 0;  
        Set keySet = paramMap.keySet();  
        for (Character character : keySet) {  
            int temp[] = paramMap.get(character);  
            result1 += (temp[0] * temp[0]);  
            result2 += (temp[1] * temp[1]);  
        }  
        return result1 * result2;  
    }  

 // 点乘法  
    private double pointMulti(Map paramMap) {  
        double result = 0;  
        Set keySet = paramMap.keySet();  
        for (Character character : keySet) {  
            int temp[] = paramMap.get(character);  
            result += (temp[0] * temp[1]);  
        }  
        return result;  
    }  

    private double sqrtMulti(Map paramMap) {  
        double result = 0;  
        result = squares(paramMap);  
        result = Math.sqrt(result);  
        return result;  
    }  






public static void main(String[] args) {
   String s1="我是中国人";
   String s3="中国人";
   String s4="我是中国人";
   String s2="66666";
   TTT t2 =new TTT(s1,s2);
   TTT t4 =new TTT(s1,s4);
   TTT t3 =new TTT(s1,s3);
   System.out.println("==相似度==="+t2.sim());
   System.out.println("==相似度==="+t4.sim());
   System.out.println("==相似度==="+t3.sim());
   
    

}

结果:

==相似度===0.0

==相似度===1.0

==相似度===0.7745966692414834







你可能感兴趣的:(java实现余弦计算相似度度量)