距离度量:机器学习中的核心工具,从入门到实践
距离度量是有监督与无监督学习算法(如K近邻、支持向量机、K均值聚类)的关键基础。选择合适的距离度量直接影响模型性能,因此深入理解每种度量的原理、适用场景及其代码实现至关重要。本文将带你系统探索10种常用距离度量方法,从几何距离到统计距离,助你轻松掌握。
一、几何距离测量
几何距离测量适用于实值向量或连续型数据,常用于特征空间中的相似性计算。
1. 欧氏距离(Euclidean distance)
- 定义:两点之间的最短直线距离,是最直观、最常用的距离度量。
- 计算公式(L2范数):
- Python实现:
from scipy.spatial import distance distance.euclidean(vector_1, vector_2)
- 缺点:
- 在高维空间(超过3维)效果较差。
- 对特征的单位敏感,需先进行标准化或归一化处理。
- 小提示:使用前务必检查特征尺度是否一致,否则距离会被量级较大的特征主导。
2. 曼哈顿距离(Manhattan distance)
- 定义:也称出租车距离或城市街区距离,模拟只能沿直角移动的路径长度。
- 适用场景:离散数据、二元属性,例如计算城市中两点间的实际行车距离。
- 计算公式(L1范数):
- Python实现:
from scipy.spatial import distance distance.cityblock(vector_1, vector_2)
- 缺点:
- 高维空间中不如欧氏距离直观。
- 不代表最短路径,仅是沿坐标轴移动的路径。
- 常见问题:
问:曼哈顿距离和欧氏距离哪个更适用于稀疏数据?
答:曼哈顿距离更适用于稀疏数据,因为它仅考虑坐标轴方向的差异,不易受大量零值影响。
3. 切比雪夫距离(Chebyshev distance)
- 定义:也称为棋盘距离,取两个向量在任意维度上的最大差值。
- 典型用途:仓库物流中,最长路径决定了移动时间。
- 计算公式(L∞范数):
- Python实现:
from scipy.spatial import distance distance.chebyshev(vector_1, vector_2)
- 缺点:使用场景非常特殊,很少用于常规机器学习任务。
- 小提示:如果你需要关注“最差情况”下的差异(如异常检测中的最大偏离),可考虑切比雪夫距离。
4. 闵可夫斯基距离(Minkowski distance)
- 定义:是欧氏距离、曼哈顿距离、切比雪夫距离的广义形式,通过参数 p 控制。
- 计算公式:
- Python实现:
from scipy.spatial import distance distance.minkowski(vector_1, vector_2, p)
- 灵活性:
- p=1 → 曼哈顿距离
- p=2 → 欧氏距离
- p→∞ → 切比雪夫距离
- 缺点:与欧氏距离、曼哈顿距离相同,高维空间表现不佳且对特征单位敏感;寻找最优p值耗时。
- 常见问题:
问:如何选择p值?
答:通常通过交叉验证尝试p=1,2,3等,观察模型性能;或者根据数据稀疏性,稀疏数据倾向p=1,密集数据倾向p=2。
5. 余弦相似度与余弦距离(Cosine similarity & Cosine distance)
- 定义:衡量两个向量方向的相似度,忽略向量的大小。余弦距离 = 1 - 余弦相似度。
- 适用场景:文本分析、推荐系统等高维稀疏数据,例如词频向量。
- 计算公式:
- Python实现:
from scipy.spatial import distance distance.cosine(vector_1, vector_2)
- 缺点:不关注数值大小,仅关注方向,若大小也有意义(如商品销量),则不适合。
- 小提示:在文本相似度计算中,余弦相似度通常结合TF-IDF使用,效果更佳。
6. 半正矢距离(Haversine distance)
- 定义:计算球面上两点间的最短弧长距离,常用于地理空间(经纬度)数据。
- 计算公式(r为球半径,φ、λ为经纬度):
- Python实现:
from sklearn.metrics.pairwise import haversine_distances haversine_distances([vector_1, vector_2])
- 缺点:假设地球为完美球体,实际存在轻微误差。
- 常见问题:
问:半正矢距离与欧氏距离在地理数据上有什么区别?
答:欧氏距离忽略地球曲率,短距离(如几公里内)近似可用,但长距离或高纬度误差极大,必须使用半正矢距离。
7. 汉明距离(Hamming distance)
- 定义:比较两个等长二进制向量或字符串,统计对应位置不同的个数,并除以长度得到0~1的值。
- 适用场景:纠错码、文字相似度(如DNA序列)、分类任务中的二元特征。
- Python实现:
from scipy.spatial import distance distance.hamming(vector_1, vector_2)
- 缺点:
- 只能比较相同长度的向量。
- 无法反映差异的大小(例如两个不同的位,但差异程度不同无法体现)。
- 小提示:如果差异的大小很重要(如颜色深浅),请使用欧氏距离或其他数值度量。
二、统计距离测量
统计距离测量用于假设检验、分类、异常检测等任务,通常基于概率或集合论。
8. 杰卡德指数与杰卡德距离(Jaccard Index / Jaccard distance)
- 定义:衡量两个样本集合的相似性,交集大小除以并集大小。距离 = 1 - 指数。
- 适用场景:图像分割、文本模式比较、二元特征数据。
- 计算公式:
- Python实现:
from scipy.spatial import distance distance.jaccard(vector_1, vector_2)
- 缺点:受数据规模影响较大,大规模集合中小差异会被放大或缩小。
- 常见问题:
问:杰卡德距离与余弦相似度有何区别?
答:杰卡德基于集合交集,余弦基于向量方向。杰卡德适用于二元稀疏数据,余弦适用于实值稀疏数据(如TF-IDF)。
9. Sörensen-Dice指数(Sorensen-Dice index)
- 定义:与杰卡德相似,但更直观——直接计算两倍交集除以总样本数,即重叠百分比。
- 适用场景:图像分割评估、文本相似度分析。
- 计算公式:
- Python实现:
from scipy.spatial import distance distance.dice(vector_1, vector_2)
- 缺点:同样对数据集大小敏感,且通常只适用于二元数据。
- 小提示:当杰卡德和Dice都适用时,Dice往往对重叠部分更敏感,适合强调匹配的任务。
10. 动态时间规整(Dynamic Time Warping, DTW)
- 定义:专门用于比较两个不同长度或时间偏移的时间序列。通过多对一、一对多的映射找到最优对齐路径。
- 适用场景:语音识别、异常检测、手势识别等时间序列任务。
- 为什么需要它:欧氏距离只能逐点比较,如果两个形状相同但时间偏移,欧氏距离会很大,而DTW能正确识别相似性。
- 路径约束条件:
- 边界条件:从起点到终点。
- 单调性:时间顺序不变。
- 连续性:路径只允许相邻时间步。
- 可选:整经窗口、坡度条件。
- Python实现:
from scipy.spatial.distance import euclidean from fastdtw import fastdtw distance, path = fastdtw(timeseries_1, timeseries_2, dist=euclidean)
- 缺点:计算复杂度较高,但使用 fastdtw 库可大幅加速。
- 常见问题:
问:何时使用DTW而不是欧氏距离?
答:当时间序列可能存在时间滞后或拉伸时(例如同样的动作有人快有人慢),必须用DTW。若序列等长且无偏移,欧氏距离更快。
总结:如何选择正确的距离度量?
本文介绍了10种常用距离度量,从几何距离到统计距离,每种都有独特的优势和限制。核心选择原则如下:
- 数据类型:连续实值 → 欧氏、曼哈顿、闵可夫斯基;二进制 → 汉明、杰卡德、Dice;地理坐标 → 半正矢;时间序列 → DTW。
- 维度:高维稀疏数据 → 余弦相似度或曼哈顿距离。
- 是否需要大小:只关心方向 → 余弦;关心大小 → 欧氏等。
- 计算效率:欧氏、曼哈顿最快;DTW最慢。
实践中,建议先对数据进行标准化或归一化,再尝试几种常用度量,通过交叉验证选择最佳方案。现在,你可以根据具体任务,自信地选用最合适的距离度量了!
(本文内容基于常见机器学习实践整理,如有疏漏欢迎补充指正。)
