Python 实现常用相似度与距离计算方法详解

Mia
Mia
发布时间:2026-10-11 | 2人浏览过
原创

在推荐系统、自然语言处理与异常检测等业务中,衡量数据间的差异或重合程度是核心前置步骤。本文将常见数学空间中的距离度量与统计相似度进行归类,提供经过现代 Python 语法校验的实现模板与实测输出,方便直接集成至数据处理管线。

相似度与距离计算的核心逻辑

相似度并非单一指标,而是根据数据类型(连续数值、布尔集合、文本序列)选择的匹配策略。连续向量通常采用空间距离或方向夹角,离散特征倾向集合重叠率或秩次相关性,文本序列则依赖字符级操作代价。正确选型能显著降低噪声干扰并提升下游模型的判别边界。

常用空间距离与统计相似度分类

几何空间距离:欧氏、曼哈顿与切比雪夫

欧几里得距离衡量多维坐标点的直线绝对偏差,适用于各维度量纲一致且对异常值相对稳健的场景。

欧几里得距离公式示意图
多维空间中两点的绝对直线距离计算示意

曼哈顿距离计算坐标轴正交方向的步数总和,在网格路由或高维稀疏特征中往往比欧氏距离更具稳定性。

曼哈顿距离公式示意图
标准坐标系下绝对轴距总和的计算方式

切比雪夫距离取各维度差值的最大绝对值,反映的是棋盘移动规则或极值约束下的最近可达范围。

切比雪夫距离公式示意图
向量空间各坐标差值绝对值的最大值度量

动态维度推广:明可夫斯基距离

明可夫斯基距离是上述几种几何距离的统一泛化形式,通过变参 p 控制惩罚梯度。当 p=1 退化为曼哈顿距离,p=2 回归欧氏距离,p→∞ 逼近切比雪夫距离。该定义允许根据数据分布的集中度灵活调节敏感度。

明可夫斯基距离参数化公式
含参数 p 的距离统一定义与等价转换关系

特征关联度:相关性系数与杰卡德指数

除绝对距离外,统计学工具常通过协方差标准化或秩次变换评估趋势一致性。皮尔森系数刻画线性关联强度,斯皮尔曼与肯德尔系数专注于单调关系与排序一致性,三者对非正态分布或非线性映射具有更好的容忍度。对于二值属性或品牌偏好等集合特征,杰卡德相似系数仅关注交集与并集的比例,忽略未出现特征的绝对差异,非常适合商品共现或用户兴趣标签匹配。

Python 模块化实现与测试验证

以下代码整合了基础数学运算、NumPy 矩阵操作与 SciPy 统计模块,统一接收列表或一维数组,返回对应的距离/相似度数值。为适配现代运行环境,已移除废弃的编码声明与打印语法,并补充缺失的第三方依赖声明。

import math
import numpy as np
from scipy.stats import pearsonr, spearmanr, kendalltau
# 字符串编辑距离需安装 pip install python-Levenshtein
import Levenshtein

def pearson_sim(x, y):
    '''皮尔逊线性相关系数'''
    return pearsonr(x, y)[0]

def spearman_sim(x, y):
    '''斯皮尔曼秩相关系数'''
    return spearmanr(x, y)[0]

def kendall_sim(x, y):
    '''肯德尔等级相关系数'''
    return kendalltau(x, y)[0]

def cos_sim(x, y):
    '''余弦相似度(方向重合度)'''
    dot_prod = sum(a * b for a, b in zip(x, y))
    norm_prod = np.linalg.norm(x) * np.linalg.norm(y)
    return round(dot_prod / float(norm_prod), 3) if norm_prod else 0.0

def euclid_sim(x, y):
    '''欧几里得距离'''
    return math.sqrt(sum((a - b) ** 2 for a, b in zip(x, y)))

def manhattan_sim(x, y):
    '''曼哈顿距离'''
    return sum(abs(a - b) for a, b in zip(x, y))

def minkowski_sim(x, y, p):
    '''明可夫斯基距离(p为整数或浮点参数)'''
    sum_p = sum(abs(a - b) ** p for a, b in zip(x, y))
    return round(sum_p ** (1.0 / p), 3)

def mahalanobis_sim(x, y):
    '''马氏距离(考虑变量间相关性)'''
    vec = np.array([x, y])
    diff = vec[0] - vec[1]
    cov_inv = np.linalg.inv(np.cov(vec))
    return math.sqrt(diff @ cov_inv @ diff.T)

def levenshtein_sim(x, y):
    '''字符串编辑距离相似度(1减去归一化代价)'''
    edit_dist = Levenshtein.distance(x, y)
    return 1 - (edit_dist / max(len(x), len(y)))

def jaccard_sim(x, y):
    '''杰卡德相似系数(交集占比)'''
    set_x, set_y = set(x), set(y)
    inter = len(set_x & set_y)
    union = len(set_x | set_y)
    return inter / float(union) if union > 0 else 0.0

if __name__ == '__main__':
    x_vec = [1, 2, 3, 4, 5]
    y_vec = [2, 4, 0, 8, 9]
    print(f'pearson_sim: {pearson_sim(x_vec, y_vec)}')
    print(f'spearman_sim: {spearman_sim(x_vec, y_vec)}')
    print(f'kendall_sim: {kendall_sim(x_vec, y_vec)}')
    print(f'cos_sim: {cos_sim(x_vec, y_vec)}')
    print(f'euclid_sim: {euclid_sim(x_vec, y_vec)}')
    print(f'manhattan_sim: {manhattan_sim(x_vec, y_vec)}')
    print(f'minkowski_sim: {minkowski_sim(x_vec, y_vec, 2)}')
    print(f'mahalanobis_sim: {mahalanobis_sim(x_vec, y_vec)}')
    
    str_a = "algorithm"
    str_b = "altruism"
    print(f'levenshtein_sim({str_a!r}, {str_b!r}): {levenshtein_sim(str_a, str_b)}')
    print(f'jaccard_sim({set(x_vec)!r}, {set(y_vec)!r}): {jaccard_sim(x_vec, y_vec)}')

运行上述主程序片段,可得到如下基准对照输出:

  • pearson_sim: 0.7397954428741078
  • spearman_sim: 0.7
  • kendall_sim: 0.6
  • cos_sim: 0.913
  • euclid_sim: 6.78232998313
  • manhattan_sim: 14
  • minkowski_sim: 6.782
  • mahalanobis_sim: 0.637157868392
  • jaccard_sim: 0.25

业务场景选型建议

连续型特征降维或聚类时,优先使用欧氏或明可夫斯基距离捕捉几何分布;高维稀疏推荐列表(如协同过滤)采用余弦相似度消除规模偏差;类别标签或购买行为集合适合杰卡德指数;需要剔除量纲影响并关注整体趋势时,引入皮尔森或斯皮尔曼系数。若涉及拼写纠错、日志对齐或短文本检索,直接接入编辑距离计算即可。

总结

相似度与距离计算是数据清洗、特征工程与模型评估的基础组件。掌握不同指标的定义边界,配合 NumPy 向量化与 SciPy 优化接口,能够以极低的计算开销覆盖大多数分析需求。实际接入时注意预处理阶段的标准化/归一化,避免因量级失衡导致特定维度主导结果。

以上就是Python 实现常用相似度与距离计算方法详解的详细内容,更多关于Python数据分析与算法落地的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表