前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Faiss向量数据库

Faiss向量数据库

作者头像
@小森
发布2024-09-05 10:38:25
980
发布2024-09-05 10:38:25
举报
文章被收录于专栏:xiaosen

Faiss(Facebook AI Similarity Search)向量数据库是由Facebook AI研究院开发的一种高效相似性搜索和聚类的库。Faiss不仅支持在高维空间中进行高效的相似性搜索,还能够在处理大规模数据集时展现出卓越的性能,尤其适用于图像检索、文本搜索、推荐系统和语音处理等多种应用场景。 

  • 在推荐系统中,Faiss可以用于快速查找用户可能感兴趣的物品或寻找具有相似兴趣的用户。 
  • 在信息检索领域,Faiss可以用于构建文档或图像的相似性搜索引擎。
  • 在图像识别领域,Faiss可以用于构建图像特征的索引,实现快速的相似图像搜索和图像聚类。

 安装Faiss:

💢cpu版本:

代码语言:javascript
复制
conda install -c pytorch faiss-cpu

💢gpu版本:

代码语言:javascript
复制
conda install -c pytorch faiss-gpu

Faiss 处理固定维数 d 的向量集合,通常为几十到几百个。这些集合可以存储在矩阵中。我们假设采用行主存储,即向量编号 i 的第 j 个分量存储在矩阵的第 i 行、第 j 列中。Faiss 仅使用 32 位浮点矩阵。

代码语言:javascript
复制
import numpy as np
d = 64                           # 设置向量的维度为64
nb = 100000                      # 向量数量为100,000
nq = 10000                       # 查询向量的数量为10,000
np.random.seed(1234)             # make reproducible
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000.
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000.    # 修改查询向量的第一个维度

建立索引 

Faiss 是围绕Index对象构建的。它封装了一组数据库向量,并可选地对它们进行预处理,以提高搜索效率。索引有很多种类型,我们将使用最简单的版本,即对它们进行强力的 L2 距离搜索:IndexFlatL2

所有索引在构建时都需要知道它们所操作的向量的维数,当索引建立并训练完成后,可以对索引进行两种操作:addsearch

  • 当我们说一个索引是否被“训练”时,我们实际上是指该索引是否已经通过某种方式优化了其内部结构,以便更有效地处理搜索查询。 
代码语言:javascript
复制
import faiss                   
index = faiss.IndexFlatL2(d)   # 创建一个IndexFlatL2类型的索引
print(index.is_trained)        # 打印出索引是否已经被训练
index.add(xb)                  # 将向量添加到索引中
print(index.ntotal)
  • IndexFlatL2索引是一种简单的暴力搜索索引,它不需要训练过程,因为它直接计算查询向量与数据库中所有向量的L2距离,以找到最相似的向量。 

搜索~

可以在索引上执行的基本搜索操作是k最近邻搜索,即对于每个查询向量,k在数据库中找到其最近的邻居。

此操作的结果可以方便地存储在大小为nq-by-的整数矩阵中k,其中第 i 行包含查询向量 i 的邻居的 ID,按距离递增排序。除了这个矩阵之外,该search操作还返回一个nq-by-k浮点矩阵,其中包含相应的平方距离。

代码语言:javascript
复制
k = 4                          # we want to see 4 nearest neighbors
D, I = index.search(xb[:5], k) # 在索引中搜索xb数组的前5个向量(xb[:5])的k个最近邻居
print(I)
print(D)
D, I = index.search(xq, k)     # 整个查询集xq上搜索每个查询向量的k个最近邻居
print(I[:5])                   # 前5个查询向量的最近邻居的索引位置
print(I[-5:])   
  • D:包含了查询向量与其找到的最近邻居之间的距离。 
  • I:也是一个数组,但它包含的是最近邻居在索引中的位置或索引。

结果:


💥由于索引中未添加任何向量,因此无法进行有效的相似性搜索。在实际应用中,我们需要先将向量添加到索引中,然后才能进行搜索操作。


💥向索引添加向量:

代码语言:javascript
复制
nb = 100000  # 假设有100,000个向量  
xb = np.random.random((nb, d)).astype('float32')  # 生成随机向量数据,100000个64维数据
index.add(xb)  # 将向量数据添加到索引中
# 优化索引(跳过)

💯结果:

  •  后两个为实际的搜索输出(前五和后五)。

更快的搜索!

为了加快搜索速度,可以将数据集分割成块。我们在 d 维空间中定义 Voronoi 单元,每个数据库向量都位于其中一个单元中。在搜索时,仅将查询 x 所在的单元中包含的数据库向量 y 和一些相邻的向量与查询向量进行比较。

这是通过IndexIVFFlat索引完成的。这种类型的索引需要一个训练阶段,可以对具有与数据库向量相同分布的任何向量集合执行。

IndexIVFFlat需要另一个索引,即量化器,它将向量分配给 Voronoi 单元。每个单元由一个质心定义,找到向量所在的 Voronoi 单元就是在质心集合中找到向量的最近邻居。这是另一个索引的任务,通常是IndexFlatL2

代码语言:javascript
复制
nlist = 100
# nlist指定IndexIVFFlat索引中聚类中心的数量
k = 4
quantizer = faiss.IndexFlatL2(d)  
index = faiss.IndexIVFFlat(quantizer, d, nlist)
# 这个索引中,quantizer 被用作内部机制来量化向量,并将它们分配到倒排文件中的不同聚类中心

# assert 语句用于验证索引的状态,确保其在训练前后的行为符合预期。
assert not index.is_trained
index.train(xb)
print("~~训练完成~~")
assert index.is_trained
index.add(xb)                  
D, I = index.search(xq, k)     
print(I[-5:])                  
index.nprobe = 10              # 在搜索时控制要检查的聚类中心的数量
D, I = index.search(xq, k)
print(I[-5:])       

# quantizer 被“嵌入”到 index 中,是因为 index 需要使用 quantizer 的量化功能来将向量分配到正确的聚类中心,并实现高效的搜索。
  • ⭐️IndexIVFFlat索引首先将向量空间划分为nlist个聚类中心,然后使用quantizerIndexFlatL2索引)来量化这些中心。
  • ⭐️在搜索时,IndexIVFFlat索引会先确定查询向量所属的聚类中心,然后只在该中心的向量中执行搜索,从而大大减少了计算量。
  • ⭐️xb(代表数据集的一部分或全部)来训练索引。这是为了优化量化器或聚类中心。
  • ⭐️我们重新初始化了索引 index,所以第一次添加的操作就没有影响了。
  • 🌟每创建一个索引,就相当于在向量搜索的上下文中创建了一个独立的、用于存储和查询向量的数据结构。

搜索方法有两个参数:nlist,即单元格数量,以及nprobe,即执行搜索时访问的单元格数量(共nlist

🧊nprobe = 10:

🧊nprobe = 1 :

💢设置 nprobe = nlist 会得到与强力搜索相同的结果(但速度较慢)。 

Faiss支持将索引保存到磁盘文件中,并在需要时重新加载它们。通过保存和重新加载索引,可以在不同的会话或应用程序中重用索引:

代码语言:javascript
复制
# 保存索引  
faiss.write_index(index, 'index.faiss')  
  
# 加载索引  
index = faiss.read_index('index.faiss')
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •  安装Faiss:
  • 建立索引 
  • 搜索~
  • 更快的搜索!
相关产品与服务
向量数据库
腾讯云向量数据库(Tencent Cloud VectorDB)是一款全托管的自研企业级分布式数据库服务,专用于存储、检索、分析多维向量数据。该数据库支持多种索引类型和相似度计算方法,单索引支持千亿级向量规模,可支持百万级 QPS 及毫秒级查询延迟。腾讯云向量数据库不仅能为大模型提供外部知识库,提高大模型回答的准确性,还可广泛应用于推荐系统、自然语言处理等 AI 领域。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档