跳至主要内容

什么是余弦距离?

探索余弦距离与余弦相似度。了解其计算方法、应用场景,并与其他度量对比。学习使用 numpy 在 R 与 Python 中实现。
· 8分钟 阅读

使用 AI 探索

由 Dall-E 绘制的余弦距离示意图

“余弦距离。” 图片由 Dall-E 提供。

衡量数据点之间的相似或不相似程度在诸多应用中都非常有用,从文本分析到推荐系统皆是如此。余弦距离是一种在高维或稀疏数据上尤为有效的距离度量,因为它关注的是向量的方向而非大小。

如果您想回顾机器学习中的常见且重要的概念,建议先阅读我们的综合教程揭秘深度学习中的数学概念。您也可以阅读另一篇基于距离的学习文章什么是曼哈顿距离?,以拓展对距离度量的理解,并比较余弦距离与曼哈顿距离的差异。

余弦距离的定义

下面我们根据余弦距离公式来定义余弦距离,并考察其与余弦相似度的关系。

余弦距离公式

余弦距离通过计算两个向量夹角的余弦来衡量它们的不相似程度。它可定义为 1 减去余弦相似度,如下式所示:

用余弦相似度表示的余弦距离公式

更形式化地说,余弦距离可由下式计算:

完整数学表达的余弦距离公式

其中,A⋅B 表示向量 A 与 B 的点积,||A|| 和 ||B|| 为向量的模(欧几里得范数)。

依据该公式,余弦距离的取值范围为 0 到 2。余弦距离为 0 表示两个向量完全同向(夹角为 0),即最大相似;而接近 2 则表示它们方向完全相反,即最大不相似。

余弦相似度 vs. 余弦距离

如上所述,余弦距离通过计算两个向量夹角的余弦来衡量不相似度,而余弦相似度则基于同一夹角的余弦来量化两个向量的相似程度。

余弦相似度的范围是 -1 到 1。相似度为 1 表示向量完全同向(夹角为 0),即最大相似;为 -1 表示方向完全相反,即最大不相似;接近 0 表示正交。

余弦距离的计算与可视化

以两个向量为例:向量 A (2,4) 与向量 B (4,2),按以下步骤计算它们的余弦距离:

  1. 计算 A 与 B 的点积:

    A · B = (2 × 4) + (4 × 2) = 8 + 8 = 16

  2. 计算 A 与 B 的模:

    ||A|| = √(2² + 4²) = √20

    ||B|| = √(4² + 2²) = √20
  1. 用点积除以模的乘积:

    (A · B) / (||A|| × ||B||) = 16 / (√20 × √20) = 16 / 20 = 0.8
  1. 计算余弦距离:

    Cosine Distance = 1 - 0.8 = 0.2

余弦距离为 0.2,在 0 到 2 的刻度上较低。这表明向量 A 与 B 在方向上相当接近。

余弦距离与余弦相似度可视化余弦距离与余弦相似度。图片由作者提供。

在该示意中:

  • 向量 A 为 (2, 4)
  • 向量 B 为 (4, 2)
  • θ 为 A 与 B 之间的夹角

余弦相似度(0.8)表示夹角 θ 的余弦。由于两个向量方向接近,夹角较小,因此相似度高、距离低(0.2)。

因为余弦距离也可定义为 1 - cos(θ),其中 cos(θ) 即为余弦相似度,这意味着:

  • 当两个向量同向(θ = 0°)时,cos(θ) = 1,故余弦距离 = 0
  • 当两个向量正交(θ = 90°)时,cos(θ) = 0,故余弦距离 = 1
  • 当两个向量反向(θ = 180°)时,cos(θ) = -1,故余弦距离 = 2

余弦距离的应用

我们来看几个重要的应用场景。

自然语言处理(NLP)

在各类自然语言处理任务中,余弦距离通过有效衡量文本表示(如 word2vec)之间的语义关系而发挥关键作用。若需快速了解这些概念,您可参考我们的教程用 Python 理解文本分类。

文档分类与相似度

在文档分类中,余弦距离通过比较文档向量之间的夹角来衡量内容相似性。每个文档都会被转化为一个向量,维度反映词语的 TF-IDF 分数。相似的文档在方向上更接近,从而具有更小的余弦距离。

聚类与语义分组

余弦距离在聚类任务(如K-means 聚类)中表现出色,即使文档未使用相同词汇,也能将语义相关的文档分到一起。它非常适合文本处理中常见的高维、稀疏数据。通过捕捉向量的方向,它能更准确地实现主题聚类。这种技术常用于无监督学习中,发掘文档集中的自然分组,例如按主题对新闻文章分组。

信息检索与搜索引擎

在信息检索中,余弦距离通过比较向量来匹配查询与文档。搜索引擎会寻找在余弦距离上最接近查询向量的文档,并将距离最小的结果优先展示。

词嵌入与词语相似性

在文档层面之外,余弦距离在 Word2Vec、GloVe 等词嵌入中同样重要,词语被表示为高维向量。嵌入捕捉语义,使得意义相近的词在向量空间中彼此接近。可用余弦距离来寻找与给定词最相似的词、支持同义词检测,甚至为更复杂的模型(如用于情感分析或机器翻译的模型)提供特征。

图像识别

在图像识别中,余弦距离用于比较从图像中提取的特征向量。无论是在人群中识别面孔,还是对自然照片进行分类,它关注的是向量方向的一致性而非大小。这种关注有助于更准确地归类图像,提高基于图像系统的准确性与有效性。

推荐系统

可以把余弦距离想象成数字世界的“撮合者”,根据用户过往偏好为其匹配电影或商品。通过比较用户与物品画像在向量空间中的方向契合度,推荐系统能够相当准确地预测您接下来可能喜欢的内容。

余弦距离的数学性质

余弦距离具有区别于其他距离度量的独特数学性质。理解这些性质有助于在不同情境下正确解释和应用余弦距离。

度量空间的性质

在数学中,度量(距离函数)用于定义集合中任意两点之间的距离。要成为真正的度量函数,需满足四个条件:

  1. 非负性:d(x, y) ≥ 0

  2. 不可分辨同一性:当且仅当 x = y 时,d(x, y) = 0

  3. 对称性:d(x, y) = d(y, x)

  4. 三角不等式:d(x, z) ≤ d(x, y) + d(y, z)

余弦距离满足前三个条件,但不总是满足三角不等式。这意味着在某些情况下,A 与 B 的余弦距离加上 B 与 C 的余弦距离,可能小于 A 与 C 的余弦距离。

尺度不变性

余弦距离的一个显著性质是尺度不变性。这意味着即使将其中一个或两个向量乘以一个标量(非零常数),两者之间的余弦距离也保持不变。形式上,对于任意非零标量 a、b 和向量 x、y:

Cosine Distance(ax, by) = Cosine Distance(x, y)

这种尺度不变性使余弦距离区别于许多其他距离度量。

在 Python 与 R 中计算余弦距离

下面演示如何在 Python 与 R 中计算余弦距离。

Python 示例

在 Python 中,我们可以使用 NumPy 计算余弦距离与余弦相似度,方法是先计算向量的点积与范数。

import numpy as np

# Define the vectors
A = np.array([2, 4])
B = np.array([4, 2])

# Calculate cosine similarity
cos_similarity = np.dot(A, B) / (np.linalg.norm(A) * np.linalg.norm(B))

# Calculate cosine distance
cos_distance = 1 - cos_similarity

print("Cosine Similarity: {:.2f}".format(cos_similarity))
print("Cosine Distance: {:.2f}".format(cos_distance))

输出:

Cosine Similarity: 0.80
Cosine Distance: 0.20

或者,我们也可以使用 SciPy 包的 cosine() 函数计算余弦距离。

import numpy as np
from scipy.spatial.distance import cosine

# Define the vectors
A = np.array([2, 4])
B = np.array([4, 2])

# Calculate cosine distance
cos_distance = cosine(A, B)  # Uses scipy's cosine for cosine distance

print("Cosine Distance: {:.2f}".format(cos_distance))

输出:

Cosine Distance: 0.20

R 示例

在 R 中,您可以用基础向量运算计算余弦相似度与余弦距离。如下所示:

# Define the vectors
A <- c(2, 4)
B <- c(4, 2)

# Calculate cosine similarity
cos_similarity <- sum(A * B) / (sqrt(sum(A^2)) * sqrt(sum(B^2)))
# Note: We can also use %*% operator for matrix multiplication. 
# %*%, when applied to two vectors, calculates the dot product. 
# For example: cos_similarity <- A %*% B / (sqrt(sum(A^2)) * sqrt(sum(B^2)))

# Calculate cosine distance
cos_distance <- 1 - cos_similarity

# Print the result
print(paste("Cosine Similarity:", cos_similarity))
print(paste("Cosine Distance:", cos_distance))

输出:

“Cosine Similarity: 0.80”
“Cosine Distance: 0.20”

在该 R 示例中,余弦相似度通过点积与范数的手动运算计算,思路与 Python 相同,且完全基于 R 的基础功能。请注意,余弦距离通过用 1 减去余弦相似度得到。

余弦相似度 vs. 欧氏距离及其他距离度量

下图在原示例基础上扩展,用不同颜色表示针对相同向量的三类距离度量:

  • 曼哈顿距离为坐标差的绝对值之和。
  • 欧氏距离为两点间的直线距离。
  • 余弦距离源自两个向量夹角的余弦。

余弦距离 vs. 欧氏距离 vs. 曼哈顿距离

余弦距离 vs. 欧氏距离 vs. 曼哈顿距离。图片由作者提供。

这些距离各自提供不同的洞见。欧氏距离与曼哈顿距离属于几何距离,会考虑向量分量的大小,因此适用于空间中的物理测量。相较之下,余弦距离聚焦于向量间的夹角,更适合理解方向性,尤其在文本分析等高维场景中表现出色。

结语

余弦距离及其互补的余弦相似度是数据科学与机器学习中的有力工具。它们为向量之间的关系提供了独到的洞察,尤其是在传统距离度量可能失效的高维空间中。

随着数据在复杂度与维度上的不断提升,诸如余弦距离之类的度量很可能在揭示隐藏模式与关系方面发挥愈发重要的作用。无论您从事自然语言处理、推荐系统,还是任何涉及高维向量空间的领域,理解并应用余弦距离都能带来有价值的洞见并提升模型表现。下一步,建议学习我们的交互式综合课程用 Python 设计机器学习工作流,其中专设一章讲解基于距离的学习与无监督工作流。

Vinod Chugani

作者

Vinod Chugani

Vinod Chugani 的职业生涯始于东京,曾任摩根大通最年轻的对冲基金销售台负责人,随后在雷曼兄弟创下个人销售纪录,之后又打造了覆盖 30 个国家的电子分销业务,营收突破 1 亿新元,随后转向数据领域。他毕业于杜克大学经济学专业,亦为 NYC Data Science Academy 校友,并在 100 多名申请者中成为Hugo Bowne-Anderson 在 Maven 开设的 “Building AI Applications” 课程的三位奖学金获得者之一。目前,他为 DataCamp、KDnuggets、Machine Learning Mastery 和 Statology 撰稿,内容涵盖从统计学到代理式 AI 等主题,并在 NYC Data Science Academy 指导数据从业者,已完成超过 1,000 场一对一辅导。

 

常见问题解答

什么是余弦相似度?

余弦相似度是一种度量,用于衡量两个向量在方向上的相似程度,而不受其大小影响。

余弦相似度的取值范围是多少?

余弦相似度的取值范围为 -1 到 1

什么是余弦相似度公式?
 

余弦相似度公式用于计算两个向量夹角的余弦,定义为向量的点积除以其模的乘积。

点积与余弦相似度有何区别?

点积是两个向量对应元素乘积之和,反映了它们的大小与方向。余弦相似度则是将点积除以两个向量模的乘积进行归一化,只关注它们在方向上的一致性。

余弦距离与余弦相似度有何不同?

余弦距离与余弦相似度是互补的度量。余弦相似度衡量两个向量的相似度,范围从 -1(完全相反)到 1(完全相同)。余弦距离则衡量两者的差异度,计算方式为 1 减去余弦相似度,范围从 0(相同向量)到 2(相反向量)。

什么是余弦距离公式?

余弦距离公式用于衡量多维空间中两个向量之间的夹角,计算方式为 1 减去两个向量夹角余弦的值。

余弦距离为 1 表示什么?

余弦距离为 1 表示两个向量相互垂直(正交),夹角为 90 度。这意味着向量在方向上没有任何相似性。就实际应用而言,在文本分析中对应完全不同的主题,在推荐系统中对应彼此无关的项目,或在机器学习的特征向量中对应不同特征。

余弦距离与角距离有何区别?

余弦距离与角距离密切相关但并不相同。余弦距离定义为 1 减去余弦相似度;而角距离是两个向量之间的夹角(弧度),计算为余弦相似度的反余弦值。角距离与余弦距离成比例,但提供了更直观的几何解释。

余弦距离与欧氏距离有何区别?

两者都衡量差异度,但余弦距离关注向量间的夹角,忽略大小;欧氏距离关注大小,衡量空间中两点之间的直线距离。

为什么余弦距离在文本分析中有用?

在文本分析中,余弦距离尤其有用,因为它关注的是词语所占的比例(向量维度),而非绝对频次。这使其能够有效比较不同长度的文档,并在不受篇幅影响的情况下识别主题相似性。

主题