四、距离计算方式
距离计算方式
(一)欧式距离
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))
本文来自博客园,作者:桑年,转载请注明原文链接:https://www.cnblogs.com/clover-1105/p/23539238

浙公网安备 33010602011771号