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
初始化
numpy数组
point1 = np.array((1, 2, 3)) point2 = np.array((1, 1, 1))
计算欧氏距离
使用 linalg.norm() 这个函数为计算 数组对应位相减平方和再开方
dist = np.linalg.norm(point1 - point2)
打印计算欧氏距离
print(dist)
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679756302169-62300eac-1aaa-4a67-a57e-20502dc62bfd.png#averageHue=%23fafafa&clientId=u3d4d7920-4884-4&from=paste&height=1050&id=uab9be12f&originHeight=1050&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=145064&status=done&style=shadow&taskId=u42ed0266-4eab-4a91-861a-359154bb36f&title=&width=1920)
<a name="RKa93"></a>
## 2. 曼哈顿距离(Manhattan Distance)
顾名思义,在曼哈顿街区要从一个十字路口开车到另一个十字路口,驾驶距离显然不是两点间的直线距离。这个实际驾驶距离就是“曼哈顿距离”。曼哈顿距离也称为“城市街区距离”(City Block distance)。<br />![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534023682-bb30a385-f272-44da-b235-ba5705370fc1.png#averageHue=%23d1d3d0&clientId=u7e3f2a1f-856d-4&from=paste&id=u80d2987c&originHeight=425&originWidth=600&originalType=url&ratio=1&rotation=0&showTitle=false&size=344728&status=done&style=shadow&taskId=u4d1138e6-d6c6-4086-ab54-c7e411bb561&title=)
- 二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离:
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534024170-1838bfbd-1c55-4682-99d8-865aedc45931.png#averageHue=%23090807&clientId=u7e3f2a1f-856d-4&from=paste&id=u88b553b4&originHeight=21&originWidth=183&originalType=url&ratio=1&rotation=0&showTitle=false&size=3246&status=done&style=shadow&taskId=u174f5478-5567-4f94-a371-f4fed31be51&title=)
- n维空间点a(x11,x12,…,x1n)与b(x21,x22,…,x2n)的曼哈顿距离:
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534024203-e4a819ce-7a0f-4615-87fb-a9eabca825dc.png#averageHue=%23030302&clientId=u7e3f2a1f-856d-4&from=paste&id=u2d4f62c5&originHeight=62&originWidth=156&originalType=url&ratio=1&rotation=0&showTitle=false&size=3869&status=done&style=shadow&taskId=u298edcf2-0530-4d54-a1a9-b88cadf4ff5&title=)
- Python计算曼哈顿距离:
```python
# 曼哈顿距离
# 1、接受两个坐标。
# 2、对两个坐标的x值求解差的绝对值。
# 3、对y值求解差的绝对值。
# 4、讲两个绝对值相加。
def func(x,y):
return sum(map(lambda i, j : abs(i-j), x, y))
print(func([1,2],[3,4]))
3. 切比雪夫距离 (Chebyshev Distance)
国际象棋中,国王可以直行、横行、斜行,所以国王走一步可以移动到相邻8个方格中的任意一个。国王从格子(x1,y1)走到格子(x2,y2)最少需要多少步?这个距离就叫切比雪夫距离。
- 二维平面两点a(x1,y1)与b(x2,y2)间的切比雪夫距离:
- n维空间点a(x11,x12,…,x1n)与b(x21,x22,…,x2n)的切比雪夫距离:
Python计算切比雪夫距离:
# 契比雪夫距离
import numpy as np
v1 = np.array([1,2,3])
v2 = np.array([4,7,5])
print(abs(v1 - v2).max())
4. 闵可夫斯基距离(Minkowski Distance)
闵氏距离不是一种距离,而是一组距离的定义,是对多个距离度量公式的概括性的表述。
闵氏距离定义:
- 两个n维变量a(x11,x12,…,x1n)与b(x21,x22,…,x2n)间的闵可夫斯基距离定义为:
其中p是一个变参数:
当p=1时,就是曼哈顿距离;
当p=2时,就是欧氏距离;
当p→∞时,就是切比雪夫距离。
因此,根据变参数的不同,闵氏距离可以表示某一类/种的距离。
- 闵氏距离,包括曼哈顿距离、欧氏距离和切比雪夫距离都存在明显的缺点。
- e.g. 二维样本(身高[单位:cm],体重[单位:kg]),现有三个样本:a(180,50),b(190,50),c(180,60)。那么a与b的闵氏距离(无论是曼哈顿距离、欧氏距离或切比雪夫距离)等于a与c的闵氏距离。但实际上身高的10cm并不能和体重的10kg划等号。
- 闵氏距离的缺点:
- (1)将各个分量的量纲(scale),也就是“单位”相同的看待了;
- (2)未考虑各个分量的分布(期望,方差等)可能是不同的。
- Python计算闵氏距离(以p=2的欧氏距离为例):
```python
闵可夫斯基距离(Minkowski Distance)
import numpy as np from numpy import linalg as LA
a1 = np.array([-3, -5, -7, 2, 6, 4, 0, 2, 8]) a2 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) b1 = a1.reshape((3, 3)) b2 = a2.reshape((3, 3)) print(b1) print(b2) ‘’’ [[-3 -5 -7] [ 2 6 4] [ 0 2 8]] ‘’’
print(“曼哈顿距离:”,np.linalg.norm(b1-b2, ord=2))
print(“曼哈顿距离:”,np.linalg.norm(b1-b2, ord=1))
print(“切比雪夫距离:”,np.linalg.norm(b1-b2, ord=np.inf))
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679758307256-903358e7-eca6-4c76-8156-d17fc56a6ba8.png#averageHue=%23faf9f9&clientId=u3d4d7920-4884-4&from=paste&height=1050&id=ubf0cfe73&originHeight=1050&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=167323&status=done&style=shadow&taskId=u341c74fa-b957-486f-8707-230594838f4&title=&width=1920)<br />numpy本身也提供了通过闵氏距离修改p值来直接实现包括曼哈顿距离在内的多种距离计算方式
```python
def minkowski_distance(vec1, vec2, p=3):
"""
闵氏距离
当p=1时,就是曼哈顿距离
当p=2时,就是欧氏距离
当p→∞时,就是切比雪夫距离
:param vec1:
:param vec2:
:param p:
:return:
"""
# return sum([(x - y) ** p for (x, y) in zip(vec1, vec2)]) ** (1 / p)
return np.linalg.norm(vec1 - vec2, ord=p)
def cosine_distance(vec1, vec2):
"""
夹角余弦
:param vec1:
:param vec2:
:return:
"""
vec1_norm = np.linalg.norm(vec1)
vec2_norm = np.linalg.norm(vec2)
return vec1.dot(vec2) / (vec1_norm * vec2_norm)
def euclidean_distance(vec1, vec2):
"""
欧氏距离
:param vec1:
:param vec2:
:return:
"""
# return np.sqrt(np.sum(np.square(vec1 - vec2)))
# return sum([(x - y) ** 2 for (x, y) in zip(vec1, vec2)]) ** 0.5
return np.linalg.norm(vec1 - vec2, ord=2)
def manhattan_distance(vec1, vec2):
"""
曼哈顿距离
:param vec1:
:param vec2:
:return:
"""
# return np.sum(np.abs(vec1 - vec1))
return np.linalg.norm(vec1 - vec2, ord=1)
def chebyshev_distance(vec1, vec2):
"""
切比雪夫距离
:param vec1:
:param vec2:
:return:
"""
# return np.abs(vec1 - vec2).max()
return np.linalg.norm(vec1 - vec2, ord=np.inf)
def hamming_distance(vec1, vec2):
"""
汉明距离
:param vec1:
:param vec2:
:return:
"""
return np.shape(np.nonzero(vec1 - vec2)[0])[0]
def jaccard_similarity_coefficient(vec1, vec2):
"""
杰卡德距离
:param vec1:
:param vec2:
:return:
"""
return dist.pdist(np.array([vec1, vec2]), 'jaccard')
5. 标准化欧氏距离 (Standardized Euclidean Distance)
定义: 标准化欧氏距离是针对欧氏距离的缺点而作的一种改进。标准欧氏距离的思路:既然数据各维分量的分布不一样,那先将各个分量都“标准化”到均值、方差相等。假设样本集X的均值(mean)为m,标准差(standard deviation)为s,X的“标准化变量”表示为:
- 标准化欧氏距离公式:
如果将方差的倒数看成一个权重,也可称之为加权欧氏距离(Weighted Euclidean distance)。
- Python计算标准化欧氏距离(假设两个分量的标准差分别为0.5和1):
```python
5. 标准化欧氏距离 (Standardized Euclidean Distance)
import numpy as np x=np.random.random(10) y=np.random.random(10)
X=np.vstack([x,y])
sk1=0.5 sk2=1 d1=np.sqrt(((x - y) 2 /sk1).sum()) d2=np.sqrt(((x - y) 2 /sk2).sum()) print(‘d1:’,d1) print(‘d2:’,d2)
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679759223240-8d27bbd2-853d-4c21-8c4c-f6f950fa7485.png#averageHue=%23faf9f9&clientId=ubbe72a9e-b134-4&from=paste&height=1050&id=u3eb3aebb&originHeight=1050&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=166177&status=done&style=shadow&taskId=u570d3d37-fe41-4a21-a600-86f4aaa511e&title=&width=1920)
<a name="A5njt"></a>
## 6. 马氏距离(Mahalanobis Distance)
马氏距离的引出:<br />![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534025534-3e5f8ef5-6f01-47c0-bab6-f41af2d05f26.png#averageHue=%23f3f3f3&clientId=u7e3f2a1f-856d-4&from=paste&id=u6fe6d3f5&originHeight=84&originWidth=190&originalType=url&ratio=1&rotation=0&showTitle=false&size=7676&status=done&style=shadow&taskId=u7f68570d-ed84-4b22-af95-079cbe589e0&title=)<br />上图有两个正态分布的总体,它们的均值分别为a和b,但方差不一样,则图中的A点离哪个总体更近?或者说A有更大的概率属于谁?显然,A离左边的更近,A属于左边总体的概率更大,尽管A与a的欧式距离远一些。这就是马氏距离的直观解释。
- 概念:马氏距离是基于样本分布的一种距离。物理意义就是在规范化的主成分空间中的欧氏距离。所谓规范化的主成分空间就是利用主成分分析对一些数据进行主成分分解。再对所有主成分分解轴做归一化,形成新的坐标轴。由这些坐标轴张成的空间就是规范化的主成分空间。
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534025640-ba36f2f8-7cdd-4e51-a80f-26892a087d08.png#averageHue=%23f8f8ed&clientId=u7e3f2a1f-856d-4&from=paste&id=u44c5a911&originHeight=441&originWidth=450&originalType=url&ratio=1&rotation=0&showTitle=false&size=143435&status=done&style=shadow&taskId=u1bf4e1c3-612a-4abb-bb93-0d40bdc9beb&title=)
- 定义:有M个样本向量X1~Xm,协方差矩阵记为S,均值记为向量μ,则其中样本向量X到μ的马氏距离表示为:
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534025709-6c9ecb9d-83bf-4eb0-bc95-d82f28a12f58.png#averageHue=%23050404&clientId=u7e3f2a1f-856d-4&from=paste&id=ub5295dbb&originHeight=42&originWidth=207&originalType=url&ratio=1&rotation=0&showTitle=false&size=4692&status=done&style=shadow&taskId=uca46ce83-0011-49af-b4a4-a1d2d4ad86a&title=)<br />向量Xi与Xj之间的马氏距离定义为:<br />![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534026136-27d80d88-4c01-4151-b413-d614ef96a9f9.png#averageHue=%23060504&clientId=u7e3f2a1f-856d-4&from=paste&id=u587037b8&originHeight=42&originWidth=252&originalType=url&ratio=1&rotation=0&showTitle=false&size=6228&status=done&style=shadow&taskId=u2d1aa9a8-d9da-4343-87f9-c5fa7643dd3&title=)<br />若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则Xi与Xj之间的马氏距离等于他们的欧氏距离:<br />![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534026178-7ff29403-8838-465e-967e-3b4a65b6e099.png#averageHue=%23070605&clientId=u7e3f2a1f-856d-4&from=paste&id=ubf3b44f7&originHeight=42&originWidth=224&originalType=url&ratio=1&rotation=0&showTitle=false&size=5742&status=done&style=shadow&taskId=uc74a5d80-c53e-4347-95f8-1a80527ce45&title=)<br />若协方差矩阵是对角矩阵,则就是标准化欧氏距离。
- 欧式距离&马氏距离:
![](https://cdn.nlark.com/yuque/0/2023/gif/22782459/1679534026620-c46b4390-7dd2-4ea9-ae97-7a62960ce102.gif#averageHue=%23f5f3e5&clientId=u7e3f2a1f-856d-4&from=paste&id=ubb8b8f6f&originHeight=244&originWidth=400&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=shadow&taskId=u7eb65eaf-9278-4cb1-8bba-e68d4a3bc62&title=)<br />![](https://cdn.nlark.com/yuque/0/2023/gif/22782459/1679534026897-fdb9df79-ceb0-4a9a-b827-5b00da65bcdf.gif#averageHue=%23f5f3e5&clientId=u7e3f2a1f-856d-4&from=paste&id=u349b9b6b&originHeight=244&originWidth=400&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=shadow&taskId=ub8d66e5f-b645-4118-9e68-27dcddb88b8&title=)
- 马氏距离的特点:
- 量纲无关,排除变量之间的相关性的干扰;
- 马氏距离的计算是建立在总体样本的基础上的,如果拿同样的两个样本,放入两个不同的总体中,最后计算得出的两个样本间的马氏距离通常是不相同的,除非这两个总体的协方差矩阵碰巧相同;
- 计算马氏距离过程中,要求总体样本数大于样本的维数,否则得到的总体样本协方差矩阵逆矩阵不存在,这种情况下,用欧式距离计算即可。
- Python计算马氏距离:
```python
# 马氏距离(Mahalanobis Distance)
# -*- coding: utf-8 -*-
import numpy as np
x = np.random.random(10)
y = np.random.random(10)
# 马氏距离要求样本数要大于维数,否则无法求协方差矩阵
# 此处进行转置,表示10个样本,每个样本2维
X = np.vstack([x, y])
XT = X.T
# 方法二:根据scipy库求解
from scipy.spatial.distance import pdist
d2 = pdist(XT, 'mahalanobis')
print('马氏距离:',d2)
7. 余弦距离(Cosine Distance)
几何中,夹角余弦可用来衡量两个向量方向的差异;机器学习中,借用这一概念来衡量样本向量之间的差异。
- 二维空间中向量A(x1,y1)与向量B(x2,y2)的夹角余弦公式:
- 两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夹角余弦为:
即:
夹角余弦取值范围为[-1,1]。余弦越大表示两个向量的夹角越小,余弦越小表示两向量的夹角越大。当两个向量的方向重合时余弦取最大值1,当两个向量的方向完全相反余弦取最小值-1。
- Python计算夹角余弦:
```python
夹角余弦
-- coding: utf-8 --
import numpy as np from scipy.spatial.distance import pdist
x = np.random.random(10) y = np.random.random(10)
solution
dist1 = 1 - np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y)) print(‘x’, x) print(‘y’, y) print(‘余弦距离:’, dist1)
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679760065378-c6b3d321-0a67-4835-8c5f-e0156db84429.png#averageHue=%23f9f8f8&clientId=ubbe72a9e-b134-4&from=paste&height=1050&id=ub2b3f3e9&originHeight=1050&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=187127&status=done&style=shadow&taskId=u9673e823-45bf-4822-a8f6-c69a786a51b&title=&width=1920)
<a name="DeSHe"></a>
## 8. 汉明距离(Hamming Distance)
![image.png](https://cdn.nlark.com/yuque/0/2023/png/22782459/1679534027035-f85e630c-ff91-4fdb-9ffd-29ab3db39f15.png#averageHue=%23030000&clientId=u7e3f2a1f-856d-4&from=paste&id=ucc396be5&originHeight=225&originWidth=370&originalType=url&ratio=1&rotation=0&showTitle=false&size=28264&status=done&style=shadow&taskId=ua5718b33-a0f2-4034-9b68-bf5948758d5&title=)
- 定义:两个等长字符串s1与s2的汉明距离为:将其中一个变为另外一个所需要作的最小字符替换次数。例如:
- 汉明重量:是字符串相对于同样长度的零字符串的汉明距离,也就是说,它是字符串中非零的元素个数:对于二进制字符串来说,就是 1 的个数,所以 11101 的汉明重量是 4。因此,如果向量空间中的元素a和b之间的汉明距离等于它们汉明重量的差a-b。
- 应用:汉明重量分析在包括信息论、编码理论、密码学等领域都有应用。比如在信息编码过程中,为了增强容错性,应使得编码间的最小汉明距离尽可能大。但是,如果要比较两个不同长度的字符串,不仅要进行替换,而且要进行插入与删除的运算,在这种场合下,通常使用更加复杂的编辑距离等算法。
- Python计算汉明距离(Matlab中2个向量之间的汉明距离的定义为2个向量不同的分量所占的百分比):
```python
# 汉明距离(Hamming distance)
# -*- coding: utf-8 -*-
from numpy import *
matV = mat([[1,1,0,1,0,1,0,0,1],[0,1,1,0,0,0,1,1,1]])
smstr = nonzero(matV[0]-matV[1])
print(shape(smstr[0])[0])
import numpy as np
x=np.random.random(10)>0.5
y=np.random.random(10)>0.5
x=np.asarray(x,np.int32)
y=np.asarray(y,np.int32)
d1=np.mean(x!=y)
print('汉明距离:', d1)