1. 距离度量的数学基础
距离度量是机器学习中衡量样本相似性的核心工具。想象一下,你要在超市里找到和手中苹果最相似的水果,大脑会不自觉比较颜色、形状、大小等特征——这本质上就是在计算"距离"。数学上,一个合格的距离函数需要满足四个基本公理:
- 非负性:距离最小为零,就像两个完全相同的苹果
- 同一性:距离为零当且仅当两个对象完全一致
- 对称性:从A到B的距离等于从B到A的距离
- 三角不等式:绕路总比直走远,就像在超市里绕开货架取水果
这些看似简单的规则,却构建了机器学习中各种距离度量的理论基础。我在处理电商推荐系统时,就遇到过违反对称性的案例——用户A喜欢B的商品列表,但B却对A的喜好无感,这时就需要调整距离计算方式。
2. 欧氏空间的距离家族
2.1 经典欧几里得距离
最熟悉的直线距离公式,源自初中几何:
import numpy as np def euclidean(a, b): return np.sqrt(np.sum((a - b)**2))这个距离对异常值非常敏感。记得有次分析用户行为数据,一个极端值就让整个聚类结果失真。这时可以考虑先做标准化处理:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaled_data = scaler.fit_transform(raw_data)2.2 曼哈顿距离的现实意义
在纽约曼哈顿街区,你不能穿楼而过,只能沿着街道直角行走。这种网格路径的距离就是:
def manhattan(a, b): return np.sum(np.abs(a - b))实测在分析稀疏的高维文本数据时,曼哈顿距离比欧氏距离更稳定。我曾用它改进过新闻分类算法,准确率提升了7%。
2.3 闵可夫斯基距离的统一视角
这其实是个距离家族,通过参数p调节:
def minkowski(a, b, p): return np.power(np.sum(np.power(np.abs(a - b), p)), 1/p)当p=1时退化为曼哈顿距离,p=2就是欧氏距离,p趋近无穷大则变成切比雪夫距离。选择适合的p值很关键——在图像匹配项目中,我们通过交叉验证发现p=1.5时效果最佳。
3. 特殊场景的距离度量
3.1 文本处理的余弦相似度
比较两篇文章的相似度,更关注方向而非长度:
from sklearn.metrics.pairwise import cosine_similarity cos_sim = cosine_similarity([text_vec1], [text_vec2])[0][0]处理知乎问答匹配时,余弦相似度比欧氏距离更适合衡量文本语义相似性。但要注意停用词处理——有次因为"的""了"等词干扰,导致结果异常。
3.2 概率分布的KL散度
当需要比较两个概率分布的差异时:
from scipy.stats import entropy kl_div = entropy(p_dist, q_dist)在构建推荐系统的多样性模块时,我们用KL散度平衡推荐结果的集中度和覆盖率。但要注意它不是真正的距离——不满足对称性。
3.3 时间序列的DTW距离
语音识别中处理不同长度的序列:
from dtaidistance import dtw distance = dtw.distance(series1, series2)这个算法能弹性对齐时间轴,在分析股票走势相似性时特别有用。但计算复杂度较高,需要适当设置窗口约束。
4. 实践中的选择策略
4.1 数据特性决定距离选择
- 低维稠密数据:欧氏距离
- 高维稀疏数据:余弦相似度
- 分类特征:汉明距离
- 概率分布:KL散度或JS散度
- 时间序列:DTW距离
曾有个医疗数据集同时包含数值型检查指标和分类型症状描述,我们最终采用了马氏距离结合杰卡德系数的混合度量方式。
4.2 距离矩阵的优化计算
当数据量很大时,直接计算所有样本对的距离会非常耗时。可以使用以下优化:
from scipy.spatial.distance import pdist, squareform dist_matrix = squareform(pdist(data, 'euclidean'))或者更高效的BallTree:
from sklearn.neighbors import BallTree tree = BallTree(data, metric='haversine')4.3 常见陷阱与解决方案
- 维度灾难:高维时所有样本距离趋同,可用降维或子空间学习
- 量纲差异:记得做标准化或归一化
- 计算效率:近似算法或采样计算
- 语义匹配:单纯数值距离可能不符合业务逻辑
在金融风控项目中,我们就因为没考虑特征间的业务相关性,导致距离度量失效。后来引入领域知识重新设计距离函数才解决问题。