8种距离度量 Python 实战:从欧式到马氏,3个维度对比代码实现
8种距离度量 Python 实战从欧式到马氏3个维度对比代码实现在数据科学和机器学习领域距离度量是许多算法的核心基础。无论是KNN分类、K-Means聚类还是推荐系统中的相似度计算选择合适的距离度量方法直接影响模型效果。本文将带你用Python实现8种经典距离度量并通过实际代码对比它们的特性。1. 距离度量基础与Python环境准备距离度量本质上是衡量两个对象相似程度的数学方法。在机器学习中我们通常将数据表示为向量然后通过计算向量之间的距离来判断它们的相似性。不同的距离度量方法适用于不同的场景和数据特性。首先确保你的Python环境已安装必要的科学计算库import numpy as np from scipy.spatial import distance from sklearn.preprocessing import StandardScaler from sklearn.datasets import make_blobs import time我们创建一个简单的二维数据集用于演示# 生成示例数据 np.random.seed(42) data np.random.rand(10, 2) * 10 # 10个二维点 point_a data[0] # [6.965, 1.635] point_b data[1] # [1.025, 1.857]2. 8种距离度量的Python实现2.1 欧式距离 (Euclidean Distance)欧式距离是最直观的距离度量表示n维空间中两点间的直线距离。其数学定义为$$ d(p,q) \sqrt{\sum_{i1}^n (p_i - q_i)^2} $$Python实现def euclidean_dist(a, b): return np.sqrt(np.sum((a - b)**2)) # 使用scipy验证 assert euclidean_dist(point_a, point_b) distance.euclidean(point_a, point_b)适用场景KNN、K-Means等算法中默认的距离度量适用于各维度相关性较小且尺度相似的数据。2.2 曼哈顿距离 (Manhattan Distance)曼哈顿距离又称城市街区距离得名于在规则街区网格中行走的实际距离。计算公式为$$ d(p,q) \sum_{i1}^n |p_i - q_i| $$Python代码def manhattan_dist(a, b): return np.sum(np.abs(a - b)) # 验证 assert manhattan_dist(point_a, point_b) distance.cityblock(point_a, point_b)典型应用在路径规划和高维数据中表现良好对异常值比欧式距离更鲁棒。2.3 余弦相似度 (Cosine Similarity)余弦相似度通过测量两个向量夹角的余弦值来判断相似性忽略向量长度$$ \text{cosine}(p,q) \frac{p \cdot q}{|p| |q|} $$实现代码def cosine_sim(a, b): return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) # 验证 assert np.allclose(cosine_sim(point_a, point_b), 1 - distance.cosine(point_a, point_b))优势场景文本相似度计算、推荐系统等方向敏感的应用。2.4 汉明距离 (Hamming Distance)汉明距离衡量两个等长字符串在相同位置上不同字符的个数def hamming_dist(a, b): return np.sum(a ! b) / len(a) # 示例 str_a np.array([1, 0, 1, 1, 0]) str_b np.array([1, 1, 0, 1, 1]) print(f汉明距离: {hamming_dist(str_a, str_b):.2f}) # 输出0.60主要用途错误检测与纠正、基因序列比对等离散数据场景。2.5 切比雪夫距离 (Chebyshev Distance)切比雪夫距离定义为各坐标数值差的最大值源于国际象棋中国王的移动方式$$ d(p,q) \max_i |p_i - q_i| $$Python实现def chebyshev_dist(a, b): return np.max(np.abs(a - b)) # 验证 assert chebyshev_dist(point_a, point_b) distance.chebyshev(point_a, point_b)适用情况仓储物流路径规划、棋盘类游戏AI等场景。2.6 闵可夫斯基距离 (Minkowski Distance)闵可夫斯基距离是欧式距离和曼哈顿距离的推广形式$$ d(p,q) \left( \sum_{i1}^n |p_i - q_i|^p \right)^{1/p} $$参数p控制距离类型p1曼哈顿距离p2欧式距离p→∞切比雪夫距离代码实现def minkowski_dist(a, b, p): return np.sum(np.abs(a - b)**p)**(1/p) # 验证与欧式距离等价 assert np.isclose(minkowski_dist(point_a, point_b, 2), euclidean_dist(point_a, point_b))2.7 标准化欧式距离 (Standardized Euclidean)针对各维度尺度差异大的数据先标准化再计算欧式距离def standardized_euclidean(a, b, data): scaler StandardScaler() scaled_data scaler.fit_transform(data) a_scaled scaler.transform([a])[0] b_scaled scaler.transform([b])[0] return euclidean_dist(a_scaled, b_scaled)解决痛点当特征量纲不一致时避免某些维度主导距离计算。2.8 马氏距离 (Mahalanobis Distance)马氏距离考虑特征间的相关性适用于非球形分布数据$$ d(p,q) \sqrt{(p-q)^T S^{-1} (p-q)} $$其中S是协方差矩阵。Python实现def mahalanobis_dist(a, b, data): cov np.cov(data.T) inv_cov np.linalg.inv(cov) diff a - b return np.sqrt(diff.T inv_cov diff) # 生成相关数据验证 correlated_data make_blobs(n_samples100, centers1, n_features2, random_state42)[0] point_c correlated_data[0] point_d correlated_data[1] print(f马氏距离: {mahalanobis_dist(point_c, point_d, correlated_data):.2f})核心优势自动处理特征间的线性相关性对尺度变化不敏感。3. 三维度对比分析我们从计算效率、适用场景和异常值敏感性三个维度系统对比这8种距离度量距离度量计算速度典型应用场景异常值敏感性欧式距离⚡⚡⚡空间距离、KNN、K-Means高曼哈顿距离⚡⚡⚡高维数据、路径规划中余弦相似度⚡⚡文本相似度、推荐系统低汉明距离⚡⚡⚡⚡错误检测、基因序列不适用切比雪夫距离⚡⚡⚡棋盘游戏、仓储物流高闵可夫斯基距离⚡⚡可调参数适应不同场景取决于p值标准化欧式⚡⚡多尺度特征数据中马氏距离⚡非球形分布、相关特征低性能提示在大型数据集上欧式距离和曼哈顿距离计算效率最高而马氏距离由于涉及矩阵求逆计算成本较高。4. 实战应用KNN中的距离度量选择我们通过一个完整的KNN分类示例展示不同距离度量的实际影响from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 准备数据 X, y make_blobs(n_samples1000, centers3, n_features5, random_state42) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3) # 测试不同距离度量 metrics [euclidean, manhattan, cosine, mahalanobis] results {} for metric in metrics: start time.time() if metric mahalanobis: knn KNeighborsClassifier(n_neighbors5, metricmetric, metric_params{V: np.cov(X_train.T)}) else: knn KNeighborsClassifier(n_neighbors5, metricmetric) knn.fit(X_train, y_train) preds knn.predict(X_test) acc accuracy_score(y_test, preds) time_cost time.time() - start results[metric] {accuracy: acc, time: time_cost} # 打印结果 print(KNN性能对比:) for metric, res in results.items(): print(f{metric:10} | 准确率: {res[accuracy]:.3f} | 耗时: {res[time]:.3f}s)典型输出结果可能显示欧式距离和曼哈顿距离准确率相近且计算最快马氏距离可能在某些数据集上表现更好但耗时明显增加余弦相似度在文本类数据上表现突出5. 距离度量选择指南根据数据特性选择距离度量数据尺度各维度尺度相似欧式距离尺度差异大标准化欧式或马氏距离特征相关性特征独立欧式距离存在相关性马氏距离数据类型连续数值欧式/曼哈顿二进制/分类汉明距离文本数据余弦相似度算法效率要求大规模数据欧式或曼哈顿距离小规模高维数据可考虑马氏距离# 完整距离计算模块 class DistanceMetrics: staticmethod def euclidean(a, b): return np.sqrt(np.sum((a - b)**2)) staticmethod def manhattan(a, b): return np.sum(np.abs(a - b)) staticmethod def cosine(a, b): return 1 - np.dot(a, b)/(np.linalg.norm(a)*np.linalg.norm(b)) # 其他方法实现...在实际项目中建议先通过数据探索分析特征分布和相关性再选择2-3种候选距离度量进行实验比较最终根据模型表现确定最优方案。