一、欧氏距离(Euclidean Distance)
二、曼哈顿距离(Manhattan Distance)
三、切比雪夫距离 (Chebyshev Distance)
四、闵可夫斯基距离(Minkowski Distance)
五、标准化欧氏距离 (Standardized Euclidean Distance)
六、马氏距离(Mahalanobis Distance)
1 欧氏距离(Euclidean Distance)
欧氏距离是最容易直观理解的距离度量方法,我们中小学接触到的两个点在空间中的距离一般都是指欧氏距离。
• 二维平面上点a(x1,y1)与b(x2,y2)间的欧氏距离:
• 三维空间点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:
• n维空间点a(x11,x12,…,x1n)与b(x21,x22,…,x2n)间的欧氏距离(两个n维向量):
•也可以用表示成向量运的形式:
代码实现:
import numpy as np
# 生成10个0-1之间的随机数
x = np.random.random(10)
y = np.random.random(10)
# 方法一:根据公式求解
d1 = np.sqrt(np.sum(np.square(x-y)))
print(d1)
# 方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X = np.vstack([x, y])
d2 = pdist(X)
print(d2)
# result
# 1.0605069560684677
# [1.06050696]
曼哈顿距离(Manhattan Distance)
顾名思义,在曼哈顿街区要从一个十字路口开车到另一个十字路口,驾驶距离显然不是两点间的直线距离。这个实际驾驶距离就是“曼哈顿距离”。曼哈顿距离也称为“城市街区距离”(City Block distance)。
•二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离:
•n维空间点a(x11,x12,…,x1n)与b(x21,x22,…,x2n)的曼哈顿距离:
代码实现:
import numpy as np
x = np.random.random(10)
y = np.random.random(10)
# 方法一:根据公式求解
d1 = np.sum(np.abs(x-y))
print(d1)
#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X = np.vstack([x,y])
d2 = pdist(X, 'cityblock')
print(d2)
# result
# 3.2596277819295145
# [3.25962778]
切比雪夫距离 (Chebyshev Distance)
国际象棋中,国王可以直行、横行、斜行,所以国王走一步可以移动到相邻8个方格中的任意一个。国王从格子(x1,y1)走到格子(x2,y2)最少需要多少步?这个距离就叫切比雪夫距离。
•二维平面两点a(x1,y1)与b(x2,y2)间的切比雪夫距离:
•n维空间点a(x11,x12,…,x1n)与b(x21,x22,…,x2n)的切比雪夫距离:
代码实现:
import numpy as np
x = np.random.random(10)
y = np.random.random(10)
# 方法一:根据公式求解
d1 = np.max(np.abs(x - y))
print(d1)
# 方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X = np.vstack([x, y])
d2 = pdist(X, 'chebyshev')
print(d2)
# resut:
# 0.7426177760349336
# [0.74261778]
闵可夫斯基距离(Minkowski Distance)
闵可夫斯基距离(Minkowski distance)是衡量数值点之间距离的一种非常常见的方法,假设数值点 P 和 Q 坐标如下:
那么,闵可夫斯基距离定义为:
该距离最常用的 p 是 2 和 1, 前者是欧几里得距离(Euclidean distance),后者是曼哈顿距离(Manhattan distance)。假设在曼哈顿街区乘坐出租车从 P 点到 Q 点,白色表示高楼大厦,灰色表示街道:
绿色的斜线表示欧几里得距离,在现实中是不可能的。其他三条折线表示了曼哈顿距离,这三条折线的长度是相等的。
当 p 趋近于无穷大时,闵可夫斯基距离转化成切比雪夫距离(Chebyshev distance):
代码实现:
import numpy as np
x = np.random.random(10)
y = np.random.random(10)
# 方法一:根据公式求解,p=2
d1 = np.sqrt(np.sum(np.square(x - y)))
print(d1)
# 方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X = np.vstack([x, y])
d2 = pdist(X, 'minkowski', p=2)
print(d2)
# reslut:
# 0.9092358349862538
# [0.90923583]
标准化欧氏距离 (Standardized Euclidean Distance)
标准化欧氏距离是针对简单欧氏距离的缺点而作的一种改进方案。标准欧氏距离的思路:既然数据各维分量的分布不一样,那我先将各个分量都“标准化”到均值、方差相等吧。均值和方差标准化到多少呢?这里先复习点统计学知识吧,假设样本集X的均值(mean)为m,标准差(standard deviation)为s,那么X的“标准化变量”表示为:
标准差公式
标准化后的值 = ( 标准化前的值 - 分量的均值 ) /分量的标准差
经过简单的推导就可以得到两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的标准化欧氏距离的公式:
如果将方差的倒数看成是一个权重,这个公式可以看成是一种加权欧氏距离(Weighted Euclidean distance)。
代码实现:
import numpy as np
x = np.random.random(10)
y = np.random.random(10)
X = np.vstack([x, y]) # 垂直(按照行顺序)的把数组给堆叠起来
# 方法一:根据公式求解
sk = np.var(X, axis=0, ddof=1) # var:表示方差
d1 = np.sqrt(((x - y) ** 2 / sk).sum())
print(d1)
# 方法二:根据scipy库求解
from scipy.spatial.distance import pdist
d2 = pdist(X, 'seuclidean')
print(d2)
# result
# 4.47213595499958
# [4.47213595]
有M个样本向量X1~Xm,协方差矩阵记为S,均值记为向量μ,则其中样本向量X到u的马氏距离表示为:
而其中向量Xi与Xj之间的马氏距离定义为:
若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则公式就成了:
也就是欧氏距离了。
若协方差矩阵是对角矩阵,公式变成了标准化欧氏距离。
代码实现:
import numpy as np
x = np.random.random(10)
y = np.random.random(10)
# 马氏距离要求样本数要大于维数,否则无法求协方差矩阵
# 此处进行转置,表示10个样本,每个样本2维
X = np.vstack([x, y])
XT = X.T
# 方法一:根据公式求解
S = np.cov(X) # 两个维度之间协方差矩阵
SI = np.linalg.inv(S) # 协方差矩阵的逆矩阵
# 马氏距离计算两个样本之间的距离,此处共有10个样本,两两组合,共有45个距离。
n = XT.shape[0]
d1 = []
for i in range(0, n):
for j in range(i + 1, n):
delta = XT[i] - XT[j]
d = np.sqrt(np.dot(np.dot(delta, SI), delta.T)) # dot()返回的是两个数组的点积
d1.append(d)
print(d1)
# 方法二:根据scipy库求解
from scipy.spatial.distance import pdist
d2 = pdist(XT, 'mahalanobis')
print(d2)