谈谈距离度量方式:欧氏距离与余弦距离

本文探讨了在机器学习中,如何根据任务需求选择欧氏距离还是余弦相似度,强调了它们的适用场景、优缺点,并指出归一化后的等价关系。欧氏用于低维或大小重要的场合,余弦适合高维和关注方向的场景,且两者在归一化向量下的联系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前因

在机器学习/深度学习的很多任务中,我们通常会面临着两个样本之间相似度的比较。通常常用的两种度量方式为欧氏距离与余弦距离,那么在什么时候用欧氏距离?什么时候用余弦相似度?他们之间的联系与区别在哪里呢?

探索

在机器学习当中,通常以一组向量来表示样本

如上图所示,欧式距离是通过勾股定理来计算两个向量之间的距离:

余弦相似度是计算两个向量之间夹角的余弦值:

通常用1-D(x,y)来表示余弦距离。

分析:

首先谈谈区别,欧氏距离的范围是不确定的(没有经过归一化),得到的值可能很大(最小为0),值越大表示样本之间越不相似,直观上的理解就是度量两个向量点之间的绝对距离(用一根绳子去连接两个点,这根绳子的长度就是欧式距离)。而余弦距离不考虑向量大小,只关注角度关系,取值范围[-1,1],当两个向量方向完全一致时取1,完全相反时取-1。可以这么说,欧氏距离体现数值上的绝对差异,而余弦距离体现方向上的相对差异。

接下来谈谈两者的缺点与应用场景,欧氏距离尝尝收到维度诅咒,当研究对象的维度很高时(通常深度网络输出一个高维向量)会受到影响,导致范围不固定,含义也比较模糊。余弦距离虽然没有受到维度诅咒,但其并没有考虑到向量的大小,只考虑了方向。
所以,应用何种距离度量函数取决于具体的应用场景:当数据维度较低,或者向量的大小很重要时采用欧氏距离,比如在分析房价时,考虑小区绿化面积与房屋面积为特征,两个样本(1000,100)与(500,50),若采用余弦距离会认为这两个房子价格较近,这肯定是不合理的。当数据维度较高(很难判断各维度之间的具体含义),或者为稀疏向量,又或者是更关于两者的相对差异时采用余弦距离:比如分析用户行为来构建推荐系统,A用户购买向量为(1,0),B用户购买向量为(0,1)。

这里的应用限制不一定对,具体情况具体分析。比如,当维度高的时候,欧氏距离也可能效果更好。

最后谈谈它们的联系,如果我们将向量归一化后执行欧氏距离,其与余弦距离等价。公式证明见下:

来自参考链接[1]

这里通过画图可以更简单地理解,当向量执行归一化后变为单位向量,欧式距离就是求单位向量之间的距离,余弦距离求夹角的余弦值:

其中两个向量用红线表示,紫线表示它们之间的欧氏距离,cosΘ为余弦距离,由余弦定理可知,两者存在反比关系。

更多的度量方式见参考链接2

扩展

余弦距离是否是严格意义上的距离?

距离的定义:在一个集合中,如果每一对元素均可唯一确定一个实数,使得三条距离公理(正定性,对称性,三角不等式)成立,则该实数可称为这对元素之间的距离。

这里简单提一下,后续有时间再补充。余弦距离满足正定性和对称性,但是不满足三角不等式,因此它并不是严格 定义的距离

参考

[1] 数据科学中常见的9种距离度量方法,内含欧氏距离、切比雪夫距离等
https://zhuanlan.zhihu.com/p/350744027
[2] 欧氏距离和余弦相似度的区别是什么?
https://www.zhihu.com/question/19640394/answer/207795500

### 关于2024年华为ODEPython相关真题 针对2024年华为ODE中的Python编程部分,确实存在一些特定类型的目。其中一道典型目涉及正则表达式的应用[^2]。 #### 正则表达式替换问描述 给定一段字符串以及若干组模式串和替换成的目标串,要求按照每组模式串依次对字符串进行匹配并替换操作,最终返回处理后的字符串。 #### 解决方案概述 此问主要考察对于Python内置`re`模块的理解与运用能力。具体实现如下: ```python import re def regex_replace(text, patterns): result = text for pattern, replacement in patterns: result = re.sub(pattern, replacement, result) return result ``` 上述函数接收两个参数:一个是待处理的始文本;另一个是由多个元组组成的列表,每个元组包含一个正则表达式模式及其对应的替代字符序列。该方法遍历所有模式并对输入文本执行相应的替换动作。 为了更好地理解如何使用这个功能,下面给出几个具体的例子来展示其工作理: ```python if __name__ == "__main__": test_cases = [ ("hello world", [("world", "universe")]), ("abc123xyz789", [(r"\d+", "#"), (r"[a-z]", "*")]) ] for case in test_cases: print(f"Original Text: {case[0]}") print(f"After Replacement: {regex_replace(*case)}\n") ``` 这段代码会输出经过不同规则转换之后的结果,有助于加深对应者关于正则表达式语法的记忆,并提高解决实际问的能力。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值