向量数据库
向量数据库是专门用于存储、索引和检索高维向量的数据库。随着深度学习和 AI 的发展,向量检索成为许多应用的核心需求,包括图像检索、文本相似度、推荐系统、问答系统。向量数据库通过针对高维向量检索的优化,实现毫秒级的搜索性能。
向量检索基础
向量表示
深度学习模型将各种数据转换为向量表示,例如文本通过 BERT、GPT 模型转换为向量,图像通过 ResNet、CLIP 模型转换为向量,音频通过 wav2vec、Whisper 模型转换为向量。向量表示捕捉数据的语义特征,相似的数据向量距离近,不相似的数据向量距离远。
向量通常是高维的,从几十维到上千维。文本模型的维度通常是 768、1024、1536。图像模型的维度通常是 512、2048。向量维度越高,表达能力越强,但检索开销也越大。
相似度度量
向量检索的核心是相似度度量,判断两个向量的相似程度。常用的相似度度量包括余弦相似度、欧氏距离、点积、汉明距离。
余弦相似度衡量向量的方向差异,计算向量夹角的余弦值,范围是 [-1, 1],1 表示完全相同,0 表示正交,-1 表示相反。余弦相似度不受向量长度影响,适合文本检索。
欧氏距离衡量向量的位置差异,计算向量空间的直线距离,范围是 [0, +∞],0 表示完全相同。欧氏距离受向量长度影响,适合需要考虑绝对距离的场景。
点积衡量向量的投影,计算向量对应位置元素乘积的和。点积与余弦相似度相关,点积 = 余弦相似度 × 向量长度乘积。如果向量长度归一化,点积等价于余弦相似度。
import numpy as np
# 余弦相似度
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 欧氏距离
def euclidean_distance(a, b):
return np.linalg.norm(a - b)
# 点积
def dot_product(a, b):
return np.dot(a, b)暴力检索
暴力检索是最简单的向量检索方法,计算查询向量与所有向量的相似度,返回最相似的 K 个向量。时间复杂度是 O(n×d),n 是向量数量,d 是向量维度。对于百万级向量和千维向量,每次检索需要计算十亿次浮点运算,耗时可观。
暴力检索的优势是精确、简单、易于实现。劣势是性能差,无法扩展到大规模向量。暴力检索可以作为基准,评估其他索引方法的准确性和性能。
HNSW 算法
图索引原理
HNSW(Hierarchical Navigable Small World)是基于图的近似最近邻搜索算法,性能和准确性都很好。NSW(Navigable Small World)是基础,HNSW 引入层次结构加速搜索。
NSW 构建一张图,每个向量是图的一个节点,边连接相似的向量。搜索时从入口节点开始,沿着边遍历,找到最近的邻居。NSW 的关键是如何连接边,使得搜索路径短且能覆盖全局。
HNSW 构建多层图,类似跳表的结构。顶层图稀疏,覆盖范围广,用于快速定位。底层图密集,用于精确搜索。搜索时从顶层开始,逐层向下,每层找到最近的节点,最后在底层找到最近邻。
HNSW 构建
HNSW 构建采用贪心策略,每次插入新节点时,从顶层开始,每层找到最近的节点,然后连接新节点到这些节点。节点层数随机分配,层数高的节点有更多边,作为枢纽节点。
连接策略是关键,每个节点有最大连接数 M,搜索时需要考虑 M 个最近的节点。太少的边导致搜索不充分,太多的边导致搜索慢和存储开销。典型参数是 M = 16,每层的连接数不同,顶层连接数少,底层连接数多。
# HNSW 伪代码
def build_hnsw(vectors, M=16):
# 初始化
hnsw = Graph()
entry_point = None
for vector in vectors:
# 随机分配层数
level = random_level()
# 从顶层开始搜索
closest = search_hnsw(hnsw, vector, level)
# 连接新节点
for l in range(level):
candidates = find_nearest(hnsw, vector, l, M)
hnsw.connect(vector, candidates, l)
# 更新入口点
if level > hnsw.max_level:
entry_point = vector
return hnsw
def search_hnsw(hnsw, query, ef=10):
# 从顶层开始
closest = entry_point
for level in range(hnsw.max_level, 0, -1):
closest = search_layer(hnsw, query, closest, level, ef=1)
# 在底层搜索
results = search_layer(hnsw, query, closest, 0, ef=ef)
return results[:k]HNSW 搜索
HNSW 搜索从入口点开始,从顶层到底层逐层搜索。每层搜索找到该层最近的节点,然后将该节点作为下一层的入口点。底层搜索使用 ef 参数控制搜索范围,ef 越大结果越准确但搜索越慢。
ef 参数是 HNSW 最重要的调优参数。ef = K 时返回精确最近邻,但性能差。ef = 2×K 或 3×K 时性能和准确性的平衡点。实际应用中,ef 可以根据查询延迟动态调整,高优先级查询使用更大的 ef。
IVF 索引
倒排文件
IVF(Inverted File)是另一种向量索引方法,基于聚类和倒排。IVF 首先将向量聚类为多个类,每个类有一个中心点。查询时找到最近的几个中心点,只在这些类中搜索,避免全量搜索。
IVF 的关键参数是 nlist,聚类数量。nlist 越大,每个类的向量越少,搜索越快但可能遗漏最近邻。nlist 越小,搜索越慢但准确性高。典型值是 sqrt(n),n 是向量总数。例如百万向量使用 1000 个类。
IVF 搜索
IVF 搜索分为两步:粗量化和精搜索。粗量化找到最近的 nprobe 个中心点,nprobe 是搜索的类数量。精搜索在这些类中计算向量相似度,返回最近邻。
nprobe 是 IVF 最重要的调优参数。nprobe = 1 时最快但准确性低,nprobe = nlist 时等价于暴力搜索。典型值是 nprobe = 10 或 16,在性能和准确性之间折中。
IVF 支持量化,将向量压缩为更短的编码,减少内存和计算。PQ(Product Quantization)将向量分成多个子向量,每个子向量单独聚类。查询时先通过粗量化定位候选向量,然后通过量化距离快速估算。
向量数据库产品
Milvus
Milvus 是开源的向量数据库,支持多种索引类型包括 FLAT、IVF、HNSW、ANNOY。Milvus 采用存算分离架构,存储使用对象存储如 MinIO、S3,计算使用无状态节点,可独立扩容。Milvus 支持标量过滤和向量检索的结合,例如先过滤类别再检索向量。
Milvus 的数据模型包括 Collection、Partition、Entity、Field。Collection 是表的集合,Partition 是 Collection 的分区,Entity 是行,Field 是列。向量字段使用 FLOAT_VECTOR 或 BINARY_VECTOR 类型,支持 float32 和 binary 向量。
Pinecone
Pinecone 是托管的向量数据库服务,提供简单的 API 和自动扩展。Pinecone 支持 Pod-based 和 Serverless 两种模式。Pod-based 模式预配置资源,适合固定负载。Serverless 模式按使用量计费,自动扩展,适合波动负载。
Pinecone 的优势是易用性,无需管理基础设施,API 简单直观。Pinecone 支持命名空间,将数据隔离到不同的逻辑空间。Pinecone 支持元数据过滤,可以结合标量条件和向量检索。
Weaviate
Weaviate 是开源的向量搜索引擎,支持向量和图数据的结合。Weaviate 的数据模型是类和属性,每个类有一个向量,属性可以是原始数据或引用其他对象。Weaviate 支持图遍历,可以沿着引用关系查询相关对象。
Weaviate 支持多种向量化模块,包括文本模型(如 OpenAI、Cohere、HuggingFace)、图像模型(如 CLIP、ResNet)。用户上传原始数据,Weaviate 自动调用向量化模块生成向量,无需手动管理向量化过程。
性能优化
索引选择
索引选择是性能优化的第一步。FLAT 索引精确但慢,适合小规模数据。IVF 索引平衡性能和准确性,适合中等规模数据。HNSW 索引性能最好,适合大规模数据和低延迟查询。
索引参数需要调优。IVF 的 nlist 和 nprobe 需要根据数据分布和查询特点调整。HNSW 的 M 和 ef 需要根据内存预算和延迟要求调整。没有通用最优参数,需要实验确定。
批量查询
批量查询是提高吞吐量的有效方法。向量数据库支持批量查询,一次查询多个向量,共享计算开销。批量大小越大,吞吐量越高,但延迟也可能增加。批量大小建议在 10-100 之间,根据硬件和应用调整。
硬件优化
向量检索的计算密集型,适合 GPU 加速。GPU 的并行计算能力可以显著加速距离计算和索引搜索。Milvus 支持 GPU 索引,可以在 GPU 上构建和搜索索引。
内存是另一个关键因素。向量索引通常在内存中,内存大小限制了可索引的向量数量。SSD 索引可以突破内存限制,但性能会下降。如果向量数量超过内存容量,考虑使用 SSD 索引或分布式索引。
应用场景
图像检索
图像检索将图像转换为向量,支持以图搜图、相似图片推荐。图像向量化使用 CNN 模型如 ResNet、EfficientNet、CLIP。向量检索找到最相似的图像,返回给用户。
电商产品可以使用图像检索,用户上传商品图片,系统返回相似商品。社交媒体可以使用图像检索,检测重复图片和版权侵权。
文本检索
文本检索将文本转换为向量,支持语义搜索、文档相似度、问答系统。文本向量化使用 Transformer 模型如 BERT、GPT、Sentence-BERT。向量检索找到语义相似的文本,而不是关键词匹配。
搜索引擎可以使用文本检索,提供语义搜索能力。客服系统可以使用文本检索,自动匹配问题和答案。推荐系统可以使用文本检索,推荐用户感兴趣的内容。
推荐系统
推荐系统将用户和物品转换为向量,支持协同过滤、内容推荐、混合推荐。用户向量表示用户偏好,物品向量表示物品特征。向量检索找到与用户向量最相似的物品向量,作为推荐结果。
推荐系统的向量可以来自深度学习模型,也可以从用户行为矩阵分解得到。向量检索可以实时生成推荐,满足个性化需求。
向量数据库是 AI 时代的基础设施,随着深度学习的普及,向量检索的需求会持续增长。选择向量数据库需要考虑数据规模、查询延迟、准确性要求、团队能力,不同的场景适合不同的数据库和索引。