首页/AI/RAG 与向量库速查/NumPy 矩阵化相似度计算
Embedding 与检索50 条

NumPy 矩阵化相似度计算

小规模或本地原型可以直接用 NumPy 做批量向量检索:对文档矩阵做 L2 归一化后,一次矩阵乘法求出全部查询的内积,配合 argpartition 取 top-k,省去引入向量库的成本。

RAG 与向量库速查AI更新于 2026-10-13

NumPy 矩阵化相似度计算是什么

小规模或本地原型可以直接用 NumPy 做批量向量检索:先对文档矩阵与查询向量做 L2 归一化,一次矩阵乘法求出全部内积,再用 argpartition 取 top-k 候选、argsort 对候选排序。数万条以内用内存矩阵完全够用,省掉引入向量库的部署与运维成本;当数据规模上升,或出现过滤、增量更新需求时,再迁移到向量库更合适。

基本信息

适用规模数万条以内的原型与离线实验
依赖numpy,向量推荐 float32
步骤归一化、矩阵乘法、取前 k、对候选排序
复杂度每次查询与数据量成线性关系
前提向量已归一化,内积才等价于余弦
迁移时机需要过滤、增量更新或规模化时

典型使用场景

  • 本地原型与算法验证,避免依赖外部服务
  • 离线评测与消融实验,快速对比不同模型
  • 单元测试中构造可控的小型检索数据集
  • 数据量很小的内部工具,不值得引入向量库
  • 作为基线实现,校验向量库参数配置是否正确

归一化加矩阵乘法

归一化加矩阵乘法
import numpy as np

def l2norm(x):
    return x / np.linalg.norm(x, axis=1, keepdims=True)   # 按行归一化

docs = l2norm(np.random.rand(50000, 384).astype("float32"))  # 文档矩阵
docs_norm = np.linalg.norm(docs, axis=1, keepdims=True)      # 只算一次并缓存
q = l2norm(np.random.rand(1, 384).astype("float32"))         # 查询向量
scores = (docs @ q.T).ravel()                                # 一次算出全部内积
top = np.argpartition(-scores, 10)[:10]                      # 线性时间取候选
top = top[np.argsort(-scores[top])]                          # 只对候选排序
print(top, scores[top])

关键调用读法

调用作用注意
np.linalg.norm(x, keepdims=True)按行求模长keepdims 保证广播维度对齐
docs 与 q 的矩阵乘法一次算出全部内积float32 可以省一半内存
argpartition 取前 k线性时间挑出候选返回结果未排序,需要再排
argsort 对候选排序只对 k 个元素排序避免对全量分数排序的开销
数万条以内的原型用内存矩阵即可;规模再大或需要过滤与更新时,迁移到向量库,接口形态基本可以保持一致。
文档矩阵的范数只需计算一次并缓存:每次查询重算是常见的性能浪费,数据量越大越明显。

易错点

  • 忘记归一化就把内积当余弦:长文档向量模长更大,被系统性高估
  • 每次查询重算文档矩阵范数:重复计算带来无谓的性能损失
  • 对全量分数做完整排序:慢于先取候选再排序,数据量大时差距明显
  • 用 float64 存向量:内存翻倍而精度收益在实际检索中几乎体现不出来

数据来源与参考

  • NumPy 官方文档(argpartition / 矩阵乘法)
  • FAISS wiki(Flat 索引即精确暴力检索)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌