最后更新:2026-09-26
下面六种度量用来比较两个向量或两个集合有多近、多像。前三种是距离(越小越近),后两种相似度越大越像,汉明距离则数对应位置上有几处不同。
曼哈顿距离又称为城市街区距离(Manhattan distance 或 city block distance),是计算两个向量之间距离的一种方法。计算方法是把两个向量每个对应元素之差的绝对值相加,如式(7-5):
常见用法:
def manhattan_distance(x, y):
# 对应分量差的绝对值求和
return sum(abs(a - b) for a, b in zip(x, y))
x = [1, 2, 3]
y = [4, 5, 6]
print(manhattan_distance(x, y)) # 9
x、y 是两个向量;zip 把对应元素配成一对;abs 取差的绝对值;sum 再把它们加起来。结果是 9,因为 \(\lvert 1-4\rvert+\lvert 2-5\rvert+\lvert 3-6\rvert=3+3+3=9\)。
欧氏距离(Euclidean distance)是两点之间的直线距离。对向量 \(x\) 与 \(y\),公式如式(7-6):
它衡量欧几里得空间里两个向量的距离,常当作相似度,也当作模型评估指标。
import math
def euclidean_distance(x, y):
# 对应分量差的平方和,再开方
return math.sqrt(sum((a - b) ** 2 for a, b in zip(x, y)))
x = [1, 2, 3]
y = [4, 5, 6]
print(euclidean_distance(x, y)) # sqrt(27) ≈ 5.196
** 2 是差的平方,sum 把平方加总,math.sqrt 开方。同一对向量 \([1,2,3]\) 与 \([4,5,6]\) 的欧氏距离是 \(\sqrt{3^{2}+3^{2}+3^{2}}=\sqrt{27}\)。
闵可夫斯基距离(Minkowski distance)是上面两种距离的一般形式。对向量 \(x\) 与 \(y\),公式如式(7-7):
当 \(p=1\) 时就是曼哈顿距离;当 \(p=2\) 时就是欧氏距离。
import math
def minkowski_distance(x, y, p):
# 差的绝对值的 p 次方求和,再开 p 次方
return math.pow(sum(abs(a - b) ** p for a, b in zip(x, y)), 1 / p)
x = [1, 2, 3]
y = [4, 5, 6]
print(minkowski_distance(x, y, 1)) # 9,与曼哈顿距离相同
print(minkowski_distance(x, y, 2)) # ≈ 5.196,与欧氏距离相同
abs 取绝对值,** p 做 \(p\) 次方,sum 相加,math.pow(..., 1/p) 开 \(p\) 次方根。
机器学习里常见三种用法:
\(p\) 取多少取决于具体问题和数据。需要按实际情况选距离,不能固定用一种。
夹角余弦衡量两个向量方向有多一致,常用于文本分类和推荐。它不看向量有多长,只看夹角。对向量 \(x\) 与 \(y\),公式如式(7-8):
取值越接近 \(1\),夹角越小,方向越一致,越相似;越接近 \(0\) 或为负,越不相似。
import math
def cosine_similarity(x, y):
# 点积除以两个向量的模长
numerator = sum(a * b for a, b in zip(x, y))
denominator = math.sqrt(sum(a ** 2 for a in x)) * math.sqrt(sum(b ** 2 for b in y))
return numerator / denominator
x = [1, 2, 3]
y = [4, 5, 6]
print(cosine_similarity(x, y)) # 32 / sqrt(14*77) ≈ 0.975
zip 对齐分量,* 逐项相乘,sum 得到点积;math.sqrt 分别算出两个模长,再相除。
汉明距离(Hamming distance)衡量两个等长字符串的距离,等于对应位置上字符不同的个数。
def hamming_distance(a, b):
# 等长序列里,数对应位置不相等的个数
return sum(1 for i in range(len(a)) if a[i] != b[i])
s1 = "10101010"
s2 = "11110000"
print(hamming_distance(s1, s2)) # 4
函数接收两个等长字符串。s1 与 s2 在第 2、4、5、7 位不同,距离为 4。
杰卡德相似系数(Jaccard similarity coefficient)衡量两个集合有多像:共同元素占全部不重复元素的比例。主要用于文本、标签这类非数值数据。对集合 \(A\) 与 \(B\):
下面的代码算的是相似系数 \(J(A,B)\),不是距离。
def jaccard_similarity(set1, set2):
# 交集大小除以并集大小
intersection = len(set1.intersection(set2))
union = len(set1.union(set2))
return intersection / union
set1 = set([1, 2, 3, 4, 5])
set2 = set([3, 4, 5, 6, 7])
print(jaccard_similarity(set1, set2)) # 3/7 ≈ 0.429
交集是 \(\{3,4,5\}\),大小为 3;并集是 \(\{1,2,3,4,5,6,7\}\),大小为 7,所以相似系数是 \(3/7\approx 0.429\)。
图像分类只输出类别和置信度,例如「船 0.9、车 0.1」。目标检测还要给出矩形框 \((x_1,y_1,x_2,y_2)\)。评价检测结果时,先看框是否对准,再看类别是否判对。下面是常用的 9 个指标。
后几项用到混淆矩阵里的四个计数:
IOU(intersection over union,交并比)用来评价两个矩形框有多重合:
浅色框是检测结果,深色框是真实标注。判定检测框时要设一个 IOU 阈值,一般取 \(0.5\):IOU 大于 \(0.5\),就认为检测到了目标。
准确率(accuracy)是被分对的样本数除以全部样本数。越高,分类器越好。如式(8-1):
分子是预测正确的正样本与预测正确的负样本之和,分母是总样本个数。
精度(precision)从预测结果来看:预测为正的样本里,有多少个真是正样本,也就是「找得对」的比例。如式(8-2):
\(\mathrm{TP}+\mathrm{FP}\) 是所有被预测为正的样本,\(\mathrm{TP}\) 是其中预测正确的正样本个数。
召回率(recall)和灵敏度(true positive rate,TPR,真正例率)是同一个概念。它从真实样本来看:全部正样本里,模型找回了多少,也就是「找得全」的比例。如式(8-3):
\(\mathrm{TP}+\mathrm{FN}\) 是所有真正的正样本,\(\mathrm{TP}\) 是预测正确的正样本个数。
FPR(false positive rate,假正例率)是实际负例里被错误判成正例的比例。这个值越小越好。如式(8-4):
\(\mathrm{FP}+\mathrm{TN}\) 是全部负样本,\(\mathrm{FP}\) 是被判成正样本的负样本。
F1 分数把召回率和精度看成同等重要,是二者的调和平均数。多分类竞赛里常把它当作最终测评。最小为 \(0\),最大为 \(1\)。如式(8-5):
它与精度、召回率的关系是
AUC 是 area under curve 的缩写,即 ROC(受试者工作特征)曲线下的面积,介于 \(0\) 和 \(1\) 之间。计算上就是这条曲线的积分。
随机抽一个正样本和一个负样本,AUC 等于正样本排在负样本前面的概率。AUC 越大,正样本越容易排在负样本前面,分类越好。
AP(average precision,平均精度)是在不同召回率点上对精度取平均。AP 越大,这一类的平均精度越高。
mAP 是 mean average precision(平均精度均值):各类别 AP 的平均。它衡量模型在所有类别上的好坏,是目标检测里最重要的指标之一。取值在 \(0\) 到 \(1\) 之间,越大越好。
其中 \(C\) 是类别数,\(\mathrm{AP}_{c}\) 是第 \(c\) 类的平均精度。