代码改变世界

十分钟搞懂机器学习中的余弦相似性

2024-07-15 12:45  萤火架构  阅读(271)  评论(2编辑  收藏  举报

在机器学习中,我们经常会使用余弦函数来计算向量之间的相似性。从推荐系统到自然语言处理,再到计算机视觉,余弦相似性在多种机器学习应用中都有其独特的价值。它不仅限于特定领域,而是几乎可以在任何需要比较向量相似度的场景下使用。
这里边有两个重要的概念:向量、余弦,这是中学阶段学习的内容,考虑到年代久远,很多同学可能对这两个概念比较模糊了,所以本文先从余弦和向量的概念讲起,带大家一步步深入了解。

什么是余弦?

余弦(余弦函数)是三角函数的一种。
在直角三角形中,某个锐角的余弦等于它的邻边与斜边的比值,比如下图中角A的余弦就可以这样计算:cosA=b/c 。
image.png
在非直角三角形中,我们可以使用余弦定理:任意三角形中任一边的平方等于其他两边的平方和减去这两边与夹角余弦乘积的两倍,用公式表达就是:

我们对这个公式做一下变换,余弦就可以表示为:

直角三角形中锐角的余弦计算其实是余弦定理的一个特例,计算过程如下:
(1)首先,我们了解直角三角形中的勾股定理:

(2)将上边公式中 替换为 ,最后就能得出直角三角形中锐角的余弦计算方法:

什么是向量?

考虑到有些同学可能对向量这个概念比较模糊了,我这里先做个简单的介绍:
向量最初应用于物理学,本意是有方向的量,比如加速度。后来这个概念被应用到了数学中,在几何中我们可以用一个有方向的线段来表示向量,线段的箭头代表向量的方向,线段的长度代表向量的大小。如下图所示:
image.png
线段R就是一个向量,我们还可以把它分解到a和b两个维度上,A和B称为向量的分量。
进一步,我们把可以把向量表示在平面直角坐标系中:

d89d6c20-107d-4d60-b642-18ece8e67b69.png
这是一个简单的二维向量(只有x、y两个维度),此时我们可以把向量表示为 a=(4,5),其中(x,y)是点P的坐标。
在机器学习中,我们只要获取到某个事物在若干纬度上的特征,就可以创建一个向量。比如对于部分人群,我们可能要关注他们的年龄、收入、工作年份等特征,假设其中一个人的特征是:

  • 年龄:30
  • 收入:60000
  • 工作年份:2014

映射后的向量就是:(30,60000,2014) ,这是一个三维向量。
在机器学习中,我们需要计算的向量通常有很多纬度,这很难通过图形进行描绘,不过高维向量和低维向量的计算方法都是相同的,所以后续将继续使用二维向量来说明相关原理。

余弦相似性有什么用?

余弦相似性是用来衡量两个向量之间相似程度的一种方法。简单来说,它告诉我们两个向量之间的“夹角”有多小,夹角越小,两个向量越相似。那这在实际生活中有什么用呢?让我举个例子来说明。
假设我们在构建一个电影推荐系统。首先,我们可以把每部电影的类型(比如动作、喜剧、科幻等)转换成一个向量。比如,一部电影可能会被表示为[1, 0, 1, 0, 0],其中1代表该电影属于某种类型,而0代表不属于。
接下来,我们需要了解用户A的电影偏好。我们可以根据用户A之前看过的电影和他们的类型,生成一个用户偏好向量。比如,如果用户A喜欢动作和科幻电影,他们的偏好向量可能是[1, 0, 1, 0, 0]。
现在,关键的一步来了:我们使用余弦相似性来计算用户A的偏好向量和所有电影向量之间的相似度。这个相似度值越高,表示用户A越喜欢这部电影。
通过比较这些相似度值的大小,我们可以筛选出最符合用户A偏好的电影列表。这样一来,我们就可以为用户A推荐他们可能喜欢的新电影。
所以,余弦相似性在这个例子中起到了桥梁的作用,帮助我们从大量的电影中找到那些最符合用户偏好的选项。通过这种方式,我们能让用户更容易发现自己感兴趣的内容,提高用户的满意度。

如何计算向量之间的余弦?

我们还是从三角形的余弦定理出发:
,a、b、c分别代表三条边的长度,θ是a和b的夹角。
在这个公式中,我们只要知道三角形三条边的长度就可以计算出余弦值。
为了计算余弦值,我们可以用向量构造一个三角形。
假设在一个二维坐标系中,我们有两个向量 A(4,2) 和 B(2,3),现在只需要把 A 和 B 的终点连接起来,就能构造一个三角形,如下图所示:
image.png
因为 A 和 B 是已知向量,我们已经可以知道它们的长度,现在只需要第三条边的长度,我们就可以计算余弦了。

向量的减法

第3条边的计算需要依据向量减法的三角形法则,A-B 会产生一个新的向量 C:从B的终点出发指向A的终点,也就是三角形的第3条边。
用公式表达就是:C=A-B
那么第3条边的长度我们可以用 A-B 的长度来代替,余弦定理可以重新表达为:

这里 ||X|| 代表向量X的长度。
这样计算余弦,我们就只需要关注两个向量的相关计算逻辑,而不需要真的构造一个三角形。

向量的长度

向量的长度有一个专业化的名词:模长。长度就长度呗,为什么还单独起个名字?
在数学中,模通常指的是一个数的大小或者绝对值,不考虑其正负符号,比如 3和-3的模都是3。向量作为一个既有大小又有方向的概念,在讨论其大小时,我们只关心它的长度,而不考虑其指向,反映了从向量起点到终点的距离,而忽略了方向性。
模长的计算方法:向量中每个分量的平方和的开方值。比如上图中A向量终点的坐标为 (4,2),那么向量A的长度就是:

向量的点积

这里还要再引入一个新的概念:向量的点积,它是一种向量运算,接收两个向量作为输入,并返回一个标量值。如果有两个n维向量 A=[a1,a2,...,an] 和 B=[b1,b2,...,bn],那么它们的点积定义为所有对应元素乘积的和:

向量长度的平方可以通过该向量与自身的点积来表示,也就是说:

这是可以推导出来的,根据上边向量长度的计算方法:

那么:

而向量A与自身的点积结果也是这个结果:

所以:

使用点积计算余弦

我们再使用点积来表示余弦定理:

向量的点积遵循分配律、结合律和交换律:

  • 分配率:a(b+c)=ab+a*c
  • 结合律:(a+b)+c=a+(b+c)
  • 交换律:ab=ba

那么上边的公式可以继续表达为:


然后我们可以约去等式两边都有的 A⋅A 和 B⋅B:

进一步约去 -2:

最终,可以得到余弦的新计算公式:

两个向量的余弦就等于它们的点积除以它们的模长乘积。
向量的点积和模长计算方法上边已经介绍过,对上图中的向量A(4,2)和向量B(2,3),它们的余弦值可以计算为:

如此,只需要向量的值,我们就可以得出他们之间的余弦相似性了。

为什么余弦相似性不关心长度

余弦的特性

使用余弦相似性的情况下,长度不重要,方向才重要。我们可以通过下边的图来理解这个问题:
image.png
对于向量A和向量B,计算它们之间夹角的余弦值,我们可以从B向A发射一条垂线,构造一个直角三角形,然后用夹角的临边除以直角三角形的斜边(这是直角三角形中锐角余弦值的计算方法)。
如果我们缩小向量B的长度,临边和斜边的长度也会同步缩小,这对夹角余弦值的计算没有什么影响。
如果你还心存疑虑,我们可以做个计算。
对上图中的向量A(4,2)和向量B(2,3),我们把上文中的余弦值计算结果拿过来:

现在我们把向量B缩小一半,改为(1,1.5),重新计算夹角的余弦值:

结果还是一样的。

业务的选择

业务选择余弦来对比相似性,是因为数据的特征符合余弦相似性这种度量方法。
此类数据通常是一些分类特征,常见的有内容的主题、风格或者类别等。
举个为用户推荐电影的例子。
我们先将电影类型表示为如下向量:

  • 喜剧:[1, 0, 0, 0, 0]
  • 动作:[0, 1, 0, 0, 0]
  • 爱情:[0, 0, 1, 0, 0]
  • 科幻:[0, 0, 0, 1, 0]
  • 恐怖:[0, 0, 0, 0, 1]

然后我们假设这样一个用户,他喜欢的电影类型是喜剧和科幻。
我们可以将用户的偏好表示为一个由喜剧和科幻向量加权平均得到的向量:

  • 用户偏好:[0.5, 0, 0, 0.5, 0]

如果我们想要为这个用户推荐电影,我们就可以计算用户偏好向量与电影类型向量之间的余弦相似性,值越大,越值得推荐。

不适合余弦相似性度量的数据

连续的特征,比如评分或者活跃度之类的,它们表示用户对物品的喜好程度或使用频率。
使用向量比较此类数据时,向量长度就是一个很关键的指标。
如果用户给某个电影打了5星,我们不仅想要给用户推荐类似类型的电影,还想要推荐同样具备高评分的电影,此时仅用余弦相似性就不够了,我们可能还要加入距离的计算。
其它相似性算法超出了本文的范畴,这里就不多说了,有兴趣的同学可以去搜索下。


以上就是本文的主要内容。

关注萤火架构,加速技术提升!