`
happy_tao_cool
  • 浏览: 17737 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

余弦相似度计算简易版

阅读更多

     今天写了下余弦相似度计算的算法,之前在学校做项目的时候使用到了,一直没去整理。

     所谓的字符串余弦相似度,就是把每个字符串比作一个向量,通过计算向量余弦值来判断字符串的相似程度,余弦值越接近1,说明两个字符串的相似度就越高,余弦值的计算公式为:(向量a*向量b)/(向量a的模*向量b的模)

    实现如下:

package demo.similarity;

import java.util.HashMap;
import java.util.Map;

public class Utils {
	
	 public static double calculateSimilarity(String source, String dest){
		 
        //用map存放词在字符串中所出现的次数,key为词,value为整型数组
         Map<String, int[]> wordAppearTimes = new HashMap<String, int[]>();
         
         //这里是按照单个字来进行分割,假如在这里做一次分词,效果会更好点,但是复杂度也会高些
         //生成source字符串的向量
         int sourceLen = source.length();
         for(int i=0; i<sourceLen; ++i){
             if(wordAppearTimes.containsKey(source.charAt(i)+"")){
                 ++(wordAppearTimes.get(source.charAt(i)+"")[0]);
             }else{
            	 int[] appearTimes = new int[2];
            	 appearTimes[0] = 1;
            	 appearTimes[1] = 0;
            	 wordAppearTimes.put(source.charAt(i)+"", appearTimes);
             }
         }
         
         //生成dest字符串的向量
         int destLen = dest.length();
         for(int i=0; i<destLen; ++i){
             if(wordAppearTimes.containsKey(dest.charAt(i)+"")){
                 ++(wordAppearTimes.get(dest.charAt(i)+"")[1]);
             }else{
            	 int[] appearTimes = new int[2];
            	 appearTimes[0] = 0;
            	 appearTimes[1] = 1;
                 wordAppearTimes.put(dest.charAt(i)+"", appearTimes);
             }
         }
         
         //向量source的模
         double sourceModel = 0.00;
         //向量dest的模 
         double destModel = 0.00;
         //向量积 
         double crossProduct = 0.00;
         
         for(Map.Entry<String, int[]> entry : wordAppearTimes.entrySet()){
        	 sourceModel += entry.getValue()[0] * entry.getValue()[0];
        	 destModel += entry.getValue()[1] * entry.getValue()[1];
        	 crossProduct += entry.getValue()[0] * entry.getValue()[1];
         }
         
         sourceModel = Math.sqrt(sourceModel);
         destModel = Math.sqrt(destModel);
         
         double similarity = crossProduct / (sourceModel * destModel);
         return similarity;
     }
	 
	 public static void main(String[] args) {
		String s1 = "代码整洁之道";
		String s2 = "代码整洁之道";
		System.out.println(calculateSimilarity(s1,s2));
	}
}

    输出为:

1.000000000000000

    虽然这样能计算两个字符串的相似度,但是也存在一些缺陷:

    1.按照上面的方法计算相似度,代码并没有按照词出现的顺序计算,比如我把上面的“代码整洁之道”改为“代码之道整洁”,结果还会是一样的

     2.在实际应用中,按照单字来计算余弦相似度也是比较少的,除非系统对相似度计算得要求不高;对字符串加入分词,效果会更好一些

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics