转自: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
Map
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
Map
if(firstWords.size() Map firstWords=secondWords; secondWords=temp; } return calculateCos((LinkedHashMap }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 Map if(firstTfMap.size() Map firstTfMap=secondTfMap; secondTfMap=temp; } return calculateCos((LinkedHashMap }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 List List //计算相似度 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); } }