关于距离这个概念,在我们很小的时候就开始接触了,不过我们最长提到的距离一般是欧式距离。它用来衡量两个点之间的远近程度,其实从另一个角度出发距离也可以描述点之间的相似度因此有很多的聚类算法都是基于距离进行计算的。为什么要有这么多距离的定义呢?其实不同定义的距离,代表了不同的含义有不同的使用场景,了解不同距离的定义可以帮助我们在使用时找到最适合场景的那个。
曼哈顿距离(Manhattan Distance)是由十九世纪的赫尔曼·闵可夫斯基所创词汇 ,是种使用在几何度量空间的几何学用语,用以标明两个点在标准坐标系上的绝对轴距总和。
曼哈顿这个城市的街道很有特点,因为它方方正正的,就像坐标轴上的坐标格网一样。在曼哈顿街区要从一个十字路口开车到另一个十字路口,驾驶距离显然不是两点间的直线距离。这个实际驾驶距离就是“曼哈顿距离”。曼哈顿距离也称为“城市街区距离”(City Block distance)。
计算公式
欧几里得度量(euclidean metric)也称欧氏距离,是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。
切比雪夫距离是各坐标的坐标差值中的最大值。
简介
比如在棋类游戏中,国王一步可以移动到相邻的8个方格中的任意一个,那么从格子(x1,y1)走到格子(x2,y2)最少需要多少步?会发现最少步数总是max( | x2-x1 | , | y2-y1 | ) 步 。
计算公式
闵氏距离不是一种距离,而是一组距离的定义,是对多个距离度量公式的概括性的表述。
计算公式
其中p是一个参数
p = 1 时,就是曼哈顿距离
p = 2 时,就是欧氏距离
p = ∞ 时,就是切比雪夫距离
马氏距离(Mahalanobis distance)是由印度统计学家马哈拉诺比斯(P. C. Mahalanobis)提出的,表示点与一个分布之间的距离。它是一种有效的计算两个未知样本集的相似度的方法。与欧氏距离不同的是,它考虑到各种特性之间的联系(例如:一条关于身高的信息会带来一条关于体重的信息,因为两者是有关联的),并且是尺度无关的(scale-invariant),即独立于测量尺度。对于一个均值为μ,协方差矩阵为Σ的多变量向量,其马氏距离为sqrt( (x-μ)'Σ^(-1)(x-μ) )。
计算公式
可根据下图进行理解
余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。
汉明距离是使用在数据传输差错控制编码里面的,汉明距离是一个概念,它表示两个(相同长度)字符串对应位置的不同字符的数量,我们以d(x,y)表示两个字x,y之间的汉明距离。对两个字符串进行异或运算,并统计结果为1的个数,那么这个数就是汉明距离。(在机组原理中关于机器码纠错的地方有提到)
计算公式
d(x,y)=∑x[i]⊕y[i]
import numpy as np
import pandas as pd
from scipy import spatial
class Distance(object):
@staticmethod
def CalEuclideanDistance(vec1, vec2):
"""
## 计算欧式距离
"""
return np.sqrt(np.sum(np.square(vec1 - vec2)))
@staticmethod
def ManhattanDistance(vec1, vec2):
"""
## 计算曼哈顿距离
"""
return np.sum(np.abs(vec1 - vec2))
@staticmethod
def ChebyshevDistance(vec1, vec2):
"""
## 计算切比雪夫距离
"""
return np.max(np.abs(vec1 - vec2))
@staticmethod
def MinkowskiDistance(vec1, vec2,p=3):
"""
## 闵可夫斯基距离
"""
return np.power(np.sum(np.power(np.abs(vec1 - vec2), p)), 1/p)
@staticmethod
def MahalanobisDistance(X,vec1, vec2):
"""
## 计算马氏距离
"""
# 协方差矩阵
D = np.cov(X.T)
# 协方差矩阵的逆矩阵
invD = np.linalg.inv(D)
tp = vec1 - vec2
return np.sqrt(np.dot(np.dot(tp.T, invD), tp))
@staticmethod
def CosineDistance(vec1, vec2):
"""
## 计算余弦距离
"""
return 1 - spatial.distance.cosine(vec1, vec2)
@staticmethod
def HammingDistance(vec1, vec2):
"""
## 计算Hamming距离
"""
assert vec1.shape == vec2.shape, "vec1 and vec2 must have the same shape"
return np.sum(vec1 != vec2)
if __name__ == "__main__":
a = np.array([1,2])
b = np.array([2,2])
print(Distance.CalEuclideanDistance(a,b))
pass