1. 程式人生 > >Java程式碼實現餘弦相似度演算法比較兩字串相似度

Java程式碼實現餘弦相似度演算法比較兩字串相似度

因工作需要比較兩個兩個字串的相似度比較,由於最短編輯距離演算法不符合需求,就又找其他演算法,在網上看到了另一個演算法:餘弦相似度演算法。於是學習了一下,並寫篇部落格儲存,以便學習以及日後用到。
程式碼如下:

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


  /*
   * 計算兩個字串(英文字元)的相似度,簡單的餘弦計算,未添權重
   */
   

public class AnotherCompare {
Map<Character, int[]> vectorMap = new HashMap<Character, int[]>();   

int[] tempArray = null;

public AnotherCompare(String string1, String string2) {

    for (Character character1 : string1.toCharArray()) {  //拆解為向量
        if (vectorMap.containsKey(character1)) {   //該字元是否已經存在map中
            vectorMap.get(character1)[0]++;   //key對應的值是一個數組,第一個字串的字元出現次數儲存在陣列第一個位置
        } else {
            tempArray = new int[2];  
            tempArray[0] = 1;  //如果字元沒有出現過,就新增到map中,陣列第一個位置設為1
            tempArray[1] = 0;
            vectorMap.put(character1, tempArray);
        }
    }
    for (Character character2 : string2.toCharArray()) {  //拆解為向量
        if (vectorMap.containsKey(character2)) {
            vectorMap.get(character2)[1]++;
        } else {
            tempArray = new int[2];
            tempArray[0] = 0;
            tempArray[1] = 1;  //第二個字串的字元出現次數儲存在陣列的第二個位置
            vectorMap.put(character2, tempArray);
        }
    }
    /*
     * 到最後,map裡的key對應的陣列,第一個位置儲存的是第一個字串字元對應的向量,第二個位置儲存的是第二個字串字元對應的向量。
     */
}

// 求餘弦相似度
public double sim() {   //分子分母相除
    double result = 0;
    result = pointMulti(vectorMap) / sqrtMulti(vectorMap);  
    return result;    //餘弦度結果返回,因為是餘弦,返回結果越大,夾角越小,兩個向量方向越接近,即兩個字串越相似
}

//求平方根
private double sqrtMulti(Map<Character, int[]> paramMap) {  
    double result = 0;
    result = squares(paramMap);  //先求平方和
    result = Math.sqrt(result);  //再開根號,就是求模
    return result;
}

// 求平方和,分母上,向量求模的平方
private double squares(Map<Character, int[]> paramMap) {
    double result1 = 0;
    double result2 = 0;
    Set<Character> keySet = paramMap.keySet();
    for (Character character : keySet) {
        int temp[] = paramMap.get(character);  //獲取key對應的值--陣列
        result1 += (temp[0] * temp[0]);   //temp[0]儲存的是第一個字串對應的向量
        result2 += (temp[1] * temp[1]);   //temp[1]儲存的是第二個字串對應的向量
    }
    return result1 * result2;
}

// 點乘法,在分子上,向量相乘
private double pointMulti(Map<Character, int[]> paramMap) {
    double result = 0;
    Set<Character> keySet = paramMap.keySet();  //返回map中所有key值的列表,這裡的set,也可以用list代替吧
    for (Character character : keySet) {    //儲存的key值都是不重複的
        int temp[] = paramMap.get(character);   //獲取key對應的值
        result += (temp[0] * temp[1]);
    }
    return resul 
    
}	

原理網上都有,這個程式碼也是網上的程式碼,我只是學習,加上了自己理解的註釋。如有不足,請多指教。