机器学习领域 几种距离度量方法【1】

一、欧氏距离(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,均值记为向量μ,则其中样本向量Xu的马氏距离表示为

而其中向量XiXj之间的马氏距离定义为

若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则公式就成了:

也就是欧氏距离了

协方差矩阵是对角矩阵,公式变成了标准化欧氏距离。

代码实现:

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)

 

猜你喜欢

转载自blog.csdn.net/yeler082/article/details/85801823