余弦相似性获取文章相似度的java实现

转自:http://www.chepoo.com/cosine-similarity-java-implementation.html

文章相似度的实现可以用余弦相似性实现。余弦定理可参考:

余弦定理

字符串之间的相似度实现:字符串相似度算法(编辑距离)java实现

我们可以把它们想象成空间中的两条线段,都是从原点([0, 0, ...])出发,指向不同的方向。两条线段之间形成一个夹角,如果夹角为0度,意味着方向相同、线段重合;如果夹角为90度,意味着形成直角,方向完全不相似;如果夹角为180度,意味着方向正好相反。因此,我们可以通过夹角的大小,来判断向量的相似程度。夹角越小,就代表越相似。

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

阮一峰老师写的一篇博文简单明了,大家可以看看:TF-IDF与余弦相似性的应用(二):找出相似文章

实现该算法思路:

1.先用es-ik进行文章分词。

2.得到两篇文章的词频向量

3.计算两个向量的余弦相似度,值越大就表示越相似。

相关代码实现已经github上。具体地址为:https://github.com/awnuxkjy/recommend-system

package com.xq.algorithm;

import java.util.ArrayList;

import java.util.LinkedHashMap;

import java.util.List;

import java.util.Map;

/**

*

*

Title:

*

Description: 余弦获取文章相似性

*

* @createDate:2013-8-26

* @author xq

* @version 1.0

*/

public class CosineSimilarAlgorithm {

/**

*

* @Title: cosSimilarityByFile

* @Description: 获取两个文件相似性

* @param @param firstFile

* @param @param secondFile

* @param @return   

* @return Double 

* @throws

*/

public static Double cosSimilarityByFile(String firstFile,String secondFile){

try{

Map> firstTfMap=TfIdfAlgorithm.wordSegCount(firstFile);

Map> secondTfMap=TfIdfAlgorithm.wordSegCount(secondFile);

if(firstTfMap==null || firstTfMap.size()==0){

throw new IllegalArgumentException("firstFile not found or firstFile is empty! ");

}

if(secondTfMap==null || secondTfMap.size()==0){

throw new IllegalArgumentException("secondFile not found or secondFile is empty! ");

}

Map firstWords=firstTfMap.get(firstFile);

Map secondWords=secondTfMap.get(secondFile);

if(firstWords.size()

Map temp=firstWords;

firstWords=secondWords;

secondWords=temp;

}

return calculateCos((LinkedHashMap)firstWords, (LinkedHashMap)secondWords);

}catch(Exception e){

e.printStackTrace();

}

return 0d;

}

/**

*

* @Title: cosSimilarityByString

* @Description: 得到两个字符串的相似性

* @param @param first

* @param @param second

* @param @return   

* @return Double 

* @throws

*/

public static Double cosSimilarityByString(String first,String second){

try{

Map firstTfMap=TfIdfAlgorithm.segStr(first);

Map secondTfMap=TfIdfAlgorithm.segStr(second);

if(firstTfMap.size()

Map temp=firstTfMap;

firstTfMap=secondTfMap;

secondTfMap=temp;

}

return calculateCos((LinkedHashMap)firstTfMap, (LinkedHashMap)secondTfMap);

}catch(Exception e){

e.printStackTrace();

}

return 0d;

}

/**

*

* @Title: calculateCos

* @Description: 计算余弦相似性

* @param @param first

* @param @param second

* @param @return   

* @return Double 

* @throws

*/

private static Double calculateCos(LinkedHashMap first,LinkedHashMap second){

List> firstList = new ArrayList>(first.entrySet());

List> secondList = new ArrayList>(second.entrySet());

//计算相似度 

        double vectorFirstModulo = 0.00;//向量1的模 

        double vectorSecondModulo = 0.00;//向量2的模 

        double vectorProduct = 0.00; //向量积 

        int secondSize=second.size();

for(int i=0;i

if(i

vectorSecondModulo+=secondList.get(i).getValue().doubleValue()*secondList.get(i).getValue().doubleValue();

vectorProduct+=firstList.get(i).getValue().doubleValue()*secondList.get(i).getValue().doubleValue();

}

vectorFirstModulo+=firstList.get(i).getValue().doubleValue()*firstList.get(i).getValue().doubleValue();

}

  return vectorProduct/(Math.sqrt(vectorFirstModulo)*Math.sqrt(vectorSecondModulo));

}

public static void main(String[] args){

Double result=cosSimilarityByString("中国是超级大国",

"中国是世界超级大国。");

System.out.println(result);

}

}

你可能感兴趣的:(余弦相似性获取文章相似度的java实现)