余弦相似性獲取文章相似度的java實現(xiàn)

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

文章相似度的實現(xiàn)可以用余弦相似性實現(xiàn)。余弦定理可參考:

余弦定理

字符串之間的相似度實現(xiàn):字符串相似度算法(編輯距離)java實現(xiàn)

我們可以把它們想象成空間中的兩條線段,都是從原點([0, 0, ...])出發(fā),指向不同的方向。兩條線段之間形成一個夾角,如果夾角為0度,意味著方向相同、線段重合;如果夾角為90度,意味著形成直角,方向完全不相似;如果夾角為180度,意味著方向正好相反。因此,我們可以通過夾角的大小,來判斷向量的相似程度。夾角越小,就代表越相似。

余弦值越接近1,就表明夾角越接近0度,也就是兩個向量越相似,這就叫”余弦相似性”。

阮一峰老師寫的一篇博文簡單明了,大家可以看看:TF-IDF與余弦相似性的應用(二):找出相似文章

實現(xiàn)該算法思路:

1.先用es-ik進行文章分詞。

2.得到兩篇文章的詞頻向量

3.計算兩個向量的余弦相似度,值越大就表示越相似。

相關代碼實現(xiàn)已經(jīng)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;

/**

*

* <p>Title:</p>

* <p>Description: 余弦獲取文章相似性

* </p>

* @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<String, Map<String, Integer>> firstTfMap=TfIdfAlgorithm.wordSegCount(firstFile);

Map<String, Map<String, Integer>> 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<String,Integer> firstWords=firstTfMap.get(firstFile);

Map<String,Integer> secondWords=secondTfMap.get(secondFile);

if(firstWords.size()<secondWords.size()){

Map<String, Integer> temp=firstWords;

firstWords=secondWords;

secondWords=temp;

}

return calculateCos((LinkedHashMap<String, Integer>)firstWords, (LinkedHashMap<String, Integer>)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<String, Integer> firstTfMap=TfIdfAlgorithm.segStr(first);

Map<String, Integer> secondTfMap=TfIdfAlgorithm.segStr(second);

if(firstTfMap.size()<secondTfMap.size()){

Map<String, Integer> temp=firstTfMap;

firstTfMap=secondTfMap;

secondTfMap=temp;

}

return calculateCos((LinkedHashMap<String, Integer>)firstTfMap, (LinkedHashMap<String, Integer>)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<String, Integer> first,LinkedHashMap<String, Integer> second){

List<Map.Entry<String, Integer>> firstList = new ArrayList<Map.Entry<String, Integer>>(first.entrySet());

List<Map.Entry<String, Integer>> secondList = new ArrayList<Map.Entry<String, Integer>>(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<firstList.size();i++){

if(i<secondSize){

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);

}

}

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容