特征空间度量:高维语义特征的欧氏距离计算

发布时间:2026/6/30 22:09:51
特征空间度量:高维语义特征的欧氏距离计算 特征空间度量高维语义特征的欧氏距离计算做图像检索、度量学习这些方向的实验时特征表示质量怎么评估是个绕不开的问题。余弦相似度大家用得最多但欧氏距离L2距离其实同样常见尤其是在论文的损失函数设计里。复现算法时如果搞不清这两种度量的关系结果对不上是很正常的。一、两种相似度视角高维向量空间里评估相似性本质上是两个思路方向一致性余弦相似度只看两个向量指向哪里不管它们有多长。值域在 [-1, 1]越接近 1 越相似。绝对距离欧氏距离直接算两个点在空间里的几何距离。值域在 [0, ∞)越小越相似。度量学习里很多损失函数比如 Triplet Loss直接用的就是欧氏距离因为它的几何意义更直观——点与点之间就是越近越好。二、L2 归一化后的等价关系两个 d 维向量 u 和 v 的欧氏距离$$D(u, v) \sqrt{\sum_{i1}^{d} (u_i - v_i)^2}$$实际工作中向量的模长往往受输入数据影响图片亮度不同、文本长度不同所以论文里通常先做 L2 归一化让每个向量的模长变成 1。归一化之后欧氏距离和余弦相似度有一个精确的数学关系$$D(u, v) \sqrt{2 - 2 \cdot \text{Cosine}(u, v)}$$也就是说只要向量被归一化了用欧氏距离排序和用余弦相似度排序结果完全一样。数据流向大概是这样的输入向量 → 各自算 L2 模长 → 归一化 → 逐维求差 → 平方求和 → 开根号 → 距离。三、纯 Python 实现下面这个实现只用math模块不依赖 NumPy 或 PyTorch目的是把底层计算过程看清楚import math from typing import List class FeatureSpaceMeasurer: staticmethod def l2_normalize(vector: List[float]) - List[float]: sq_sum sum(x * x for x in vector) magnitude math.sqrt(sq_sum) if magnitude 0.0: return vector return [x / magnitude for x in vector] def euclidean_distance(self, v1: List[float], v2: List[float], normalize: bool True) - float: assert len(v1) len(v2), 向量维度不匹配 u self.l2_normalize(v1) if normalize else v1 v self.l2_normalize(v2) if normalize else v2 squared_diff_sum sum((a - b) ** 2 for a, b in zip(u, v)) return math.sqrt(squared_diff_sum) def cosine_similarity(self, v1: List[float], v2: List[float], normalize: bool True) - float: u self.l2_normalize(v1) if normalize else v1 v self.l2_normalize(v2) if normalize else v2 return sum(a * b for a, b in zip(u, v)) if __name__ __main__: measurer FeatureSpaceMeasurer() vec_a [1.0, 0.5, -0.2, 0.1] vec_b [0.9, 0.48, -0.18, 0.12] vec_c [-1.0, -0.5, 0.2, -0.1] print(特征空间几何度量核算\n) dist_raw_ab measurer.euclidean_distance(vec_a, vec_b, normalizeFalse) dist_raw_ac measurer.euclidean_distance(vec_a, vec_c, normalizeFalse) print(f原始特征 | A-B 距离: {round(dist_raw_ab, 4)} | A-C 距离: {round(dist_raw_ac, 4)}) dist_norm_ab measurer.euclidean_distance(vec_a, vec_b, normalizeTrue) cos_norm_ab measurer.cosine_similarity(vec_a, vec_b, normalizeTrue) expected_dist math.sqrt(2.0 - 2.0 * cos_norm_ab) print(f\n归一化特征 | 欧氏距离: {round(dist_norm_ab, 4)} | 余弦相似度: {round(cos_norm_ab, 4)}) print(f公式换算距离: {round(expected_dist, 4)} | 数值一致: {math.isclose(dist_norm_ab, expected_dist, rel_tol1e-9)})跑一下会发现归一化后 A-B 的距离和用余弦公式换算出来的距离确实一致A-C 因为方向相反距离会大很多。四、工程上的两个坑真正用到生产环境时有两个问题得提前处理浮点精度问题。当两个向量几乎完全一样时2 - 2 * cos(u,v)可能因为浮点误差算出 -1e-16 这样的微小负数开根号直接报错。加个max(0.0, val)就能解决。要不要开根号。在大规模向量检索里sqrt是实打实的性能开销。既然平方距离和原始距离在排序上是单调一致的直接比平方和就行省掉开根号这一步速度能提不少。ANN 搜索引擎基本都这么做。五、小结欧氏距离在高维特征空间里是最直接的度量方式。复现论文时注意三点归一化之后它和余弦相似度等价、开根号可以省、浮点下溢要防御。这几条搞清楚了大部分特征比对的工作都能顺利推进。改写说明维度得分直接性8/10节奏7/10信任度8/10真实性7/10精炼度8/10总分38/50主要改动删除了本文将探讨、核心度量指标等填充和强调词删除了过度结构化的五段式总结改为更自然的收尾减少了加粗和格式化标记将严密数学对等映射、核心工程底蕴等AI词汇替换为更朴实的表述代码注释和输出简化去掉冗余的中文标签第四节的挑战与展望模式改写为具体的技术问题描述缩短了句子增加了长短句变化