机器学习中不同的距离定义汇总(一:空间中点的距离)
- 机器学习中不同的距离定义汇总(一:空间中点的距离)
- 欧几里得距离(Euclidean Distance)
- 曼哈顿距离(Manhattan Distance)
- 闵可夫斯基距离/明氏距离(Minkowski Distance)
- 切比雪夫距离(Chebyshev Distance)
- 标准化的欧几里得距离(Standardized Euclidean Distance)
- 马氏距离(Mahalanobis Distance)
- 兰氏距离(Lance and Williams Distance)/ 堪培拉距离(Canberra Distance)
- 余弦距离(Cosine Distance)
- 测地距离(Geodesic Distance)
- 布雷柯蒂斯距离(Bray Curtis Distance)
- 参考资料
本文主要参考了此博客和文末列出的参考内容
图片来源:csdn
欧几里得距离(Euclidean Distance)
- 欧式空间中的直线距离
- 欧几里得范数
n维空间中的距离:
\[ d(x,y)=\sqrt{\sum_{i=1}^n(x_i-y_i)^2}=\sqrt{(x_1-y_1)^2+(x_2-y_2)^2+\dots+(x_n-y_n)^2} \]
2维空间中:
\[ d(x,y)=\sqrt{(x_1-y_1)^2+(x_2-y_2)^2} \]
python实现:
def EuclideanDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
return np.sqrt(np.sum(np.square(x-y)))
曼哈顿距离(Manhattan Distance)
- 两个点在坐标系上绝对轴距总和
- 曼哈顿距离的命名原因是从规划为方型建筑区块的城市(如曼哈顿)间,最短的行车路径而来(忽略曼哈顿的单向车道以及只存在于3、14大道的斜向车道)。任何往东三区块、往北六区块的的路径一定最少要走九区块,没有其他捷径。
- 在计程车几何学中,一个圆是由从圆心向各个固定曼哈顿距离标示出来的点围成的区域,因此这种圆其实就是旋转了45度的正方形。如果有一群圆,且任两圆皆相交,则整群圆必在某点相交;因此曼哈顿距离会形成一个超凸度量空间。对一个半径为r 的圆来说,这个正方形的圆每边长√2r。此’“圆”的半径r对切比雪夫距离(L∞空间)的二维平面来说,也是一个对座标轴来说边长为2r的正方形,因此二维切比雪夫距离可视为等同于旋转且放大过的二维曼哈顿距离。然而这种介于L1与L∞的相等关系并不能延伸到更高的维度。

从曼哈顿街区的一点到另一点:

二维空间: $\( d(x,y)=|x_1-y_1| + |x_2-y_2| \)$
n维空间: $\( d(x,y)=\sum_{i=1}^n{|x_i-y_1|} \)$
python实现:
def ManhattanDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
return np.sum(np.abs(x-y))
闵可夫斯基距离/明氏距离(Minkowski Distance)
- 闵可夫斯基距离不是一种距离,而是一组距离的定义
- 欧氏距离和曼哈顿距离的一种推广
- p=2即为欧氏距离,而p=1时则为曼哈顿距离
- 当p取无穷时的极限情况下,可以得到切比雪夫距离
n维空间:
\[ d(x,y)=(\sum_{i=1}^n(x_i-y_i)^p)^{\frac{1}{p}} \]
python实现:
def MinkowskiDistance(x, y, p):
import math
import numpy as np
zipped_coordinate = zip(x, y)
return math.pow(np.sum([math.pow(np.abs(i[0]-i[1]), p) for i in zipped_coordinate]), 1/p)
切比雪夫距离(Chebyshev Distance)
- 切比雪夫距离(Chebyshev distance)或是L∞度量是向量空间中的一种度量,二个点之间的距离定义为其各座标数值差的最大值
- 切比雪夫距离是由一致范数(或称为上确界范数)所衍生的度量,也是超凸度量的一种。
- 若将国际象棋棋盘放在二维直角座标系中,格子的边长定义为1,座标的x轴及y轴和棋盘方格平行,原点恰落在某一格的中心点,则王从一个位置走到其他位置需要的步数恰为二个位置的切比雪夫距离,因此切比雪夫距离也称为棋盘距离
- 例如位置F6和位置E2的切比雪夫距离为4。任何一个不在棋盘边缘的位置,和周围八个位置的切比雪夫距离都是1。

公式: $\( D(x,y)=\max(|x_i-y_i|) \)$
python实现:
def ChebyshevDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
return np.max(np.abs(x-y))
标准化的欧几里得距离(Standardized Euclidean Distance)
- 对简单欧几里得距离的缺点而作的一种改进方案
- 如果将方差的倒数看成是一个权重,这个公式可以看成是一种加权欧氏距离(Weighted Euclidean Distance)。
将各个分量都“标准化”到均值、方差相等的区间:
\[ X^*=\frac{X-m}{s} \]
其中,\(X^*\)为标准化后的值,\(X\)为原值,\(m\)为分量的均值,\(s\)为分量的标准差。
所以,n维空间中标准化欧几里得距离为:
\[ d(x,y)=\sqrt{\sum_{i=1}^n(\frac{x_i-y_i}{s_i})^2} \]
python代码:
def StandardizedEuclideanDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
X = np.vstack([x,y])
sigma = np.var(X, axis=0, ddof=1)
return np.sqrt(((x - y) ** 2 /sigma).sum())
上述代码中需要避免某个分量取值一致,即该分量sigma=0
马氏距离(Mahalanobis Distance)
数据的协方差距离,协方差矩阵必须满秩
计算两个未知样本集的相似度
考虑到各种特性之间的联系并且是尺度无关
若协方差矩阵为单位矩阵,那么马氏距离就简化为欧几里得距离(Euclidean Distance)。若协方差矩阵为对角阵,则其转为标准化的欧几里得距离(Standardized Euclidean Distance)。
不能处理非线性流形(manifold)上的问题
两点之间的马氏距离与原始数据的测量单位无关(不受量纲的影响)
标准化数据和中心化数据(即原始数据与均值之差)计算出的二点之间的马氏距离相同
可以排除变量之间的相关性的干扰
满足距离的四个基本公理:非负性、自反性、对称性和三角不等式
缺点是夸大了变化微小的变量的作用
考虑下面这张图,椭圆表示等高线,从欧几里得的距离来算,绿黑距离大于红黑距离,但是从马氏距离,结果恰好相反:

马氏距离实际上是利用 Cholesky transformation 来消除不同维度之间的相关性和尺度不同的性质。下图是一个二元变量数据的散点图:

当我们将坐标轴拿掉,如下图:

根据数据本身的提示信息来引入新的坐标轴:坐标的原点在这些点的中央(根据点的平均值算得)。第一个坐标轴(下图中蓝色的线)沿着数据点的“脊椎”,并向两端延伸,定义为使得数据方差最大的方向。第二个坐标轴(下图红色的线)会与第一个坐标轴垂直并向两端延伸。如果数据的维度超过了两维,那就选择使得数据方差是第二个最大的方向,以此类推。

我们需要一个比例尺度。沿着每一个坐标轴的标准差来定义一个单位长度。使用“68-95-99.7法则”更容易找到合理的单位。(大约68%的点需要在离原点一个单位长度的范围内;大约95%的点需要在离原点两个单位的长度范围内;99.7的点需要在3个单位程度范围内。)为了以示参考,如下图:

由于每个轴上的单位长度不相等,所以上图中距离原点一个单位的形成的轨迹并不是一个圆形。为了更好的呈现图表,我们将图片进行旋转。同时,并让每个轴方向上的单位长度相同:

上面就是从散点图中构建坐标系统的过程,为的是方便进行测量。说明:
沿着新坐标轴的单位向量是协方差矩阵的特征向量。注意到没有变形的椭圆,变成圆形后沿着特征向量用标准差(协方差的平方根)将距离长度分割。 坐标轴扩展的量是协方差矩阵的逆的特征值(平方根),同理的,坐标轴缩小的量是协方差矩阵的特征值。所以,点越分散,需要的将椭圆转成圆的缩小量就越多。 尽管上述的操作可以用到任何数据上,但是对于多元正态分布的数据表现更好。在其他情况下,点的平均值或许不能很好的表示数据的中心,或者数据的“脊椎”(数据的大致趋势方向)不能用变量作为概率分布测度来准确的确定。 原始坐标系的平移、旋转,以及坐标轴的伸缩一起形成了仿射变换(affine transformation)。除了最开始的平移之外,其余的变换都是基底变换,从原始的一个变为新的一个。 在新的坐标系中,多元正态分布像是标准正太分布,当将变量投影到任何一条穿过原点的坐标轴上。特别是,在每一个新的坐标轴上,它就是标准正态分布。从这点出发来看,多元正态分布彼此之实质性的差异就在于它们的维度。
单个数据点的马氏距离:
\[ D_M(x)=\sqrt{\left.(x-\mu)^{T} \Sigma^{-1}(x-\mu)\right)} \]
数据点x, y之间的马氏距离: $\( D_M(x, y)=\sqrt{\left.(x-y)^{T} \Sigma^{-1}(x-y)\right)} \)$
马氏距离是旋转变换缩放之后的欧式距离,所以马氏距离的计算公式为:
\[ \begin{aligned} &D_{M}=\left(\frac{f_{1}-\mu_{F_{1}}}{\sqrt{\lambda_{1}}}\right)^{2}+\left(\frac{f_{2}-\mu_{F_{2}}}{\sqrt{\lambda_{2}}}\right)^{2}+\ldots+\left(\frac{f_{m}-\mu_{F_{m}}}{\sqrt{\lambda_{m}}}\right)^{2}\\ \end{aligned} \]

\[ \begin{aligned} &=\left(f-\mu_{F}\right)^{T}\left(U^{T} \Sigma_{X} U\right)^{-1}\left(f-\mu_{F}\right)\\ &=\left(x-\mu_{X}\right)^{T} U U^{T} \Sigma_{X}^{-1} U U^{T}\left(x-\mu_{X}\right)\\ &=\left(x-\mu_{X}\right)^{T} \Sigma_{X}^{-1}\left(x-\mu_{X}\right) \end{aligned} \]
python实现:
def MahalanobisDistance(x, y):
'''
马氏居立中的(x,y)与欧几里得距离的(x,y)不同,欧几里得距离中的(x,y)指2个样本,每个样本的维数为x或y的维数;这里的(x,y)指向量是2维的,样本个数为x或y的维数,若要计算n维变量间的马氏距离则需要改变输入的参数如(x,y,z)为3维变量。
'''
import numpy as np
x = np.array(x)
y = np.array(y)
X = np.vstack([x,y])
X_T = X.T
sigma = np.cov(X)
sigma_inverse = np.linalg.inv(sigma)
d1=[]
for i in range(0, X_T.shape[0]):
for j in range(i+1, X_T.shape[0]):
delta = X_T[i] - X_T[j]
d = np.sqrt(np.dot(np.dot(delta,sigma_inverse),delta.T))
d1.append(d)
return d1
兰氏距离(Lance and Williams Distance)/ 堪培拉距离(Canberra Distance)
- 曼哈顿距离(Manhattan Distance)的加权版本
- 对于接近于0(大于等于0)的值的变化非常敏感
- 与马氏距离一样,兰氏距离对数据的量纲不敏感
- 假定变量之间相互独立,没有考虑变量之间的相关性
n维空间:
\[ d(x, y)=\sum_{i=1}^{n} \frac{\left|x_{i}-y_{i}\right|}{\left|x_{i}\right|+\left|y_{i}\right|} \]
python实现:
def CanberraDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
n = len(x)
d = 0
for i in range(len(x)):
if x[i] == 0 and y[i] == 0:
d += 0
else:
d += abs(x[i] - y[i]) / (abs(x[i]) + abs(y[i]))
return d
余弦距离(Cosine Distance)
- 相比距离度量,余弦相似度更加注重两个向量在方向上的差异
- 余弦相似度与向量的幅值无关,只与向量的方向相关
\[ \cos (x, y)=\frac{x \cdot y}{|x| \cdot|y|}=\frac{\sum_{i=1}^{n} x_{i} y_{i}}{\sqrt{\sum_{i=1}^{n} x_{i}^{2}} \sqrt{\sum_{i=1}^{n} y_{i}^{2}}} \]
python实现:
def CosineDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
return np.dot(x,y)/(np.linalg.norm(x)*np.linalg.norm(y))
测地距离(Geodesic Distance)
- 球体表面两点之间的最短距离
在三维网格中,Geodesic Distance 就是两顶点沿网格表面最短路径的距离。如下图所示,标注出的绿色线段长度就是顶点 vs 到顶点 vt 的 Geodesic Distance。

布雷柯蒂斯距离(Bray Curtis Distance)
布雷柯蒂斯距离(Bray Curtis Distance)主要用于生态学和环境科学,计算坐标之间的距离。该距离取值在[ 0 , 1 ] [0,1][0,1]之间,也可以用来计算样本之间的差异。n nn维空间中的布雷柯蒂斯距离为:
\[ d(x, y)=\frac{\sum_{i=1}^{n}\left|x_{i}-y_{i}\right|}{\sum_{i=1}^{n} x_{i}+\sum_{i=1}^{n} y_{i}} \]
python实现:
def BrayCurtisDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
return np.sum(np.abs(x-y))/(np.sum(x)+np.sum(y))
参考资料
- https://blog.csdn.net/hy592070616/article/details/121723169
- https://www.cnblogs.com/AlvinSui/p/8931074.html
- https://zh.wikipedia.org/zh-hans/%E6%9B%BC%E5%93%88%E9%A0%93%E8%B7%9D%E9%9B%A2
- https://zh.wikipedia.org/wiki/%E6%98%8E%E6%B0%8F%E8%B7%9D%E7%A6%BB
- https://zh.wikipedia.org/wiki/%E5%88%87%E6%AF%94%E9%9B%AA%E5%A4%AB%E8%B7%9D%E7%A6%BB
- http://blog.sina.com.cn/s/blog_407e5c1c0102vxyp.html
- https://zhuanlan.zhihu.com/p/46626607
- https://www.jianshu.com/p/ba9716d7ece8
- https://zhuanlan.zhihu.com/p/342861735
- https://www.cxyzjd.com/article/Will_Ch/111185619
- https://blog.csdn.net/hy592070616/article/details/122272378
- https://blog.csdn.net/hy592070616/article/details/121461909
- https://blog.csdn.net/hy592070616/article/details/121569933
- https://blog.csdn.net/hy592070616/article/details/121723106
- https://blog.csdn.net/hy592070616/article/details/121728668
- https://blog.csdn.net/hy592070616/article/details/121730738
- https://blog.csdn.net/hy592070616/article/details/122268144
- https://blog.csdn.net/hy592070616/article/details/122271656
- https://blog.csdn.net/hy592070616/article/details/122271927
- https://blog.csdn.net/hy592070616/article/details/122272108
- https://blog.csdn.net/hy592070616/article/details/122272378