简介:个人学习分享,如有错误,欢迎批评指正。
前言:距离的作用
数据聚类:距离度量在聚类算法(如K-means、层次聚类)中用于衡量数据点之间的相似性或差异性,帮助确定聚类的中心和边界。分类问题:在K最近邻(K-NN)等分类算法中,距离度量用于计算待分类点与已知类别点的距离,以确定待分类点的类别。降维:在多维标度法(MDS)和主成分分析(PCA)等降维技术中,距离度量用于保留数据点之间的相对距离,帮助在低维空间中重构高维数据。异常检测:距离度量可用于检测数据中的异常点,通过计算数据点到中心或其他点的距离来判断其是否为异常值。信息检索:在文本检索和推荐系统中,距离度量用于计算查询向量与文档向量之间的相似度,以返回最相关的文档或推荐内容。图像处理:在图像分类、分割等任务中,距离度量用于衡量图像特征向量之间的相似性,帮助识别和处理图像内容。
通过合理选择和应用距离度量,可以提高数据分析和机器学习任务的效果和准确性。
一、 欧氏距离(EuclideanDistance)
1.定义: 欧几里得度量(euclidean metric)(也称欧氏距离)是最常见的距离度量方法之一,表示在欧几里得空间中两点之间的直线距离。它基于勾股定理计算,是一种自然且直观的度量方式。 2.计算公式: 在二维空间中,两个点
(
x
1
,
y
1
)
(x_1, y_1)
(x1,y1) 和
(
x
2
,
y
2
)
(x_2, y_2)
(x2,y2) 之间的欧氏距离为:
d
=
(
x
2
−
x
1
)
2
+
(
y
2
−
y
1
)
2
d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}
d=(x2−x1)2+(y2−y1)2
在 n 维空间中,两个点
x
=
(
x
1
,
x
2
,
…
,
x
n
)
\mathbf{x} = (x_1, x_2, \ldots, x_n)
x=(x1,x2,…,xn) 和
y
=
(
y
1
,
y
2
,
…
,
y
n
)
\mathbf{y} = (y_1, y_2, \ldots, y_n)
y=(y1,y2,…,yn) 之间的距离为:
d
=
∑
i
=
1
n
(
x
i
−
y
i
)
2
d = \sqrt{\sum_{i=1}^{n} (x_i - y_i)^2}
d=i=1∑n(xi−yi)2
3.python代码
不调包
import numpy as np
def euclidean_distance(point1, point2):
"""
计算两个点之间的欧氏距离
:param point1: 第一个点的坐标,列表或元组形式
:param point2: 第二个点的坐标,列表或元组形式
:return: 两点之间的欧氏距离
"""
# 将输入点转换为numpy数组
point1 = np.array(point1)
point2 = np.array(point2)
# 计算各维度上的差值
diff = point1 - point2
# 对差值进行平方
sq_diff = diff ** 2
# 将所有平方和相加
sum_sq_diff = np.sum(sq_diff)
# 对总和开平方,得到欧氏距离
distance = np.sqrt(sum_sq_diff)
return distance
# 示例使用
pointA = (1, 2)
pointB = (4, 6)
distance = euclidean_distance(pointA, pointB)
print(f"Point A 和 Point B 之间的欧氏距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
pointA = (1, 2)
pointB = (4, 6)
# 使用scipy的euclidean函数
distance = distance.euclidean(pointA, pointB)
print(f"Point A 和 Point B 之间的欧氏距离是: {distance}")
使用Numpy库
import numpy as np
pointA = np.array([1, 2])
pointB = np.array([4, 6])
# 计算欧氏距离
distance = np.linalg.norm(pointA - pointB)
print(f"Point A 和 Point B 之间的欧氏距离是: {distance}")
4.优缺点 优点
直观且计算简单: 欧氏距离基于勾股定理,计算过程简单明了,非常直观,易于理解和实现。适用性广泛: 适用于许多实际问题,如分类、聚类、回归等,特别是在低维空间中的效果较好。几何解释清晰:欧氏距离可以直接解释为两点之间的直线距离,具有明确的几何意义。
缺点
对尺度敏感: 如果数据的不同维度具有不同的量纲(例如,一个维度是米,另一个维度是千克),欧氏距离可能会被某个维度主导。需要进行数据标准化或归一化。对异常值敏感: 欧氏距离对离群点(异常值)敏感,这些异常值会显著影响距离的计算结果。高维数据效果不佳:在高维空间中,欧氏距离可能失去其有效性(称为“维数灾难”),因为所有点之间的距离趋于相似。忽略数据的相关性: 欧氏距离没有考虑各维度之间的相关性,对于具有相关特征的数据,效果可能不理想。
二、 曼哈顿距离(ManhattanDistance)
1.定义: 曼哈顿距离(Manhattan Distance),也称为城市街区距离或L1距离,是指在标准坐标系上,沿着坐标轴移动的距离。这个名称来源于曼哈顿的网格状街道布局,在这种布局下的两点之间的距离就是其在各个坐标轴上的绝对距离之和。顾名思义,在曼哈顿街区要从一个十字路口开车到另一个十字路口,驾驶距离显然不是两点间的直线距离。这个实际驾驶距离就是“曼哈顿距离”。曼哈顿距离也称为“城市街区距离”(City Block distance)。
2.计算公式:
在二维空间中,两个点
(
x
1
,
y
1
)
(x_1, y_1)
(x1,y1) 和
(
x
2
,
y
2
)
(x_2, y_2)
(x2,y2) 之间的曼哈顿距离为:
d
=
∣
x
2
−
x
1
∣
+
∣
y
2
−
y
1
∣
d = |x_2 - x_1| + |y_2 - y_1|
d=∣x2−x1∣+∣y2−y1∣
在 n 维空间中,两个点
x
=
(
x
1
,
x
2
,
…
,
x
n
)
\mathbf{x} = (x_1, x_2, \ldots, x_n)
x=(x1,x2,…,xn) 和
y
=
(
y
1
,
y
2
,
…
,
y
n
)
\mathbf{y} = (y_1, y_2, \ldots, y_n)
y=(y1,y2,…,yn) 之间的曼哈顿距离为:
d
=
∑
i
=
1
n
∣
x
i
−
y
i
∣
d = \sum_{i=1}^{n} |x_i - y_i|
d=i=1∑n∣xi−yi∣
3.python代码
不调包
import numpy as np
def manhattan_distance(point1, point2):
"""
计算两个点之间的曼哈顿距离
:param point1: 第一个点的坐标,列表或元组形式
:param point2: 第二个点的坐标,列表或元组形式
:return: 两点之间的曼哈顿距离
"""
# 将输入点转换为numpy数组
point1 = np.array(point1)
point2 = np.array(point2)
# 计算各维度上的绝对差值
abs_diff = np.abs(point1 - point2)
# 将所有绝对差值相加
distance = np.sum(abs_diff)
return distance
# 示例使用
pointA = (1, 2)
pointB = (4, 6)
distance = manhattan_distance(pointA, pointB)
print(f"Point A 和 Point B 之间的曼哈顿距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
pointA = (1, 2)
pointB = (4, 6)
# 使用scipy的cityblock函数
distance = distance.cityblock(pointA, pointB)
print(f"Point A 和 Point B 之间的曼哈顿距离是: {distance}")
4.优缺点 优点
1. 对尺度不敏感: 曼哈顿距离对不同维度的尺度变化不敏感,即便各维度的单位不同,距离计算结果仍具有可靠性。 2. 计算简单:曼哈顿距离的计算比欧氏距离简单,因为它只涉及绝对值和求和操作,无需进行平方和开平方操作。 3. 适用于网格状路径:在城市规划、机器人路径规划等网格状布局的应用中,曼哈顿距离更加符合实际路径长度。
缺点
1. 不考虑方向:曼哈顿距离只考虑各维度上的差值绝对值,忽略了数据点之间的方向信息,这在某些应用中可能导致信息丢失。 2. 不适用于高维空间:在高维空间中,曼哈顿距离可能不如欧氏距离直观,并且随着维度增加,距离的分布可能变得更加稀疏。 3. 对异常值敏感:曼哈顿距离对数据中的异常值(outliers)敏感,这些异常值会显著影响距离的计算结果。
三、 切比雪夫距离 (Chebyshev Distance)
1.定义: 切比雪夫距离(Chebyshev Distance),又称为
L
∞
L_{\infty}
L∞距离或最大距离,是指在一个 n 维空间中,两个点在各个坐标轴上差值的最大值。它表示在国际象棋中,国王从一个方格移动到另一个方格所需的最小步数。
2.计算公式:
在二维空间中,两个点
(
x
1
,
y
1
)
(x_1, y_1)
(x1,y1) 和
(
x
2
,
y
2
)
(x_2, y_2)
(x2,y2) 之间的切比雪夫距离为:
d
=
max
(
∣
x
2
−
x
1
∣
,
∣
y
2
−
y
1
∣
)
d = \max (|x_2 - x_1|, |y_2 - y_1|)
d=max(∣x2−x1∣,∣y2−y1∣)
在 n 维空间中,两个点
x
=
(
x
1
,
x
2
,
…
,
x
n
)
\mathbf{x} = (x_1, x_2, \ldots, x_n)
x=(x1,x2,…,xn) 和
y
=
(
y
1
,
y
2
,
…
,
y
n
)
\mathbf{y} = (y_1, y_2, \ldots, y_n)
y=(y1,y2,…,yn) 之间的切比雪夫距离为:
d
=
max
i
(
∣
x
i
−
y
i
∣
)
d = \max_i (|x_i - y_i|)
d=imax(∣xi−yi∣)
3.python代码
不调包
import numpy as np
def chebyshev_distance(point1, point2):
"""
计算两个点之间的切比雪夫距离
:param point1: 第一个点的坐标,列表或元组形式
:param point2: 第二个点的坐标,列表或元组形式
:return: 两点之间的切比雪夫距离
"""
# 将输入点转换为numpy数组
point1 = np.array(point1)
point2 = np.array(point2)
# 计算各维度上的绝对差值
abs_diff = np.abs(point1 - point2)
# 取最大值
distance = np.max(abs_diff)
return distance
# 示例使用
pointA = (1, 2)
pointB = (4, 6)
distance = chebyshev_distance(pointA, pointB)
print(f"Point A 和 Point B 之间的切比雪夫距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
pointA = (1, 2)
pointB = (4, 6)
# 使用scipy的chebyshev函数
distance = distance.chebyshev(pointA, pointB)
print(f"Point A 和 Point B 之间的切比雪夫距离是: {distance}")
4.优缺点 优点
对尺度不敏感: 切比雪夫距离对不同维度的尺度变化不敏感,即便各维度的单位不同,距离计算结果仍具有可靠性。适用于离散空间: 在离散空间或网格状路径(如棋盘)中,切比雪夫距离更加符合实际路径长度,尤其在国际象棋等棋类游戏中。计算简单: 切比雪夫距离的计算仅涉及绝对值和取最大值操作,无需复杂的数学运算。
缺点
不考虑方向: 切比雪夫距离只考虑各维度上的最大差值,忽略了数据点之间的方向信息,这在某些应用中可能导致信息丢失。不适用于连续空间: 在连续空间中,切比雪夫距离可能不如欧氏距离和曼哈顿距离直观,并且对于某些实际应用不太适合。对异常值敏感: 切比雪夫距离对数据中的异常值(outliers)敏感,这些异常值会显著影响距离的计算结果。
四、 闵可夫斯基距离(Minkowski Distance)
1.定义: 闵可夫斯基距离(Minkowski Distance)是欧氏距离(当
p
=
2
p = 2
p=2)和曼哈顿距离(当
p
=
1
p = 1
p=1)的广义形式。它是一种更为通用的距离度量方法,通过调节参数
p
p
p,可以在不同距离度量之间进行平滑过渡。闵可夫斯基距离通常用于度量多维空间中两个点之间的距离。
假设数值点 P 和 Q 坐标如下:
P
=
(
x
1
,
x
2
,
…
,
x
n
)
and
Q
=
(
y
1
,
y
2
,
…
,
y
n
)
∈
R
n
P = (x_1, x_2, \ldots, x_n) \quad \text{and} \quad Q = (y_1, y_2, \ldots, y_n) \in \mathbb{R}^n
P=(x1,x2,…,xn)andQ=(y1,y2,…,yn)∈Rn
那么,闵可夫斯基距离定义为:
(
∑
i
=
1
n
∣
x
i
−
y
i
∣
p
)
1
p
\left( \sum_{i=1}^{n} |x_i - y_i|^p \right)^{\frac{1}{p}}
(i=1∑n∣xi−yi∣p)p1
该距离最常用的
p
p
p是 2 和 1,前者是欧几里得距离(Euclidean distance),后者是曼哈顿距离(Manhattan distance)。假设在曼哈顿街区乘坐出租车从 P 点到 Q 点,白色表示高楼大厦,灰色表示街道: 绿色的斜线表示欧几里得距离,在现实中是不可能的。其他三条折线表示了曼哈顿距离,这三条折线的长度是相等的。
当 (p) 趋近于无穷大时,闵可夫斯基距离将化成切比雪夫距离(Chebyshev distance):
lim
p
→
∞
(
∑
i
=
1
n
∣
x
i
−
y
i
∣
p
)
1
p
=
max
i
=
1
n
∣
x
i
−
y
i
∣
\lim_{p \to \infty} \left( \sum_{i=1}^{n} |x_i - y_i|^p \right)^{\frac{1}{p}} = \max_{i=1}^{n} |x_i - y_i|
p→∞lim(i=1∑n∣xi−yi∣p)p1=i=1maxn∣xi−yi∣
我们知道平面上到原点为欧几里得距离(
p
=
2
p = 2
p=2)为 1的点所组成的形状是一个圆,当
p
p
p取其他数值的时候呢?
注意,当
p
<
1
p < 1
p<1时,闵可夫斯基距离不再符合三角形法则,举个例子:当
p
<
1
p < 1
p<1,(0,0) 到 (1,1) 的距离等于
(
1
+
1
)
1
/
p
(1+1)^{1/p}
(1+1)1/p > 2,而 (0,1) 到这两个点的距离都是 1。
闵可夫斯基距离比较直观,但是它与数据的分布无关,具有一定的局限性,如果 x 方向的幅值远远大于 y 方向的值,这个距离公式就会过度放大 x 维度的作用。所以,在计算距离之前,我们可能还需要对数据进行 z-transform 处理,即减去均值,除以标准差:
(
x
1
,
y
1
)
→
(
x
1
−
μ
x
σ
x
,
y
1
−
μ
y
σ
y
)
(x_1, y_1) \rightarrow \left( \frac{x_1 - \mu_x}{\sigma_x}, \frac{y_1 - \mu_y}{\sigma_y} \right)
(x1,y1)→(σxx1−μx,σyy1−μy)
μ
\mu
μ:该维度上的均值
σ
\sigma
σ:该维度上的标准差
可以看到,上述处理开始假设数据的统计特性了。这种方法在假设数据各个维度不相关的情况下利用数据分布的特性计算出不同的距离。如果维度之间互相关联(例如:身高和体重的信息很有可能会带来大量重复的信息,因为两者是有关联的),这时候就得用到马氏距离(Mahalanobis distance)了。
2.计算公式:
在 n 维空间中,两个点
x
=
(
x
1
,
x
2
,
…
,
x
n
)
\mathbf{x} = (x_1, x_2, \ldots, x_n)
x=(x1,x2,…,xn) 和
y
=
(
y
1
,
y
2
,
…
,
y
n
)
\mathbf{y} = (y_1, y_2, \ldots, y_n)
y=(y1,y2,…,yn) 之间的闵可夫斯基距离为:
d
(
x
,
y
)
=
(
∑
i
=
1
n
∣
x
i
−
y
i
∣
p
)
1
p
d(\mathbf{x}, \mathbf{y}) = \left( \sum_{i=1}^{n} |x_i - y_i|^p \right)^{\frac{1}{p}}
d(x,y)=(i=1∑n∣xi−yi∣p)p1
其中,
p
p
p 是一个参数:
当
p
=
1
p = 1
p=1 时,闵可夫斯基距离即为曼哈顿距离。当
p
=
2
p = 2
p=2 时,闵可夫斯基距离即为欧氏距离。当
p
→
∞
p \to \infty
p→∞ 时,闵可夫斯基距离即为切比雪夫距离。
3.python代码
不调包
import numpy as np
def minkowski_distance(point1, point2, p):
"""
计算两个点之间的闵可夫斯基距离
:param point1: 第一个点的坐标,列表或元组形式
:param point2: 第二个点的坐标,列表或元组形式
:param p: 距离的阶数(p值)
:return: 两点之间的闵可夫斯基距离
"""
# 将输入点转换为numpy数组
point1 = np.array(point1)
point2 = np.array(point2)
# 计算各维度上的差值绝对值的p次方
abs_diff_p = np.abs(point1 - point2) ** p
# 求和并开p次方
distance = np.sum(abs_diff_p) ** (1 / p)
return distance
# 示例使用
pointA = (1, 2)
pointB = (4, 6)
p = 3
distance = minkowski_distance(pointA, pointB, p)
print(f"Point A 和 Point B 之间的闵可夫斯基距离(p={p})是: {distance}")
使用Scipy库
from scipy.spatial import distance
pointA = (1, 2)
pointB = (4, 6)
p = 3
# 使用scipy的minkowski函数
distance = distance.minkowski(pointA, pointB, p)
print(f"Point A 和 Point B 之间的闵可夫斯基距离(p={p})是: {distance}")
4.优缺点 优点
灵活性: 闵可夫斯基距离通过参数
p
p
p 的调节,可以表示多种不同的距离度量方法,使其适应各种不同的应用场景。
统一性: 闵可夫斯基距离将多种常用的距离度量(如曼哈顿距离、欧氏距离和切比雪夫距离)统一在一个公式下,提供了一个更为通用的框架。
适用于不同维度的数据: 闵可夫斯基距离可以处理不同维度的数据,尤其在高维空间中,通过选择合适的
p
p
p值,可以调整其计算结果的敏感性。
缺点
对数据的依赖性: 闵可夫斯基距离的计算结果对参数
p
p
p 值高度依赖,不同的
p
p
p 值会产生显著不同的距离,这使得在某些应用中选择合适的
p
p
p 值变得困难。
计算复杂度: 对于某些特定的
p
p
p 值(如
p
>
2
p > 2
p>2),计算闵可夫斯基距离的复杂度较高,特别是在高维数据集上,这可能导致计算开销较大。
对异常值敏感: 闵可夫斯基距离,尤其在
p
p
p 值较高时,对数据中的异常值(outliers)敏感,这些异常值可能会显著影响距离的计算结果。
五、 标准化欧式距离(Standardized Euclidean Distance)
1.定义: 标准化欧式距离(Standardized Euclidean Distance)是一种改进的欧式距离度量方法,它通过对每个维度进行标准化(通常是通过方差标准化)来消除不同特征之间的量纲差异。标准化欧式距离在计算时,对每个维度的差值进行标准化处理,使得各维度的影响在距离计算中得到均衡考虑。
2.计算公式: 在
n
n
n 维空间中,两个点
x
=
(
x
1
,
x
2
,
…
,
x
n
)
\mathbf{x} = (x_1, x_2, \ldots, x_n)
x=(x1,x2,…,xn) 和
y
=
(
y
1
,
y
2
,
…
,
y
n
)
\mathbf{y} = (y_1, y_2, \ldots, y_n)
y=(y1,y2,…,yn) 之间的标准化欧式距离为:
d
(
x
,
y
)
=
∑
i
=
1
n
(
x
i
−
y
i
)
2
s
i
2
d(\mathbf{x}, \mathbf{y}) = \sqrt{\sum_{i=1}^{n} \frac{(x_i - y_i)^2}{s_i^2}}
d(x,y)=i=1∑nsi2(xi−yi)2
其中,
s
i
s_i
si 表示第
i
i
i 个维度的标准差。
3.python代码
不调包
import numpy as np
def standardized_euclidean_distance(point1, point2, variance):
"""
计算两个点之间的标准化欧式距离
:param point1: 第一个点的坐标,列表或元组形式
:param point2: 第二个点的坐标,列表或元组形式
:param variance: 每个维度的方差,列表或元组形式
:return: 两点之间的标准化欧式距离
"""
# 将输入点和方差转换为numpy数组
point1 = np.array(point1)
point2 = np.array(point2)
variance = np.array(variance)
# 计算各维度上的差值
diff = point1 - point2
# 计算标准化欧式距离
distance = np.sqrt(np.sum((diff ** 2) / variance))
return distance
# 示例使用
pointA = [1, 2]
pointB = [4, 6]
variance = [1.5, 2.5]
distance = standardized_euclidean_distance(pointA, pointB, variance)
print(f"Point A 和 Point B 之间的标准化欧式距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
pointA = [1, 2]
pointB = [4, 6]
variance = [1.5, 2.5]
# 使用scipy的seuclidean函数
distance = distance.seuclidean(pointA, pointB, variance)
print(f"Point A 和 Point B 之间的标准化欧式距离是: {distance}")
4.优缺点 优点
消除量纲差异: 标准化欧式距离通过对差值进行标准化,消除了不同特征之间的量纲差异,使得各维度在距离计算中得到公平的权重。适用于不同尺度的特征: 当数据的不同维度具有不同的量纲或尺度时,标准化欧式距离能够有效处理这些差异,避免某一维度主导距离计算结果。保留了欧式距离的几何意义: 标准化欧式距离在消除量纲差异的同时,仍然保留了欧式距离的几何意义,能够直观反映数据点之间的空间距离。
缺点
对标准差的依赖性: 标准化欧式距离对各维度标准差的计算结果敏感,如果标准差估计不准确,可能影响距离的准确性。计算复杂度较高: 由于需要计算各维度的标准差并进行标准化处理,标准化欧式距离的计算复杂度比普通欧式距离稍高,尤其是在大规模数据集上。对异常值敏感: 虽然标准化处理能够减少某些偏差的影响,但标准化欧式距离仍然对异常值敏感,这些异常值可能会对标准差的计算产生不利影响。
六、 马氏距离(Mahalanobis distance)
1.定义: 马氏距离(Mahalanobis Distance)是一种考虑了数据分布特征的距离度量方法。它不仅考虑了各个特征之间的尺度差异,还考虑了特征之间的相关性。马氏距离通过数据的协方差矩阵来衡量样本点与分布之间的距离,广泛应用于多变量分析、异常检测和分类问题中。
2.计算公式:
定义:有 M 个样本向量
X
1
∼
X
m
X_1 \sim X_m
X1∼Xm,协方差矩阵记为
S
S
S,均值记为向量
μ
\mu
μ,则其中样本向量
X
X
X 到
μ
\mu
μ 的马氏距离表示为:
D
(
X
)
=
(
X
−
μ
)
T
S
−
1
(
X
−
μ
)
D(X) = \sqrt{(X - \mu)^T S^{-1}(X - \mu)}
D(X)=(X−μ)TS−1(X−μ)
向量
X
i
X_i
Xi 与
X
j
X_j
Xj 之间的马氏距离定义为:
D
(
X
i
,
X
j
)
=
(
X
i
−
X
j
)
T
S
−
1
(
X
i
−
X
j
)
D(X_i, X_j) = \sqrt{(X_i - X_j)^T S^{-1}(X_i - X_j)}
D(Xi,Xj)=(Xi−Xj)TS−1(Xi−Xj)
若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则
X
i
X_i
Xi 与
X
j
X_j
Xj 之间的马氏距离等于他们的欧氏距离:
D
(
X
i
,
X
j
)
=
(
X
i
−
X
j
)
T
(
X
i
−
X
j
)
D(X_i, X_j) = \sqrt{(X_i - X_j)^T(X_i - X_j)}
D(Xi,Xj)=(Xi−Xj)T(Xi−Xj)
若协方差矩阵是对角矩阵,则就是标准化欧氏距离。
3.python代码
不调包
import numpy as np
from scipy.spatial import distance
def mahalanobis_distance(point, data):
"""
计算点与数据集之间的马氏距离
:param point: 待测点的坐标,列表或元组形式
:param data: 数据集,二维数组形式,每一行为一个样本点
:return: 点与数据集之间的马氏距离
"""
# 计算数据集的均值向量
mean = np.mean(data, axis=0)
# 计算数据集的协方差矩阵
cov_matrix = np.cov(data, rowvar=False)
# 计算协方差矩阵的逆矩阵
inv_cov_matrix = np.linalg.inv(cov_matrix)
# 计算差值向量
diff = point - mean
# 计算马氏距离
distance = np.sqrt(np.dot(np.dot(diff, inv_cov_matrix), diff.T))
return distance
# 示例使用
data = np.array([[1, 2], [2, 3], [3, 4], [4, 5]])
point = np.array([2, 3])
distance = mahalanobis_distance(point, data)
print(f"点 {point} 和数据集之间的马氏距离是: {distance}")
使用Scipy库
import numpy as np
from scipy.spatial import distance
data = np.array([[1, 2], [2, 3], [3, 4], [4, 5]])
point = np.array([2, 3])
# 使用scipy的mahalanobis函数
cov_matrix = np.cov(data, rowvar=False)
inv_cov_matrix = np.linalg.inv(cov_matrix)
distance = distance.mahalanobis(point, np.mean(data, axis=0), inv_cov_matrix)
print(f"点 {point} 和数据集之间的马氏距离是: {distance}")
4.优缺点 优点
考虑了特征的相关性: 马氏距离通过协方差矩阵将特征之间的相关性纳入考虑,使得其在多变量数据分析中表现更好。
尺度无关性:由于马氏距离通过协方差矩阵对数据进行了标准化处理,因此它对不同尺度的特征具有鲁棒性,能够有效避免某个特征主导距离计算结果的问题。
有效的异常检测: 马氏距离特别适用于检测多维空间中的异常值,因为异常值通常会显著偏离数据分布中心,从而产生较大的马氏距离。
缺点
计算复杂度高: 计算协方差矩阵及其逆矩阵的过程较为复杂,尤其在数据维度较高的情况下,计算马氏距离的开销较大。
对数据的依赖性强: 马氏距离的计算依赖于数据的分布特性,如果数据分布不符合多变量正态分布,计算结果可能会受到影响。
对小样本不稳定: 在小样本数据集上,协方差矩阵的估计不准确,导致马氏距离的计算结果不稳定。
七、 余弦距离(Cosine Distance)
1.定义: 余弦距离(Cosine Distance)是基于余弦相似度的一种距离度量方法,用于衡量两个向量之间的相似性。它通过计算两个向量之间的夹角余弦值,反映向量方向上的差异,而不考虑向量的大小。余弦距离主要用于文本分析、信息检索等高维空间的应用场景。
2.计算公式:
二维空间中向量 A
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1) 与向量 B
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2) 的夹角余弦公式:
cos
θ
=
x
1
x
2
+
y
1
y
2
x
1
2
+
y
1
2
⋅
x
2
2
+
y
2
2
\cos \theta = \frac{x_1 x_2 + y_1 y_2}{\sqrt{x_1^2 + y_1^2} \cdot \sqrt{x_2^2 + y_2^2}}
cosθ=x12+y12
⋅x22+y22
x1x2+y1y2
两个 n 维样本点 a
(
x
11
,
x
12
,
.
.
.
,
x
1
n
)
(x_{11},x_{12},...,x_{1n})
(x11,x12,...,x1n) 和 b
(
x
21
,
x
22
,
.
.
.
,
x
2
n
)
(x_{21},x_{22},...,x_{2n})
(x21,x22,...,x2n) 的夹角余弦为:
cos
(
θ
)
=
a
⋅
b
∣
a
∣
∣
b
∣
\cos(\theta) = \frac{\mathbf{a} \cdot \mathbf{b}}{|\mathbf{a}| |\mathbf{b}|}
cos(θ)=∣a∣∣b∣a⋅b
即:
cos
(
θ
)
=
∑
k
=
1
n
x
1
k
x
2
k
∑
k
=
1
n
x
1
k
2
⋅
∑
k
=
1
n
x
2
k
2
\cos(\theta) = \frac{\sum_{k=1}^{n} x_{1k} x_{2k}}{\sqrt{\sum_{k=1}^{n} x_{1k}^2} \cdot \sqrt{\sum_{k=1}^{n} x_{2k}^2}}
cos(θ)=∑k=1nx1k2
⋅∑k=1nx2k2
∑k=1nx1kx2k
夹角余弦取值范围为[-1,1],余弦越大表示两个向量的夹角越小,余弦越小表示两个向量的夹角越大。当两个向量的方向重合时余弦取最大值1,当两个向量的方向完全相反余弦取最小值-1。
3.python代码
不调包
import numpy as np
def cosine_distance(vector1, vector2):
"""
计算两个向量之间的余弦距离
:param vector1: 第一个向量,列表或元组形式
:param vector2: 第二个向量,列表或元组形式
:return: 两个向量之间的余弦距离
"""
# 将输入向量转换为numpy数组
vector1 = np.array(vector1)
vector2 = np.array(vector2)
# 计算点积
dot_product = np.dot(vector1, vector2)
# 计算模长
norm1 = np.linalg.norm(vector1)
norm2 = np.linalg.norm(vector2)
# 计算余弦相似度
cosine_similarity = dot_product / (norm1 * norm2)
# 计算余弦距离
cosine_distance = 1 - cosine_similarity
return cosine_distance
# 示例使用
vectorA = [1, 0, 1]
vectorB = [0, 1, 1]
distance = cosine_distance(vectorA, vectorB)
print(f"向量 A 和 向量 B 之间的余弦距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
vectorA = [1, 0, 1]
vectorB = [0, 1, 1]
# 使用scipy的cosine函数
distance = distance.cosine(vectorA, vectorB)
print(f"向量 A 和 向量 B 之间的余弦距离是: {distance}")
4.优缺点 优点
尺度无关性:余弦距离只关注向量的方向,而不考虑向量的大小,因此它对特征值的尺度变化不敏感,特别适用于文本分析等场景。
高效处理高维数据: 在高维空间中,余弦距离能够有效处理稀疏向量(例如词频向量),并且计算复杂度较低。
适用于文本和向量数据:余弦距离广泛应用于文本分析、推荐系统、信息检索等领域,特别是在计算文档或句子相似度时表现出色。
缺点
对零向量不定义:如果输入向量中存在零向量,则无法计算余弦相似度,进而无法计算余弦距离。
不能反映向量的大小:余弦距离仅关注向量之间的角度,不反映向量大小的差异,因此在某些应用中可能无法有效捕捉向量的实际差异。
适用场景有限:余弦距离在那些需要考虑向量大小的场景中表现不佳,例如图像分析、物理量度等领域。
八、 汉明距离(Hamming Distance)
1.定义: 汉明距离(Hamming Distance)是一种用于衡量两个等长字符串(或二进制数)之间差异的度量方法。它表示在两个字符串或二进制数对应位置上不同字符的数量。汉明距离广泛应用于编码理论、信息学、错误检测与纠正等领域。
2.计算公式: 给定两个等长字符串
x
\mathbf{x}
x 和
y
\mathbf{y}
y,它们之间的汉明距离定义为:
d
(
x
,
y
)
=
∑
i
=
1
n
δ
(
x
i
,
y
i
)
d(\mathbf{x}, \mathbf{y}) = \sum_{i=1}^{n} \delta(x_i, y_i)
d(x,y)=i=1∑nδ(xi,yi)
其中,
δ
(
x
i
,
y
i
)
\delta(x_i, y_i)
δ(xi,yi) 是一个指示函数,当
x
i
≠
y
i
x_i \neq y_i
xi=yi 时取值为 1,否则为 0。即汉明距离就是所有对应位置字符不同的次数。
3.python代码
不调包
def hamming_distance(str1, str2):
"""
计算两个字符串之间的汉明距离
:param str1: 第一个字符串
:param str2: 第二个字符串
:return: 两个字符串之间的汉明距离
"""
if len(str1) != len(str2):
raise ValueError("字符串长度必须相等")
# 计算汉明距离
distance = sum(c1 != c2 for c1, c2 in zip(str1, str2))
return distance
# 示例使用
str1 = "1011101"
str2 = "1001001"
distance = hamming_distance(str1, str2)
print(f"字符串 {str1} 和 {str2} 之间的汉明距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
str1 = "1011101"
str2 = "1001001"
# 使用scipy的hamming函数(注意:需要将字符串转换为列表或数组形式)
distance = distance.hamming(list(str1), list(str2)) * len(str1)
print(f"字符串 {str1} 和 {str2} 之间的汉明距离是: {distance}")
4.优缺点 优点
计算简单:汉明距离的计算非常简单,只需要逐个比较对应位置的字符即可,适用于字符串和二进制数的简单比较。适用于错误检测:汉明距离广泛应用于编码理论中的错误检测与纠正,因为它可以准确地指出不同字符的位置和数量。应用广泛:汉明距离在通信、密码学、数据压缩、基因序列分析等领域中有广泛的应用,特别是在测量二进制数据和字符数据的差异时表现出色。
缺点
仅适用于等长字符串:汉明距离要求两个字符串或二进制数必须等长,无法直接应用于长度不同的字符串。忽略了字符的性质:汉明距离只考虑字符是否相同,而忽略了字符之间的实际差异或相似性,这在某些应用中可能不够精确。对连续性变化不敏感:汉明距离无法反映两个字符串之间连续性变化的影响,例如字符串中字符顺序的交换不会改变汉明距离。
九、 杰卡德距离(Jaccard Distance)
1.定义: 杰卡德距离(Jaccard Distance)是一种用于衡量两个集合之间相异性的度量方法。它基于杰卡德相似系数(Jaccard Similarity Coefficient)来定义,反映了两个集合的交集与并集之间的关系。杰卡德距离广泛应用于信息检索、文本分析、推荐系统等领域,尤其适用于衡量二元数据(如标签、集合)之间的差异。
2.计算公式: 给定两个集合
A
A
A 和
B
B
B,它们之间的杰卡德相似系数定义为:
Jaccard Similarity
=
∣
A
∩
B
∣
∣
A
∪
B
∣
\text{Jaccard Similarity} = \frac{|A \cap B|}{|A \cup B|}
Jaccard Similarity=∣A∪B∣∣A∩B∣
其中,
∣
A
∩
B
∣
|A \cap B|
∣A∩B∣ 表示集合
A
A
A 和
B
B
B 的交集的大小,
∣
A
∪
B
∣
|A \cup B|
∣A∪B∣ 表示它们并集的大小。
杰卡德距离由杰卡德相似系数衍生而来,定义为:
Jaccard Distance
=
1
−
Jaccard Similarity
\text{Jaccard Distance} = 1 - \text{Jaccard Similarity}
Jaccard Distance=1−Jaccard Similarity
杰卡德距离的取值范围在 [0, 1] 之间,其中 0 表示两个集合完全相同,1 表示两个集合完全不同。
3.python代码
不调包
def jaccard_distance(set1, set2):
"""
计算两个集合之间的杰卡德距离
:param set1: 第一个集合
:param set2: 第二个集合
:return: 两个集合之间的杰卡德距离
"""
# 计算交集
intersection = len(set1.intersection(set2))
# 计算并集
union = len(set1.union(set2))
# 计算杰卡德相似系数
jaccard_similarity = intersection / union
# 计算杰卡德距离
jaccard_distance = 1 - jaccard_similarity
return jaccard_distance
# 示例使用
setA = {1, 2, 3, 4}
setB = {3, 4, 5, 6}
distance = jaccard_distance(setA, setB)
print(f"集合 A 和 集合 B 之间的杰卡德距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
setA = [1, 1, 1, 0]
setB = [1, 1, 0, 0]
# 使用scipy的jaccard函数
distance = distance.jaccard(setA, setB)
print(f"集合 A 和 集合 B 之间的杰卡德距离是: {distance}")
4.优缺点 优点
适用于二元数据:杰卡德距离特别适用于衡量二元数据(如集合、布尔向量)之间的差异,在文本分析、集合比较、标签数据处理中表现出色。处理稀疏数据:在稀疏数据集上,杰卡德距离能够有效地度量两个数据点之间的相似性,尤其适用于大规模的文本数据或集合数据。简单直观:杰卡德距离基于集合操作,计算简单且具有直观的几何意义,易于理解和实现。
缺点
忽略频次信息:杰卡德距离仅考虑集合中元素的存在与否,而忽略了元素在集合中出现的频次信息,因此在一些需要考虑频次的应用中不够精确。不适用于有序数据:杰卡德距离不考虑数据的顺序信息,对于有序数据或连续数据的比较效果不佳。对小集合敏感:对于元素较少的小集合,杰卡德距离可能过于敏感,即使两个集合只有一个元素不同,也可能导致较大的距离。
十、 相关距离(Correlation distance)
1.定义: 相关距离(Correlation Distance)是一种基于相关系数的距离度量方法,用于衡量两个变量(或两个向量)之间的线性关系。相关距离反映了两个向量在方向上的相似性,而不考虑它们的大小和尺度。常用的相关系数包括皮尔逊相关系数(Pearson Correlation Coefficient)和斯皮尔曼秩相关系数(Spearman’s Rank Correlation Coefficient)。相关距离在统计分析、数据挖掘、机器学习等领域有广泛应用,尤其适用于度量数据集中变量之间的相似性。
2.计算公式: 对于两个向量
A
\mathbf{A}
A 和
B
\mathbf{B}
B,它们的皮尔逊相关系数定义为:
r
(
A
,
B
)
=
∑
i
=
1
n
(
A
i
−
A
ˉ
)
(
B
i
−
B
ˉ
)
∑
i
=
1
n
(
A
i
−
A
ˉ
)
2
⋅
∑
i
=
1
n
(
B
i
−
B
ˉ
)
2
r(\mathbf{A}, \mathbf{B}) = \frac{\sum_{i=1}^{n} (A_i - \bar{A})(B_i - \bar{B})}{\sqrt{\sum_{i=1}^{n} (A_i - \bar{A})^2} \cdot \sqrt{\sum_{i=1}^{n} (B_i - \bar{B})^2}}
r(A,B)=∑i=1n(Ai−Aˉ)2
⋅∑i=1n(Bi−Bˉ)2
∑i=1n(Ai−Aˉ)(Bi−Bˉ)
其中,
A
ˉ
\bar{A}
Aˉ 和
B
ˉ
\bar{B}
Bˉ 分别是向量
A
\mathbf{A}
A 和
B
\mathbf{B}
B 的均值。
相关距离定义为:
Correlation Distance
=
1
−
r
(
A
,
B
)
\text{Correlation Distance} = 1 - r(\mathbf{A}, \mathbf{B})
Correlation Distance=1−r(A,B)
相关距离的取值范围在 [0, 2] 之间,其中 0 表示两个向量完全正相关,2 表示两个向量完全负相关,1 表示不相关。
3.python代码
不调包
import numpy as np
def correlation_distance(vector1, vector2):
"""
计算两个向量之间的相关距离
:param vector1: 第一个向量,列表或元组形式
:param vector2: 第二个向量,列表或元组形式
:return: 两个向量之间的相关距离
"""
# 将输入向量转换为numpy数组
vector1 = np.array(vector1)
vector2 = np.array(vector2)
# 计算皮尔逊相关系数
correlation_coefficient = np.corrcoef(vector1, vector2)[0, 1]
# 计算相关距离
correlation_distance = 1 - correlation_coefficient
return correlation_distance
# 示例使用
vectorA = [1, 2, 3, 4, 5]
vectorB = [2, 4, 6, 8, 10]
distance = correlation_distance(vectorA, vectorB)
print(f"向量 A 和 向量 B 之间的相关距离是: {distance}")
使用Scipy库
from scipy.spatial import distance
import numpy as np
vectorA = [1, 2, 3, 4, 5]
vectorB = [2, 4, 6, 8, 10]
# 使用scipy的correlation函数
distance = distance.correlation(vectorA, vectorB)
print(f"向量 A 和 向量 B 之间的相关距离是: {distance}")
4.优缺点 优点
适用于线性关系:相关距离可以有效地度量变量之间的线性关系,尤其在研究变量之间的依赖性和共变性时表现出色。尺度无关性:相关距离不受变量尺度和大小的影响,只关注变量之间的相对变化,因此在数据标准化之前使用非常方便。广泛应用:相关距离广泛应用于统计分析、经济学、金融学、基因表达分析等领域,特别适合分析时间序列数据和高维数据集。
缺点
仅适用于线性关系:相关距离只能反映线性关系,对于非线性关系的变量,相关距离可能无法有效地度量它们之间的真实关系。对异常值敏感:皮尔逊相关系数对异常值非常敏感,异常值可能会显著影响相关距离的计算结果,从而影响分析的准确性。忽略数据分布形态: 相关距离不考虑数据的具体分布形态,可能在某些情况下忽略了数据之间的重要差异。
十一、 信息熵(Information Entropy)
1.定义: 信息熵(Entropy)是信息理论中的一个重要概念,由数学家克劳德·香农(Claude Shannon)在1948年提出。信息熵用于衡量信息的不确定性或随机性程度。熵的值越大,表明系统的随机性或不确定性越高。信息熵广泛应用于数据压缩、密码学、机器学习、通信等领域。
2.计算公式: 对于一个离散随机变量
X
X
X,其信息熵定义为:
H
(
X
)
=
−
∑
i
=
1
n
p
(
x
i
)
log
b
p
(
x
i
)
H(X) = -\sum_{i=1}^{n} p(x_i) \log_b p(x_i)
H(X)=−i=1∑np(xi)logbp(xi)
其中,
p
(
x
i
)
p(x_i)
p(xi) 表示随机变量
X
X
X 取值为
x
i
x_i
xi 的概率,
b
b
b 是对数的底,通常取 2(表示熵的单位为比特 bit)。
当
b
=
2
b = 2
b=2 时,熵单位为比特(bit)。当
b
=
e
b = e
b=e 时,熵单位为纳特(nat)。当
b
=
10
b = 10
b=10 时,熵单位为哈特莱(hartley)。
3.python代码
不调包
import numpy as np
def entropy(probabilities, base=2):
"""
计算给定概率分布的熵
:param probabilities: 概率分布,列表或数组形式
:param base: 对数的底,默认为2
:return: 信息熵的值
"""
# 确保概率分布的有效性
probabilities = np.array(probabilities)
probabilities = probabilities[probabilities > 0] # 去除概率为0的项
# 计算信息熵
entropy_value = -np.sum(probabilities * np.log(probabilities) / np.log(base))
return entropy_value
# 示例使用
probabilities = [0.2, 0.3, 0.5]
entropy_value = entropy(probabilities)
print(f"给定概率分布的熵为: {entropy_value} 比特")
使用Scipy库
from scipy.stats import entropy
probabilities = [0.2, 0.3, 0.5]
# 使用scipy的entropy函数计算熵,默认对数底为e
entropy_value = entropy(probabilities, base=2)
print(f"给定概率分布的熵为: {entropy_value} 比特")
4.优缺点 优点
量化不确定性: 信息熵提供了一种数学方法来量化系统的不确定性或混乱程度,广泛应用于信息论、统计学和机器学习中。适用于多种数据类型: 信息熵能够处理离散型数据和连续型数据,适用于不同的数据分析场景。用于特征选择: 在机器学习中,信息熵常用于特征选择和决策树的构建,因为它能帮助识别对目标变量影响最大的特征。
缺点
对概率分布敏感: 信息熵的计算依赖于概率分布,如果数据的概率分布不准确或不可知,熵的计算结果可能不可靠。不适用于小样本数据: 在小样本数据集上,熵的估计可能不准确,因为小样本中的概率估计可能偏离真实分布。复杂度较高: 当数据量较大或维度较高时,信息熵的计算复杂度较高,尤其是在需要处理大量类别或连续型变量的情况下。
十二、 总结
欧式距离、曼哈顿距离、切比雪夫距离 是常见的基于几何学的距离度量方法,适用于不同的应用场景,计算简单但在高维空间中表现不佳。标准化欧式距离 通过标准化处理消除了尺度差异,更适合不同尺度的特征,但计算复杂度较高。马氏距离 考虑了数据分布和特征相关性,适用于多变量分析,但对数据的依赖性较强,计算复杂。余弦距离 和 相关距离 都反映了向量间的相似性,但余弦距离更注重方向相似性,相关距离则考虑了线性关系。汉明距离 和 杰卡德距离 适用于二进制数据和集合数据的比较,汉明距离关注位置差异,杰卡德距离则关注集合差异。信息熵 作为一种度量不确定性的工具,广泛应用于信息论和机器学习,适用于特征选择和模型优化。
这些距离度量方法各有优缺点,适用于不同的数据类型和应用场景。选择合适的距离度量方法需要结合具体的数据特征和分析需求。
参考文献: 机器学习——各种距离度量方法总结
结~~~