当前位置: 首页 > news >正文

向量数据库基础和实践 (Faiss)

向量数据库:AI时代的数据基础设施

向量数据库是一种专门用于存储、索引和查询向量数据的数据库系统。在人工智能和机器学习飞速发展的今天,向量数据库正成为处理非结构化数据的核心基础设施。

是什么

向量数据库是一种新型数据库,它存储的数据不是传统的结构化表格,而是高维向量。这些向量通常是通过深度学习模型将非结构化数据(如文本、图像、音频、视频等)转换而来的数值表示。

与传统关系型数据库不同,向量数据库的核心功能不是基于精确匹配的查询,而是基于相似度匹配。它能够快速地从海量向量中找出与查询向量最相似的向量,这使得它在处理复杂的非结构化数据时具有独特的优势。
在这里插入图片描述

原理

向量数据库的核心原理包括以下几个方面:

1. 向量表示

任何类型的数据都可以通过深度学习模型转换为向量。例如:

  • 文本可以通过Word2Vec、BERT等模型转换为向量
  • 图像可以通过ResNet、VGG等模型转换为向量
  • 音频可以通过MFCC、WaveNet等模型转换为向量

这些向量捕获了数据的语义信息,使得相似的数据具有相似的向量表示。

2. 相似度计算

向量数据库使用各种距离度量来计算向量之间的相似度,常用的包括:

  • 欧几里得距离(Euclidean Distance):衡量向量空间中两点间的直线距离
  • 余弦相似度(Cosine Similarity):衡量两个向量之间的夹角余弦值,不受向量长度影响
  • 曼哈顿距离(Manhattan Distance):衡量向量空间中两点间的折线距离
  • 汉明距离(Hamming Distance):衡量两个等长向量对应位置不同元素的数量

其中,余弦相似度在处理高维数据时表现尤为出色,因为它不受向量长度的影响。

相似度计算示例

为了更直观地理解这些相似度度量方法,我们以两个简单向量为例进行计算:

  • 向量 A = [1, 2, 3]
  • 向量 B = [4, 5, 6]
1. 欧氏距离

欧氏距离是向量空间中两点间的直线距离,计算公式为:
d(A,B)=∑i=1n(Ai−Bi)2 d(A,B) = \sqrt{\sum_{i=1}^{n} (A_i - B_i)^2} d(A,B)=i=1n(AiBi)2

对于向量 A 和 B:
d(A,B)=(1−4)2+(2−5)2+(3−6)2=9+9+9=27≈5.196 d(A,B) = \sqrt{(1-4)^2 + (2-5)^2 + (3-6)^2} = \sqrt{9 + 9 + 9} = \sqrt{27} \approx 5.196 d(A,B)=(14)2+(25)2+(36)2=9+9+9=275.196

2. 点积

点积(内积)是两个向量对应元素相乘之和,计算公式为:
[A⋅B=∑i=1nAi×Bi][ A \cdot B = \sum_{i=1}^{n} A_i \times B_i ][AB=i=1nAi×Bi]

对于向量 A 和 B:
A⋅B=1×4+2×5+3×6=4+10+18=32 A \cdot B = 1\times4 + 2\times5 + 3\times6 = 4 + 10 + 18 = 32 AB=1×4+2×5+3×6=4+10+18=32

点积值越大,通常表示向量在相同方向上的分量越多,但它受向量长度影响较大。

3. 余弦相似度

余弦相似度衡量两个向量之间的夹角余弦值,计算公式为:
cos⁡(θ)=A⋅B∥A∥×∥B∥ \cos(\theta) = \frac{A \cdot B}{\|A\| \times \|B\|} cos(θ)=A×BAB

其中,(|A|) 和 (|B|) 分别是向量 A 和 B 的模长(欧氏距离)。

对于向量 A 和 B:

  • ∥A∥=12+22+32=14≈3.7417\|A\| = \sqrt{1^2 + 2^2 + 3^2} = \sqrt{14} \approx 3.7417A=12+22+32=143.7417
  • ∥B∥=42+52+62=77≈8.775\|B\| = \sqrt{4^2 + 5^2 + 6^2} = \sqrt{77} \approx 8.775B=42+52+62=778.775
  • cos⁡(θ)=323.7417×8.775≈3232.83≈0.9747\cos(\theta) = \frac{32}{3.7417 \times 8.775} \approx \frac{32}{32.83} \approx 0.9747cos(θ)=3.7417×8.7753232.83320.9747

余弦相似度接近1,表示两个向量方向非常相似;接近0,表示方向正交;接近-1,表示方向相反。

向量数据库的核心流程
  • 输入:一个查询向量
  • 输出:最相似的几个向量
最近邻搜索问题

最近邻搜索(Nearest Neighbor,NN)是向量数据库的核心问题,涉及多种算法:

  1. 暴力搜索(Brute Force):最精准但耗时长,适用于小规模数据
  2. 聚类算法:聚类算法生成的簇中心可以作为近似最近邻搜索的参考点,以快速定位相似的对象
  3. 近似最近邻(Approximate Nearest Neighbor,ANN):通过牺牲部分精度来换取显著的速度提升
    1. 局部敏感哈希(Locality Sensitive Hashing,LSH):使用哈希函数使相似向量更容易碰撞到同一桶中
    2. 分层导航小世界 (Hierarchical Navigable Small World Graphs) HNSW:构建一个多层图连接点到邻居,实现快速导航到近似邻居

这些算法在搜索质量和搜索时间之间做出了不同的权衡。

3. 索引结构

为了实现高效的相似度查询,向量数据库采用了各种专门的索引结构,主要包括:

  • FLAT索引:简单暴力的全量扫描,适用于小规模数据
  • IVF索引(倒排文件):将向量空间划分为多个聚类,查询时先找到最近的聚类,再在该聚类内搜索
  • HNSW索引(分层导航小世界):通过构建多层图结构加速查询
  • PQ索引(乘积量化):通过量化向量降低存储空间和计算复杂度

应用场景

以图搜图 视频推荐等等

向量数据库在以下场景中发挥着重要作用:

1. 推荐系统

向量数据库能够高效地计算用户兴趣向量与物品向量之间的相似度,从而实现精准推荐。例如:

  • 电商平台的商品推荐
  • 视频平台的内容推荐
  • 音乐平台的歌曲推荐

2. 自然语言处理

向量数据库在NLP领域有着广泛应用:

  • 语义搜索:根据查询的语义而非关键词匹配文档
  • 问答系统:快速找到与问题相关的上下文信息
  • 文本聚类:将相似主题的文本聚在一起

3. 计算机视觉

  • 图像检索:根据图像内容而非标签查找相似图像
  • 人脸识别:快速识别和比对人脸特征
  • 物体检测:识别图像中的物体并分类

4. 多模态数据处理

向量数据库能够处理不同类型的数据(文本、图像、音频等),实现跨模态的相似度查询。例如,根据图像搜索相关的文本描述,或根据文本描述搜索相关的图像。

5. 大模型增强(RAG)

检索增强生成(RAG)是向量数据库的重要应用场景,它通过检索相关文档来增强大语言模型的生成能力,解决了大模型的知识时效性和幻觉问题。

对比

与传统关系型数据库对比

特性向量数据库关系型数据库
数据类型高维向量结构化数据
查询方式相似度匹配精确匹配
索引结构专门的向量索引(IVF、HNSW等)B+树、哈希索引等
主要应用非结构化数据处理、AI应用事务处理、报表分析

主流向量数据库产品对比

产品特点优势劣势
Faiss开源、高效、支持多种索引性能出色、内存占用低不支持分布式部署
Milvus开源、分布式、支持多种索引可扩展性强、支持云原生资源消耗较大
Pinecone闭源、托管服务开箱即用、无需维护成本较高
Qdrant开源、轻量级、支持过滤条件安装简单、查询速度快生态相对薄弱
Chroma开源、轻量级、专注于开发体验简单易用、内存占用低、集成度高不支持分布式部署、高级功能较少

实践

使用 faiss 存储向量并且进行向量检索

FAISS(Facebook AI Similarity Search)是由Facebook人工智能研究院开发的高效 相似度搜索和聚类 库,专为处理大规模高维向量数据设计。

核心特点

  • 高效检索 :提供多种索引类型(如 Flat 、 IVF 、 HNSW 等),支持精确搜索和近似搜索(ANN),平衡搜索速度与精度。
  • 大规模处理 :可轻松处理数十亿级别的高维向量(如10亿+ 128维向量)。
  • 硬件加速 :支持CPU和GPU加速(通过CUDA),显著提升检索性能。
  • 多语言支持 :提供Python和C++接口,易于集成到不同应用中。
'''
相似性搜索'''
import os
import timeimport faiss
import numpy as npnp.random.seed(42) # 保证多次运行结果一致# 1. 索引创建
def test01():dim = 10data = np.random.rand(10000, dim)idx_name = f"dim_{dim}_datalen_{len(data)}.faiss"# dim_1000_datalen_100000 500ms生成向量时间降到了  150 ms    数据占用 380MBt1 = time.time()if not os.path.exists(idx_name):# index = faiss.IndexFlatL2(dim)  # 使用欧式距离计算相似度index = faiss.IndexFlatIP(dim)  # 使用点积计算相似度# index = faiss.index_factory(dim, "Flat", faiss.METRIC_L2)# index = faiss.index_factory(dim, "Flat", faiss.METRIC_INNER_PRODUCT)# 添加向量index.add(data)faiss.write_index(index, idx_name)else:index = faiss.read_index(idx_name)t2 = time.time()print('index time:', t2 - t1)# 搜索向量topK= 1query_vectors = np.random.rand(1, dim)distances, idx = index.search(query_vectors, k=topK)print(distances) # D 就是 点积 或者是 欧氏距离,I 就是搜索结果对应的IDprint("=======================")print(idx) # D 就是 点积 或者是 欧氏距离,I 就是搜索结果对应的IDresV = data[idx][0,0]print(resV)# 计算两个向量的点积print("=======================")dis = np.sum(query_vectors * resV, axis=1) # 都是 dim*1 的向量print(dis)print("=======================")# 查询最近似向量的IDI = index.assign(query_vectors, k=topK)print(I)# 重建指定位置向量,并不是所有索引都支持该函数# print(index.reconstruct(0))# # 删除指定 ID 数据# index.remove_ids(np.array([1, 2, 3]))# print(index.ntotal)## # 删除所有向量数据# index.reset()# print(index.ntotal)if __name__ == '__main__':test01()

如何加速向量检索

'''IndexFlat 索引是一种基于线性搜索的索引,它通过逐个计算与每个向量的相似度来进行搜索。在数据量较大的时候,搜索效率会较低。
此时,我们可以使用 IndexIVFFlat 索引来提升搜索效率。
它的原理如下:对于所有的向量进行聚类,相当于把所有的数据进行分类。当进行查询时,在最相似的N 个簇中进行线性搜索。
这就减少了需要进行相似度计算的数据量,从而提升搜索效率。time: 0.0645294189453125
[[28.383003 29.018719]] [[ 54513 682317]]
time: 0.013531208038330078
[[28.383003 29.018719]] [[ 54513 682317]]搜索簇 数量减少  精度下降,但是 速度提升
这种方法是一种在查询的精度和效率之间平衡的方法
time: 0.06836390495300293
[[28.383003 29.018719]] [[ 54513 682317]]
time: 0.0030002593994140625
[[28.383003 30.071785]] [[ 54513 597587]]'''
import faiss
import numpy as np
import timenp.random.seed(42)
data = np.random.rand(1000000, 256)
ids = np.arange(0, 1000000)
query_vector = np.random.rand(1, 256)def test01():index = faiss.IndexFlatL2(256)index = faiss.IndexIDMap(index)# 添加向量index.add_with_ids(data, ids)# 搜索向量s = time.time()D, I = index.search(query_vector, k=2)print('time:', time.time() - s)print(D, I)def test02():# 第一个参数:量化参数# 第二个参数:向量维度# 第三个参数:质心数量quantizer = faiss.IndexFlatL2(256)index = faiss.IndexIVFFlat(quantizer, 256, 100) # 100 个质心# 增加搜索质心数量可以提高精确度,但是需要更多的时间# 默认为1  index.nprobe = 1 表示在搜索过程中只考虑一个聚类中心。# 这意味着搜索会在与查询向量最相似的一个聚类中进行线性搜索。这种方法可以显著提高搜索速度,但可能会牺牲一些精度。# 10可以  5 不行index.nprobe = 10# 聚类计算质心index.train(data)# 添加向量index.add_with_ids(data, ids)# 搜索向量s = time.time()D, I = index.search(query_vector, k=2)  # ANN近似最近邻print('time:', time.time() - s)print(D, I)if __name__ == '__main__':test01() # 暴力搜索test02() # 聚类之后再搜索
http://www.xdnf.cn/news/1317709.html

相关文章:

  • PyCharm与前沿技术集成指南:AI开发、云原生与大数据实战
  • 【FreeRTOS】刨根问底6: 应该如何防止任务栈溢出?
  • linux中已经启用的命令和替代命令
  • Honor of Kings 101star (S40) 2025.08.17
  • 开发者说 | EmbodiedGen:为具身智能打造可交互3D世界生成引擎
  • ICCV 2025 | Reverse Convolution and Its Applications to Image Restoration
  • GitLab CI/CD、Jenkins与GitHub Actions在Kubernetes环境中的方案对比分析
  • 多维视角下离子的特性、应用与前沿探索
  • C#读取文件, IO 类属性及使用示例
  • 为何她总在关键时“失联”?—— 解密 TCP 连接异常中断
  • tcp会无限次重传吗
  • 前端vue3+后端spring boot导出数据
  • 《设计模式》工厂方法模式
  • 【CV 目标检测】Fast RCNN模型②——算法流程
  • 代码随想录算法训练营四十四天|图论part02
  • 【Luogu】每日一题——Day21. P3556 [POI 2013] MOR-Tales of seafaring (图论)
  • 上网行为组网方案
  • 数据结构03(Java)--(递归行为和递归行为时间复杂度估算,master公式)
  • Mac(五)自定义鼠标滚轮方向 LinearMouse
  • Linux软件编程:进程与线程(线程)
  • JVM学习笔记-----StringTable
  • Docker Compose 安装 Neo4j 的详细步骤
  • PostgreSQL导入mimic4
  • go基础学习笔记
  • k8s集群搭建一主多从的jenkins集群
  • Win11 文件资源管理器预览窗格显示 XAML 文件内容教程
  • C++ vector的使用
  • 10 SQL进阶-SQL优化(8.15)
  • 说一下事件委托
  • Java 大视界 -- Java 大数据分布式计算在基因测序数据分析与精准医疗中的应用(400)