cos相似度算法 余弦距离计算

定义

余弦距离,也称余弦相似度,是用向量空间中两个向量夹角的余弦值作为衡量两个个体之间差异大小的度量。我们知道在数学领域内,cosθ 的值越接近 1,此时两个向量的夹角 θ 越接近 0度,表明这两个向量越相似,在极端情况下,当夹角为0度时 表示2个向量完全重合,这就叫“余弦相似性”。

公式

在平面直角三角形中余弦定值公式为

cos相似度算法 余弦距离计算_第1张图片

cos(θ) = a / c
但是在非直角三角形中,并不能用余弦定理求出cos(θ),在任意三角形中cos(θ)的求解公式为:

file

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T5Z98usV-1611377446693)(http://jeff.spring4all.com/FotFBt0mq8X-Lfsw7fgM-NXtpiOU)]

但是向量并不一定存在于平面中,因此在n维的空间里,cos(θ)的求解公式为

cos相似度算法 余弦距离计算_第2张图片

举例

以Meng 和 man为例,来计算二者之间的相似度。过程如下:

1、进行分词,并获取每个词在字符串中出现的次数作为向量值

词语 在第一个字符串出现的次数 在第二个字符串出现的次数
M 1 0
e 1 0
n 1 1
g 1 0
m 0 1
a 0 1

于是可以得出一个关于词语的map

{
	"M":[1][0],
	"e":[1][0],
	"n":[1][1],
	"g":[1][0],
	"m":[0][1],
	"a":[0][1]
}

根据计算公式可以得到

file

代码实现

public int cosSimilarity (String str1,String str2) {
	Map<Character, int[]> vectorMap = new HashMap<Character, int[]>();
    int[] tempArray = null;
    for (Character character1 : str1.toCharArray()) {
        if (vectorMap.containsKey(character1)) {
            vectorMap.get(character1)[0]++;
        } else {
            tempArray = new int[2];
            tempArray[0] = 1;
            tempArray[1] = 0;
            vectorMap.put(character1, tempArray);
        }
    }
    for (Character character2 : str2.toCharArray()) {
        if (vectorMap.containsKey(character2)) {
            vectorMap.get(character2)[1]++;
        } else {
            tempArray = new int[2];
            tempArray[0] = 0;
            tempArray[1] = 1;
            vectorMap.put(character2, tempArray);
        }
    }

    double result = 0;
    double sqrtResult = MathUtil.sqrtMulti(vectorMap);
    result = sqrtResult == 0 ? 0 : (MathUtil.pointMulti(vectorMap) / MathUtil.sqrtMulti(vectorMap));
    return result;
}

public static double sqrtMulti(Map<Character, int[]> paramMap) {
    double result = 0;
    result = squares(paramMap);
    result = Math.sqrt(result);
    return result;
}
	
public static double pointMulti(Map<Character, int[]> paramMap) {
    double result = 0;
    Set<Character> keySet = paramMap.keySet();
    for (Character character : keySet) {
        int[] temp = paramMap.get(character);
        result += (temp[0] * temp[1]);
    }
    return result;
}
	
public static double sqrtMulti(Map<Character, int[]> paramMap) {
    double result = 0;
    result = squares(paramMap);
    result = Math.sqrt(result);
    return result;
}
	
/**
 * 求平方和
 */
public static 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);
        result1 += (temp[0] * temp[0]);
        result2 += (temp[1] * temp[1]);
    }
    return result1 * result2;
}

运行代码可以得出和手工计算的一致

cos相似度算法 余弦距离计算_第3张图片

欢迎关注我的公众号

cos相似度算法 余弦距离计算_第4张图片

你可能感兴趣的:(算法,java,大数据)