news 2026/7/4 21:40:47

8种距离度量 Python 实战:从欧式到马氏,3个维度对比代码实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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_{i=1}^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_{i=1}^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_{i=1}^n |p_i - q_i|^p \right)^{1/p} $$

参数p控制距离类型:

  • p=1:曼哈顿距离
  • p=2:欧式距离
  • 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_samples=100, centers=1, n_features=2, random_state=42)[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_samples=1000, centers=3, n_features=5, random_state=42) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3) # 测试不同距离度量 metrics = ['euclidean', 'manhattan', 'cosine', 'mahalanobis'] results = {} for metric in metrics: start = time.time() if metric == 'mahalanobis': knn = KNeighborsClassifier(n_neighbors=5, metric=metric, metric_params={'V': np.cov(X_train.T)}) else: knn = KNeighborsClassifier(n_neighbors=5, metric=metric) 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. 距离度量选择指南

根据数据特性选择距离度量:

  1. 数据尺度

    • 各维度尺度相似:欧式距离
    • 尺度差异大:标准化欧式或马氏距离
  2. 特征相关性

    • 特征独立:欧式距离
    • 存在相关性:马氏距离
  3. 数据类型

    • 连续数值:欧式/曼哈顿
    • 二进制/分类:汉明距离
    • 文本数据:余弦相似度
  4. 算法效率要求

    • 大规模数据:欧式或曼哈顿距离
    • 小规模高维数据:可考虑马氏距离
# 完整距离计算模块 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种候选距离度量进行实验比较,最终根据模型表现确定最优方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 21:36:56

vLLM服务安全部署:集成Nginx与API Key认证的Docker镜像构建指南

1. 项目概述:为什么vLLM镜像需要身份认证?最近在部署和运维基于vLLM的大模型服务时,我遇到了一个非常典型且棘手的问题:如何安全地开放服务给外部调用?直接启动一个vLLM服务,默认情况下,其提供的…

作者头像 李华
网站建设 2026/7/4 21:35:25

STM32与25CSM04 EEPROM的高速数据检索优化实践

1. 项目背景与核心需求在嵌入式系统开发中,快速精确的数据检索是一个常见但极具挑战性的需求。25CSM04作为一款4Mb SPI接口的EEPROM存储器,与STM32F303VC这款Cortex-M4内核微控制器的组合,为解决这一问题提供了理想的硬件平台。我最近在一个工…

作者头像 李华
网站建设 2026/7/4 21:34:15

nwpu-cram之自然语言生成:文本摘要与对话系统全解析

nwpu-cram之自然语言生成:文本摘要与对话系统全解析 【免费下载链接】nwpu-cram 西北工业大学/西工大/nwpu/npu软件学院复习(突击)资料!! 项目地址: https://gitcode.com/GitHub_Trending/nw/nwpu-cram nwpu-cram是西北工业大学软件学…

作者头像 李华
网站建设 2026/7/4 21:32:30

零基础入门PE文件分析:readpe多平台安装与配置完全手册

零基础入门PE文件分析:readpe多平台安装与配置完全手册 【免费下载链接】readpe The PE file analysis toolkit 项目地址: https://gitcode.com/gh_mirrors/re/readpe 想要学习PE文件分析,但不知道从何开始?本文将为你详细介绍readpe工…

作者头像 李华
网站建设 2026/7/4 21:31:05

为什么选择Genome?探索Swift中失败驱动映射的完整解决方案

为什么选择Genome?探索Swift中失败驱动映射的完整解决方案 【免费下载链接】Genome A simple, type safe, failure driven mapping library for serializing JSON to models in Swift 3.0 (Supports Linux) 项目地址: https://gitcode.com/gh_mirrors/ge/Genome …

作者头像 李华
网站建设 2026/7/4 21:30:59

火山引擎Coding Plan抢购难?开发者API调用成本控制与多模型切换实战指南

火山引擎的 Coding Plan 套餐最近成了技术圈里的一个热门话题,不是因为功能有多惊艳,而是因为根本抢不到。连续几天都是“秒无货”的状态,这让很多想尝鲜或者有实际开发需求的开发者感到非常困惑和不满。一个背靠大公司的产品,在资…

作者头像 李华