余弦相似度算法(Cosine Similarity)

前言

最近在刷视频的时候,刷到一个视频推荐的后台逻辑算法,其中之一就是余弦相似度算法。
想到了大学做商城项目,做商品推荐功能也用到了这个算法,当时觉得很难的知识,现在看看视频就能轻松理解了。
这篇文章是我最近学习余弦相似度的笔记,其中也附带了我个人的一些理解。

定义

余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。------《百度百科》

公式

计算余弦相似度离不开高中数学向量的知识
向量 A 表示为 (a1,a2,⋯ ,an)(a_1, a_2, \cdots, a_n)(a1,a2,,an)
向量 B 表示为 (b1,b2,⋯ ,bn)(b_1, b_2, \cdots, b_n)(b1,b2,,bn)

数学向量计算点积的公式:
A⋅B=∣∣A∣∣×∣∣B∣∣×cosθ A \cdot B= ||A|| \times ||B|| \times cos \theta AB=∣∣A∣∣×∣∣B∣∣×cosθ

余弦相似度由数学点积公式转换而得,cosθcos \thetacosθ 就代表余弦相似度。计算AB向量的余弦相似度的公式:
cosθ=A⋅B∣∣A∣∣×∣∣B∣∣ cos \theta = \frac { A \cdot B} {||A|| \times ||B||} cosθ=∣∣A∣∣×∣∣B∣∣AB

其中 A⋅BA \cdot BAB 是两个向量的点积,点积的计算公式:
A⋅B=∑i=1n(ai×bi)=a1×b1+a2×b2+⋯+an×bn A \cdot B = \sum_{i=1}^n(a_i \times b_i) = a_1 \times b_1 + a_2 \times b_2 + \cdots + a_n \times b_n AB=i=1n(ai×bi)=a1×b1+a2×b2++an×bn

∣∣A∣∣×∣∣B∣∣||A|| \times ||B||∣∣A∣∣×∣∣B∣∣ 是A、B向量的模的乘积:
∣∣A∣∣=∑i=1n(ai)2=(a1)2+(a2)2+⋯+(an)2 ||A|| = \sqrt{\sum_{i=1}^n(a_i)^2} = \sqrt{(a_1)^2 +(a_2)^2+ \cdots+ (a_n)^2 } ∣∣A∣∣=i=1n(ai)2=(a1)2+(a2)2++(an)2
∣∣B∣∣=∑i=1n(bi)2=(b1)2+(b2)2+⋯+(bn)2 ||B|| = \sqrt{\sum_{i=1}^n(b_i)^2} = \sqrt{(b_1)^2 +(b_2)^2 + \cdots+ (b_n)^2 } ∣∣B∣∣=i=1n(bi)2=(b1)2+(b2)2++(bn)2

余弦相似度公式展开:
cosθ=∑i=1n(ai×bi)∑i=1n(ai)2×∑i=1n(bi)2=a1×b1+a2×b2+⋯+an×bn(a1)2+(a2)2+⋯+(an)2×(b1)2+(b2)2+⋯+(bn)2 cos \theta = \frac { \sum_{i=1}^n(a_i \times b_i) } { \sqrt{\sum_{i=1}^n(a_i)^2} \times \sqrt{\sum_{i=1}^n(b_i)^2} } = \frac { a_1 \times b_1 + a_2 \times b_2 + \cdots + a_n \times b_n } { \sqrt{(a_1)^2 +(a_2)^2+ \cdots+ (a_n)^2 } \times \sqrt{(b_1)^2 +(b_2)^2 + \cdots+ (b_n)^2 } } cosθ=i=1n(ai)2×i=1n(bi)2i=1n(ai×bi)=(a1)2+(a2)2++(an)2×(b1)2+(b2)2++(bn)2a1×b1+a2×b2++an×bn
cosθ\thetaθ 的值域为 [-1, 1], 计算出的结果永远处于 [-1, 1] 区间。

代码实现

public class CosineSimilarityManual {
    public static double compute(double[] v1, double[] v2) {
        double dotProduct = 0.0;
        double norm1 = 0.0;
        double norm2 = 0.0;

        for (int i = 0; i < v1.length; i++) {
            dotProduct += v1[i] * v2[i];
            norm1 += Math.pow(v1[i], 2);
            norm2 += Math.pow(v2[i], 2);
        }

        return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
    }

    public static void main(String[] args) {
        double[] v1 = {1, 2, 3};
        double[] v2 = {4, 5, 6};

        double similarity = compute(v1, v2);
        System.out.println("Cosine Similarity (Manual): " + similarity);
    }
}

计算结果的数学解释

余弦相似度测量的是两个向量在方向上的差异
计算结果处于 (0, 1] 区间时,两个向量才会有正相关,并且越接近 1,相关性越高。
当计算结果为 1,表示两个向量方向完全相同。
当计算结果为 0,表示两个向量互相独立(正交)。
当计算结果为 -1,表示两个向量方向完全相反。

余弦相似度在平面直角坐标系的几何意义

余弦相似度就是两个向量的夹角余弦值,只和向量的夹角有关。
以二维平面直角坐标系,以下四个向量为例
A (2, 0)
B (3\sqrt{3}3, 1)
C (1, 3\sqrt{3}3)
D (0,2)
【图片】

如图所示
AB的夹角θ1\theta_1θ1 = BC的夹角θ2\theta_2θ2 = CD的夹角θ3\theta_3θ3
所以在这个例子中
AB夹角的余弦相似度cosθ1cos \theta_1cosθ1 = BC夹角的余弦相似度cosθ2cos \theta_2cosθ2 = CD夹角的余弦相似度cosθ3cos \theta_3cosθ3

代码中计算结果如下,发现和上述一致
在这里插入图片描述
公式的计算结果永远处于 [-1, 1] 这个区间。
在三维情况下,我们仍然可以想象得到两个向量,在一个三维空间内,产生一个夹角,并且计算夹角的余弦值。
在四维以上的情况下,就没办法建立对应的坐标系画出对应的图形了,但是并不影响计算的结果,结果也处于 [-1, 1] 这个区间,也不影响其结果代表的含义。

应用场景

余弦相似度的应用场景
1.求职软件技术栈匹配,为求职者推荐岗位,或者为hr推荐牛人
2.对文字进行分词之后,可以做文章查重、论文查重、代码查重
3.在交友软件中,可以推荐与我志同道合的好友
4.在娱乐软件中,可以做歌单推荐、视频推荐
5.分析足球运动某位置需要的能力与球员的能力匹配度
6.考勤打卡、刷脸支付人脸比对

注意事项

余弦相似度只能根据两个向量的夹角求相似度,与向量本身的模并没有关系。
所以有时候要结合向量的模一起使用。

以上述应用场景1求职软件为例:
假设岗位需要:精通mysql、精通java、精通RabbitMQ,精通redis
一个求职者在给自己的简历标签是:了解mysql、了解java、了解RabbitMQ,了解redis。

用【1, 2, 3, 4, 5】来代表 【了解, 熟悉, 掌握, 熟练, 精通】
岗位向量:(5, 5, 5, 5, 5)
求职者向量:(1, 1, 1, 1, 1)
计算得到的 cosθcos \thetacosθ=1 完全匹配
但是在这个业务场景中,很显然,一个对技术只有了解的开发者,大概率不能胜任这个岗位,因此,这个场景需要结合向量的模来一起做判断。

总结

余弦相似度关注方向而非距离,当数据的大小不重要而方向重要时,余弦相似度比欧氏距离更合适。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值