向量数据库实战:选型、调优与落地~系列文章03:向量相似度算法全解:余弦、欧氏、内积,到底该用哪个?

向量相似度算法全解:余弦、欧氏、内积,到底该用哪个?🔢

🔥 本文是《向量数据库实战:选型、调优与落地》专栏第 03 篇

⏱️ 阅读时间:约 12 分钟


🎯 开篇:选错距离算法,效果差一半

上一篇我们聊了嵌入模型的选型,今天来聊另一个直接影响检索效果 的关键因素------相似度算法

很多人用向量数据库时,距离算法直接选默认值就不管了。这是一个巨大的隐患!

不同的距离算法适用于不同的场景,选错了,你的检索结果可能完全不对 😱


🧮 三大主流距离算法

1. 余弦相似度(Cosine Similarity)

核心思想:只看方向,不看长度。衡量两个向量的"夹角"有多接近。

复制代码
cos(θ) = (A · B) / (||A|| × ||B||)

取值范围:[-1, 1]
- 1  = 完全相同方向(最相似)
- 0  = 正交(无关)
- -1 = 完全相反方向(最不相似)

直观理解

复制代码
        场景 A:两向量方向一致,长度不同
        → 余弦相似度高(因为它们"说的是同一件事")
        
        例:
        A = [1, 2, 3]    (短文档)
        B = [10, 20, 30]  (长文档,内容相同)
        cos(A, B) = 1.0  ← 完全相同!✅

适用场景

  • 文本语义搜索(最常用!)
  • ✅ 文档长度不一致的场景
  • ✅ 大多数 Embedding 模型的默认选择

2. 欧氏距离(Euclidean Distance / L2)

核心思想:两点之间的直线距离。既看方向,也看长度。

复制代码
d(A, B) = √(Σ(Ai - Bi)²)

取值范围:[0, +∞)
- 0  = 完全相同(最相似)
- 越大 = 越不相似

直观理解

复制代码
        场景:两向量在空间中的"物理距离"
        
        例:
        A = [1, 2, 3]
        B = [1.1, 2.1, 3.1]  → 距离很近,约 0.17
        C = [5, 6, 7]        → 距离很远,约 6.93

适用场景

  • 图像特征匹配(像素级比较)
  • ✅ 向量已经归一化的场景(此时等价于余弦)
  • ✅ 需要同时考虑"方向"和"幅度"的场景

3. 内积(Inner Product / Dot Product)

核心思想:方向 × 长度的综合度量。

复制代码
IP(A, B) = A · B = Σ(Ai × Bi)

取值范围:(-∞, +∞)
- 越大 = 越相似

关键特性

复制代码
⚠️ 内积同时受方向和长度影响!

例:
A = [1, 2, 3]
B = [2, 4, 6]  → IP = 2+8+18 = 28(方向相同,长度大)
C = [1, 2, 3]  → IP = 1+4+9 = 14(方向相同,长度小)

B 和 C 方向完全相同,但 IP(A,B) > IP(A,C)
→ 内积认为 B 比 C 更相似!(因为 B 的"能量"更大)

适用场景

  • 推荐系统(用户-物品向量,长度代表热度/流行度)
  • ✅ 已归一化向量的快速计算(归一化后内积 = 余弦)
  • ✅ 需要同时考虑"语义"和"权重"的场景

📊 三大算法对比总结

对比维度 余弦相似度 欧氏距离(L2) 内积(IP)
计算方式 方向(夹角) 空间直线距离 方向 × 长度
是否受向量长度影响 ❌ 不受影响 ✅ 受影响 ✅ 受影响
值域 -1, 1 [0, +∞) (-∞, +∞)
值越大表示 越相似 相似 越相似
计算复杂度 中等(需归一化) 中等 最低
最常用场景 文本搜索 🏆 图像匹配 推荐系统
归一化后等价于 自身 余弦 余弦

🔑 一个重要的数学关系

当向量经过 L2 归一化后,三种算法完全等价!

复制代码
归一化:A' = A / ||A||

归一化后:
- 余弦(A', B') = 内积(A', B') 
- 欧氏距离(A', B') = √(2 - 2×余弦(A', B'))

→ 所以,如果你的向量已经归一化,选哪个算法都一样!

实际意义

复制代码
┌─────────────────────────────────────────────────────┐
│                                                     │
│  大部分 Embedding 模型输出的向量                      │
│  → 建议先做 L2 归一化                                │
│  → 然后统一用余弦相似度(或内积,结果一样)              │
│  → 这样不管换什么模型,距离计算逻辑都不用改              │
│                                                     │
└─────────────────────────────────────────────────────┘

💻 代码实战:三种算法的 Python 实现

python 复制代码
import numpy as np
from numpy.linalg import norm

# 示例向量
A = np.array([0.12, -0.34, 0.56, 0.78])
B = np.array([0.11, -0.32, 0.55, 0.79])
C = np.array([0.89, 0.12, -0.45, 0.03])

# 1. 余弦相似度
def cosine_similarity(a, b):
    return np.dot(a, b) / (norm(a) * norm(b))

# 2. 欧氏距离
def euclidean_distance(a, b):
    return norm(a - b)

# 3. 内积
def inner_product(a, b):
    return np.dot(a, b)

print("=== A vs B(语义相近)===")
print(f"余弦相似度: {cosine_similarity(A, B):.4f}")  # 接近 1
print(f"欧氏距离:   {euclidean_distance(A, B):.4f}")  # 接近 0
print(f"内积:       {inner_product(A, B):.4f}")

print("\n=== A vs C(语义无关)===")
print(f"余弦相似度: {cosine_similarity(A, C):.4f}")  # 接近 0
print(f"欧氏距离:   {euclidean_distance(A, C):.4f}")  # 较大
print(f"内积:       {inner_product(A, C):.4f}")

输出结果

复制代码
=== A vs B(语义相近)===
余弦相似度: 0.9994    ← 非常相似!
欧氏距离:   0.0224    ← 距离很近!
内积:       0.7465

=== A vs C(语义无关)===
余弦相似度: 0.0512    ← 几乎无关
欧氏距离:   1.2847    ← 距离很远!
内积:       0.0913

⚙️ 在各向量数据库中的配置

Milvus

python 复制代码
from pymilvus import CollectionSchema, FieldSchema

# 创建集合时指定度量类型
index_params = {
    "metric_type": "COSINE",   # 可选:COSINE / L2 / IP
    "index_type": "HNSW",
    "params": {"M": 16, "efConstruction": 256}
}

Qdrant

python 复制代码
from qdrant_client.models import VectorParams, Distance

# Qdrant 用 Distance 枚举
collection_params = VectorParams(
    size=1024,
    distance=Distance.COSINE  # 可选:COSINE / EUCLID / DOT
)

Chroma

python 复制代码
import chromadb

# Chroma 默认就是余弦相似度
client = chromadb.Client()
collection = client.create_collection(
    name="my_collection",
    metadata={"hnsw:space": "cosine"}  # 可选:cosine / l2 / ip
)

💡 选型建议:到底该用哪个?

复制代码
你的向量是否已经归一化?
│
├── ✅ 是 → 选 COSINE 或 IP(结果一样,COSINE 更直观)
│
└── ❌ 否
    │
    ├── 文本搜索场景 → 先归一化,再用 COSINE
    ├── 图像匹配场景 → 用 L2(保留幅度信息)
    ├── 推荐系统场景 → 用 IP(长度代表权重)
    └── 不确定 → 用 COSINE(最安全的选择)🏆

我的经验法则

场景 推荐算法 理由
RAG 知识库 COSINE 文本语义搜索的标准选择
以图搜图 L2 图像特征需要保留幅度
推荐召回 IP 向量长度代表流行度/权重
去重/查重 COSINE 只关心内容是否相似
异常检测 L2 需要检测"偏离正常"的程度

⚠️ 常见误区

误区 1:"余弦相似度一定比欧氏距离好"

错! 关键看场景。图像匹配中,像素强度的绝对差异很重要,L2 更合适。

误区 2:"内积和余弦是一样的"

不完全对! 只有归一化后才等价。未归一化时,内积受向量长度影响,余弦不受。

误区 3:"默认值就行,不用改"

危险! 不同数据库的默认值不同:

  • Milvus 默认 L2
  • Qdrant 默认 COSINE(创建时需指定)
  • Chroma 默认 COSINE

一定要根据你的场景显式指定!


🔑 本篇核心要点回顾

要点 说明
余弦相似度 只看方向不看长度,文本搜索首选
欧氏距离 看方向也看长度,图像匹配常用
内积 方向×长度,推荐系统常用
归一化后三者等价 建议先归一化再统一用余弦
一定要显式指定 不要依赖默认值

✍️ 写在最后

相似度算法的选择看似简单,实则直接影响检索质量

记住一句话

文本场景 → 归一化 → 余弦相似度

这一招能覆盖 80% 的场景。剩下 20% 的特殊需求,再根据本文的决策树选择。


📌 下篇预告:《HNSW 索引深度剖析:为什么它是向量检索的"王者算法"?👑》

💬 有问题欢迎评论区讨论,觉得有用请点赞收藏 👍

作者:高炉炼铁智能化技术研究者,专注钢铁冶金与人工智能 交叉领域。

👍 如果觉得有帮助,请点赞、收藏、转发!

版权归作者所有,未经许可请勿抄袭,套用,商用(或其它具有利益性行为)

🔔 关注专栏,不错过后续精彩内容

相关推荐
神奇小汤圆16 小时前
为什么 skills 装得越多,AI 越笨?最火的那个 skill 只有一句话
人工智能
毛丫讲绘本16 小时前
独立老师开始做绘本课,怎样做少走弯路?
人工智能·学习·微信·微信公众平台·微信开放平台
weixin_4684668516 小时前
从Transformer到ViT与Swin详解
人工智能·深度学习·transformer·computer vision·vit·卷积·swin
新知图书16 小时前
详细实现与核心配置(新闻早报智能体开发)
人工智能·agent·ai agent·智能体·扣子
Lorin 洛林17 小时前
OpenClaw:跳出聊天框,拥有自主行动力的 AI 智能体
人工智能
rain_sxr17 小时前
大规模数据可视化渲染:D3 与 ECharts 的管线优化实战
人工智能
大海变好AI17 小时前
AIGC分层推理落地能否串联多工具完成自动化闭环
人工智能·python·自动化·aigc
Cosolar17 小时前
AI Agent 架构原理详解:从一次提问到任务完成的完整闭环
人工智能·后端·架构
小白说大模型17 小时前
从向量嵌入到复杂 Agent:LLM、LangChain、LangGraph 完整科普
java·开发语言·人工智能·gpt·深度学习·langchain