视觉相似度计算算法详解:余弦、欧氏、曼哈顿距离对比

📅 2025-09-18 | 👁️ 2.1K | ⏱️ 12分钟

一、为什么需要相似度计算

在图像搜索系统中,我们将图像转换为特征向量后,需要计算两个向量之间的相似程度。选择合适的相似度度量方法直接影响搜索结果的准确性和效率。

二、三大核心算法

1. 余弦相似度(Cosine Similarity)

核心思想:计算两个向量之间的夹角余弦值,关注方向而非大小。

数学公式:

cos(θ) = (A · B) / (||A|| × ||B||) 范围:[-1, 1],值越大越相似

Python实现:

import numpy as np def cosine_similarity(vec1, vec2): dot_product = np.dot(vec1, vec2) norm1 = np.linalg.norm(vec1) norm2 = np.linalg.norm(vec2) return dot_product / (norm1 * norm2) # 示例 a = np.array([1, 2, 3]) b = np.array([2, 4, 6]) print(f"余弦相似度: {cosine_similarity(a, b):.4f}") # 输出: 1.0000

优点:

缺点:

适用场景:

2. 欧氏距离(Euclidean Distance)

核心思想:计算两点在空间中的直线距离,最直观的距离度量。

数学公式:

d = √(Σ(ai - bi)²) 范围:[0, +∞),值越小越相似

Python实现:

import numpy as np def euclidean_distance(vec1, vec2): return np.sqrt(np.sum((vec1 - vec2) ** 2)) # 或使用scipy from scipy.spatial.distance import euclidean distance = euclidean(vec1, vec2) # 示例 a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(f"欧氏距离: {euclidean_distance(a, b):.4f}") # 输出: 5.1962

优点:

缺点:

适用场景:

3. 曼哈顿距离(Manhattan Distance)

核心思想:计算两点在各维度上差值的绝对值之和,类似城市街区距离。

数学公式:

d = Σ|ai - bi| 范围:[0, +∞),值越小越相似

Python实现:

import numpy as np def manhattan_distance(vec1, vec2): return np.sum(np.abs(vec1 - vec2)) # 或使用scipy from scipy.spatial.distance import cityblock distance = cityblock(vec1, vec2) # 示例 a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(f"曼哈顿距离: {manhattan_distance(a, b):.4f}") # 输出: 9.0000

优点:

缺点:

适用场景:

三、算法对比

算法 计算复杂度 归一化需求 高维表现 异常值敏感度
余弦相似度 O(n) 不需要 优秀
欧氏距离 O(n) 需要 一般
曼哈顿距离 O(n) 需要 良好

四、实战案例对比

使用三种算法对同一组图像特征进行相似度计算:

import numpy as np from scipy.spatial.distance import cosine, euclidean, cityblock # 模拟CLIP特征向量(512维) query = np.random.randn(512) image1 = query + np.random.randn(512) * 0.1 # 相似图像 image2 = np.random.randn(512) # 不相似图像 # 余弦相似度(值越大越相似) cos_sim1 = 1 - cosine(query, image1) cos_sim2 = 1 - cosine(query, image2) print(f"余弦相似度 - 图像1: {cos_sim1:.4f}, 图像2: {cos_sim2:.4f}") # 欧氏距离(值越小越相似) euc_dist1 = euclidean(query, image1) euc_dist2 = euclidean(query, image2) print(f"欧氏距离 - 图像1: {euc_dist1:.4f}, 图像2: {euc_dist2:.4f}") # 曼哈顿距离(值越小越相似) man_dist1 = cityblock(query, image1) man_dist2 = cityblock(query, image2) print(f"曼哈顿距离 - 图像1: {man_dist1:.4f}, 图像2: {man_dist2:.4f}")

五、如何选择

场景1:深度学习特征向量(CLIP、ResNet)

推荐:余弦相似度

场景2:低维特征(颜色、纹理)

推荐:欧氏距离

场景3:稀疏高维向量

推荐:曼哈顿距离

场景4:实时搜索系统

推荐:余弦相似度 + FAISS优化

六、性能优化技巧

1. 向量归一化

# 归一化后,余弦相似度 = 点积 normalized_vec = vec / np.linalg.norm(vec) similarity = np.dot(normalized_vec1, normalized_vec2)

2. 批量计算

# 使用矩阵运算加速 from sklearn.metrics.pairwise import cosine_similarity similarities = cosine_similarity(query_vectors, database_vectors)

3. FAISS加速

import faiss # 使用内积搜索(等价于余弦相似度,需先归一化) index = faiss.IndexFlatIP(dimension) index.add(normalized_vectors) distances, indices = index.search(query, k=10)

七、总结

三种相似度算法各有优劣:

我们的系统采用余弦相似度结合FAISS优化,在百万级图片库中实现毫秒级搜索。立即体验