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

📅 2026/7/16 16:04:28
向量数据库实战:选型、调优与落地~系列文章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 2818 28方向相同长度大 C [1, 2, 3] → IP 149 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 实现importnumpyasnpfromnumpy.linalgimportnorm# 示例向量Anp.array([0.12,-0.34,0.56,0.78])Bnp.array([0.11,-0.32,0.55,0.79])Cnp.array([0.89,0.12,-0.45,0.03])# 1. 余弦相似度defcosine_similarity(a,b):returnnp.dot(a,b)/(norm(a)*norm(b))# 2. 欧氏距离defeuclidean_distance(a,b):returnnorm(a-b)# 3. 内积definner_product(a,b):returnnp.dot(a,b)print( A vs B语义相近)print(f余弦相似度:{cosine_similarity(A,B):.4f})# 接近 1print(f欧氏距离:{euclidean_distance(A,B):.4f})# 接近 0print(f内积:{inner_product(A,B):.4f})print(\n A vs C语义无关)print(f余弦相似度:{cosine_similarity(A,C):.4f})# 接近 0print(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⚙️ 在各向量数据库中的配置MilvusfrompymilvusimportCollectionSchema,FieldSchema# 创建集合时指定度量类型index_params{metric_type:COSINE,# 可选COSINE / L2 / IPindex_type:HNSW,params:{M:16,efConstruction:256}}Qdrantfromqdrant_client.modelsimportVectorParams,Distance# Qdrant 用 Distance 枚举collection_paramsVectorParams(size1024,distanceDistance.COSINE# 可选COSINE / EUCLID / DOT)Chromaimportchromadb# Chroma 默认就是余弦相似度clientchromadb.Client()collectionclient.create_collection(namemy_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 默认 L2Qdrant 默认 COSINE创建时需指定Chroma 默认 COSINE一定要根据你的场景显式指定 本篇核心要点回顾要点说明余弦相似度只看方向不看长度文本搜索首选欧氏距离看方向也看长度图像匹配常用内积方向×长度推荐系统常用归一化后三者等价建议先归一化再统一用余弦一定要显式指定不要依赖默认值✍️ 写在最后相似度算法的选择看似简单实则直接影响检索质量。记住一句话文本场景 → 归一化 → 余弦相似度这一招能覆盖 80% 的场景。剩下 20% 的特殊需求再根据本文的决策树选择。下篇预告《HNSW 索引深度剖析为什么它是向量检索的王者算法》有问题欢迎评论区讨论觉得有用请点赞收藏 作者高炉炼铁智能化技术研究者专注钢铁冶金与人工智能 交叉领域。 如果觉得有帮助请点赞、收藏、转发版权归作者所有未经许可请勿抄袭套用商用(或其它具有利益性行为)。 关注专栏不错过后续精彩内容