四、距离计算方式

距离计算方式

(一)欧式距离

1. 定义

欧式距离是最常见的距离度量方法,也称为直线距离

在二维空间中,欧式距离计算两点之间的直线距离

2. 公式

\[\sqrt{\sum_{i=1}^{n}(x_i - y_i)^2} ==> \sum_{i=1}^{n}(x_i - y_i)^2 \]

3. 缺点

在使用此距离度量之前,需要对数据进行标准化

随着数据维数的增加,欧氏距离的用处也就越小

4. 代码

import math

# 新建两个点
x = [1,2]
y = [4,6]

# 欧式距离
def euclidean_distance(x,y):
    l = [(a-b)**2 for a,b in zip(x,y)]
    return math.sqrt(sum(l))

print("欧式距离:",euclidean_distance(x,y))

(二)曼哈段距离

1. 定义

曼哈顿距离是计算两点之间水平或垂直线段的距离之和,也称为城市街区距离或 L1 距离

2. 公式

\[\sum_{i=1}^{n} |x_i - y_i| \]

3. 缺点

由于它不是可能的最短路径,它比欧几里得距离更有可能给出一个更高的距离值

随着数据维数的增加,曼哈顿距离的用处也就越小

4. 代码

import math

# 新建两个点
x = [1,2]
y = [4,6]

# 曼哈顿距离
def manhattan_distance(x,y):
    l = [abs(a - b) for a,b in zip(x, y)]
    return sum(l)

print("曼哈顿距离:",manhattan_distance(x,y))

(三)切比雪夫距离

1. 定义

切比雪夫距离是计算两点在各个坐标上的差的绝对值的最大值

【计算 Δx 和 Δy,取最大的值】

2. 公式

\[\max\limits_{i=1}^{n} |x_i - y_i| \]

3. 缺点

切比雪夫通常用于非常特定的用例,这使得它很难像欧氏距离那样作通用的距离度量

4. 代码

import math

# 新建两个点
x = [1,2]
y = [4,6]

# 切比雪夫距离
def chebyshev_distance(x,y):
    l = [abs(a - b) for a,b in zip(x, y)]
    return max(l)

print("切比雪夫距离:",chebyshev_distance(x,y))

(四)余弦相似度

1. 定义

余弦相似度是两个向量之间的夹角余弦值,表示两个向量的方向差异,而不是长度差异

2. 公式

\[\frac{\sum_{i=1}^{n} x_i \cdot y_i}{\sqrt{\sum_{i=1}^{n} x_i^2} \cdot \sqrt{\sum_{i=1}^{n} y_i^2}} \]

3. 缺点

余弦相似度无法捕捉向量的幅度信息,只考虑方向

4. 代码

import math

# 新建两个点
x = [1,2]
y = [4,6]

# 余弦相似度
def cosine_similarity(x,y):
    # 分子
    numerator = sum([a*b for a,b in zip(x,y)])
    # 分母
    denominator1 = math.sqrt(sum(a**2 for a in x))
    denominator2 = math.sqrt(sum(b**2 for b in y))
    # 返回结果
    return numerator/(denominator1*denominator2)

print("余弦相似度:",cosine_similarity(x,y))

(五)汉明距离

1. 定义

汉明距离用于衡量两个等长字符串在相同位置上不同字符的个数

2. 公式

\[\sum_{i=1}^{n} \text{int}(x_i \neq y_i) \]

3. 缺点

当两个向量的长度不相等时,很难使用汉明距离

4. 代码

# 汉明距离
def hamming_distance(x_str,y_str):
    return sum(a!=b for a,b in zip(x_str,y_str))

x_str = "101100"
y_str = "110101"
print("汉明距离:",hamming_distance(x_str,y_str))

(六)闵可夫斯基距离

1. 定义

闵可夫斯基距离是欧式距离和曼哈顿距离的泛化

  • p=1 -- 曼哈顿距离
  • p=2 -- 欧氏距离
  • p=∞ -- 切比雪夫距离

2. 公式

\[\left( \sum_{i=1}^{n} |x_i - y_i|^p \right)^{\frac{1}{p}} \]

3. 缺点

使用参数 p 实际上可能很麻烦

4. 代码

import math

# 新建两个点
x = [1,2]
y = [4,6]

# 闵可夫斯基距离
def minkowski_distance(x,y,p):
    l = [abs(a - b)**p for a,b in zip(x, y)]
    return sum(l)**(1/p)

p = 100
print("闵可夫斯基距离:",minkowski_distance(x,y,p))

(七)Jaccard 指数

1. 定义

Jaccard(杰卡德)指数用于计算两个集合的相似度

2. 公式

\[\frac{|X \cap Y|}{|X \cup Y|} \]

3. 缺点

它受到数据大小的很大影响

大型数据集可能会对指数产生很大影响,因为数据量大的话可能显著增加并集,同时保持交集不变

4. 代码

# Jaccard指数
def jaccard_index(x_set,y_set):
    # 交集
    intersection = len(set(x_set & y_set))
    # 并集
    union = len(set(x_set | y_set))
    # 返回结果
    return intersection/union

x_set = {1,2,3}
y_set = {2,3,4}
print("Jaccard指数:",jaccard_index(x_set,y_set))

(八)半正矢距离

1. 定义

用于地理坐标系统中两个经纬度点之间的距离

2. 公式

\[d = 2R \arcsin\left( \sqrt{\sin^2\left(\frac{\phi_2 - \phi_1}{2}\right) + \cos(\phi_1)\cos(\phi_2)\sin^2\left(\frac{\lambda_2 - \lambda_1}{2}\right)} \right) \]

d :是两点之间的半正矢距离

R :是地球的半径

Φ₁ 和 Φ₂ :是第一点和第二点的纬度

λ₁ 和 λ₂ :是第二点和第二点的经度以弧度表示。

3. 缺点

切比雪夫通常用于非常特定的用例,这使得它很难像欧氏距离那样作通用的距离度量

4. 代码

# 正半矢距离
def haversine_distance(lat1,lon1,lat2,lon2):
    # 地球半径 6371 km
    R = 6371.0

    # 将十进制转成弧度
    lat1 = math.radians(lat1)
    lat2 = math.radians(lat2)
    lon1 = math.radians(lon1)
    lon2 = math.radians(lon2)

    # 求经纬度的差值
    dlat = lat2 - lat1
    dlon = lon2 - lon1

    # 计算距离
    part1 = math.sin(dlat/2)**2
    part2 = math.cos(lat1) * math.cos(lat2)
    part3 = math.sin(dlon/2)**2
    part4 = math.sqrt(part1 + part2 * part3)
    d = 2 * R * math.asin(part4)

    # 返回结果
    return d

lat1,lon1 = 52.2296756,21.0122287   # 华沙的经纬度
lat2,lon2 = 51.5073509,-0.1277583   # 伦敦的经纬度
print("正半矢距离:",haversine_distance(lat1,lon1,lat2,lon2))
posted @ 2026-11-03 20:07  桑年  阅读(9)  评论(0)    收藏  举报