nmslib 是一个 超快、适用于高维向量的最近邻搜索库,基于 HNSW 算法,被广泛用于 语义搜索、推荐系统、人脸识别等任务
nmslib 是什么?
nmslib
(Non-Metric Space Library)是一个 高效的最近邻搜索(ANN, Approximate Nearest Neighbor Search) 库,专门用于 高维向量搜索,适用于 文本、图像、语音等嵌入向量 的相似性搜索。
它的核心功能是:
- 提供 快速、高效的最近邻搜索(ANN),即找到 与某个向量最相似的 k 个向量。
- 主要基于 HNSW(Hierarchical Navigable Small World) 算法,能在 数百万数据点级别 仍保持高效的搜索速度。
- 适用于 高维度数据(如 512 维、1024 维嵌入向量),比 KD-Tree、Ball-Tree 等传统方法更适合高维数据。
nmslib 的主要特点
-
极快的近似最近邻搜索
nmslib
通过 HNSW 索引结构,使搜索速度比 暴力搜索快数百倍,而准确率仍然很高。- 适用于大规模数据集(数百万数据点)。
-
支持多种度量空间(Metric Spaces)
- 默认使用 余弦相似度(cosine similarity),但也支持 欧几里得距离(L2)、内积(dot product) 等不同距离度量方式。
-
支持磁盘索引(离线存储)
- 可以将索引保存到磁盘,下次直接加载,不用重新计算,提高效率。
-
Python & C++ 实现,性能优越
- 采用 C++ 实现核心部分,性能比纯 Python 库(如
faiss
)还要快。
- 采用 C++ 实现核心部分,性能比纯 Python 库(如
nmslib 的应用场景
nmslib
广泛应用于:
- 语义搜索(Semantic Search):基于文本嵌入找到最相关的文档或句子。
- 推荐系统:找到用户最感兴趣的相似商品或内容。
- 人脸识别:从数据库中快速找到最相似的人脸。
- 图像搜索:在大型图片库中查找相似图片。
- 语音识别:查找音频中相似的片段。
nmslib 的基本用法
1. 安装 nmslib
pip install nmslib
2. 创建 HNSW 索引
import nmslib
import numpy as np
# 生成 10000 个随机向量,每个向量 128 维
data = np.random.random((10000, 128)).astype(np.float32)
# 初始化索引,使用 HNSW 方法和余弦相似度
index = nmslib.init(method='hnsw', space='cosinesimil')
# 添加数据到索引
index.addDataPointBatch(data)
# 构建索引,提高搜索速度
index.createIndex({'post': 2}, print_progress=True)
3. 进行最近邻搜索
# 查询一个随机向量
query_vector = np.random.random((1, 128)).astype(np.float32)
# 搜索最相似的 5 个向量
ids, distances = index.knnQuery(query_vector, k=5)
print("Top 5 最近邻 ID:", ids)
print("对应的距离:", distances)
4. 保存和加载索引
# 保存索引到文件
index.saveIndex('my_index.nms')
# 加载索引
index2 = nmslib.init(method='hnsw', space='cosinesimil')
index2.loadIndex('my_index.nms')
nmslib vs. 其他 ANN 搜索库
库名称 | 优势 | 劣势 |
---|---|---|
nmslib | 速度快、支持多种距离度量、适用于高维数据 | 不如 Faiss 适用于 GPU |
Faiss | Facebook 出品,支持 GPU,高效 | 仅支持 L2、内积,空间选择少 |
Annoy | 适合离线搜索,索引体积小 | 索引构建较慢,查询速度比 nmslib 慢 |
ScaNN | Google 出品,适用于 TensorFlow | 兼容性一般,不如 Faiss 通用 |
总结
✅ nmslib
是一个 超快、适用于高维向量的最近邻搜索库,基于 HNSW 算法,被广泛用于 语义搜索、推荐系统、人脸识别等任务。
✅ 适用于 百万级别数据,在 准确率和搜索速度之间取得了很好的平衡。
✅ 对比 Faiss、Annoy 等 ANN 搜索库,nmslib
在 CPU 环境下搜索速度最快,但不如 Faiss 适用于 GPU。
🚀 如果你在做文本、图片、音频等向量化搜索,nmslib
绝对是一个值得尝试的库!
nmslib 不是一个数据库
nmslib 不是一个数据库,而是一个 高效的近似最近邻(ANN)搜索库,用于高维向量搜索。
不过,它可以用于数据库中的向量索引,类似于 FAISS、Annoy 等工具,帮助数据库进行 高效的相似搜索。但 nmslib 本身不具备数据库的 CRUD(增删改查)、事务管理等功能。
nmslib vs. 数据库
特性 | nmslib | 数据库(如 MySQL、PostgreSQL) |
---|---|---|
主要功能 | 高维向量搜索(ANN) | 结构化数据存储、查询、事务管理 |
是否存储数据 | 仅存储索引,不存储原始数据 | 存储完整数据(表、行、列等) |
是否支持 SQL | ❌ 不支持 SQL | ✅ 支持 SQL 查询 |
数据管理能力 | 仅限于向量索引 | 事务、权限、关系型查询 |
索引类型 | HNSW(层次小世界图) | B-Tree、Hash、GIN 等 |
使用方式 | 适用于 AI、搜索推荐 | 适用于通用数据管理 |
如何在数据库中使用 nmslib?
如果你有一个数据库(如 PostgreSQL),但想用 nmslib 进行向量搜索,可以这样做:
- 数据库存储数据(文本、图片等)
- 使用嵌入模型(如 OpenAI Embeddings、Word2Vec)生成向量
- 用 nmslib 建立索引,加速相似搜索
- 数据库 + nmslib 联合查询,用 nmslib 搜索相似向量,再从数据库取出完整数据。
例如,在 PostgreSQL + nmslib 组合中:
import psycopg2
import nmslib
import numpy as np
# 连接数据库
conn = psycopg2.connect("dbname=mydb user=myuser password=mypass host=localhost")
cur = conn.cursor()
# 从数据库加载向量数据
cur.execute("SELECT id, embedding FROM my_table")
rows = cur.fetchall()
# 转换为 NumPy 数组
ids, embeddings = zip(*rows)
embeddings = np.array([np.frombuffer(e, dtype=np.float32) for e in embeddings])
# 创建 nmslib 索引
index = nmslib.init(method='hnsw', space='cosinesimil')
index.addDataPointBatch(embeddings, ids)
index.createIndex({'post': 2}, print_progress=True)
# 查询相似向量
query_vector = np.random.random((1, 128)).astype(np.float32)
nearest_ids, distances = index.knnQuery(query_vector, k=5)
# 在数据库中获取完整数据
cur.execute("SELECT * FROM my_table WHERE id IN %s", (tuple(nearest_ids),))
results = cur.fetchall()
print(results)
这种方法让 nmslib 负责搜索,数据库负责存储,实现高效的 AI 语义搜索。
总结
❌ nmslib 不是数据库,它是一个 高效的 ANN(近似最近邻)搜索库。
✅ 但它可以 与数据库结合使用,为数据库中的向量数据提供 快速的相似搜索能力(如 文本、图片、语音检索)。
🚀 如果你需要存储数据并进行管理,仍然需要一个数据库(如 PostgreSQL、MySQL、MongoDB),然后结合 nmslib 进行搜索优化!
nmslib 本身对嵌入模型并没有强制的限制
nmslib 本身对嵌入模型并没有强制的限制,也就是说你可以使用任何生成固定维度数值向量的嵌入模型。不过,在使用时需要注意以下几点:
-
固定维度:
嵌入模型的输出必须是固定维度的向量,因为 nmslib 索引需要知道每个向量的长度。如果你的模型输出动态长度的向量,则需要先进行处理或填充,使之变为固定长度。 -
数据格式:
nmslib 要求嵌入向量是数值型数据,通常为 NumPy 数组或可转换为 NumPy 数组的格式。如果嵌入结果不是这种格式,需要转换为相应的数值型数组。 -
归一化:
如果你使用的距离度量是余弦相似度(如 “cosinesimil”),那么通常需要对向量进行归一化。虽然 nmslib 本身不强制归一化,但为了获得更准确的相似度计算,通常建议在索引前对向量进行处理。 -
维度和性能:
嵌入向量的维度越高,索引的构建和查询可能会消耗更多的计算资源和内存。这并不是 nmslib 限制嵌入模型的问题,而是高维数据处理的常见挑战。所以在选择嵌入模型时,也需要权衡维度、性能和精度之间的关系。
总结来说,nmslib 不限制你使用哪种嵌入模型,但要求输出的嵌入向量满足固定维度和数值型数据的要求,此外还要考虑向量预处理(如归一化)和高维数据带来的性能问题。