我是靠谱客的博主 老迟到白云,最近开发中收集的这篇文章主要介绍faiss选择合适的index类型选择合适的index类型,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

选择合适的index类型

选择index类型并没有一套精准的法则可以依据,需要根据自己的实际情况选取。下面的几个问题可以作为选取index的参考。

是否需要精确的结果

如果需要,应该使用“Flat” 只有 IndexFlatL2 能确保返回精确结果。一般将其作为baseline与其他索引方式对比,以便在精度和时间开销之间做权衡。
不支持add_with_ids,如果需要,可以用“IDMap, Flat”。
支持GPU。

In [8]:

#导入faiss
import sys
sys.path.append('/home/maliqi/faiss/python/')
import faiss

#数据
import numpy as np 
d = 512          #维数
n_data = 2000   
np.random.seed(0) 
data = []
mu = 3
sigma = 0.1
for i in range(n_data):
    data.append(np.random.normal(mu, sigma, d))
data = np.array(data).astype('float32')

#ids, 6位随机数
ids = []
start = 100000
for i in range(data.shape[0]):
    ids.append(start)
    start += 100
ids = np.array(ids)

In [9]:

#不支持add_with_ids
index = faiss.index_factory(d, "Flat")
index.add(data)
dis, ind = index.search(data[:5], 10)
print(ind)
[[   0  798  879  223  981 1401 1458 1174  919   26]
 [   1  981 1524 1639 1949 1472 1162  923  840  300]
 [   2 1886  375 1351  518 1735 1551 1958  390 1695]
 [   3 1459  331  389  655 1943 1483 1723 1672 1859]
 [   4   13  715 1470  608  459  888  850 1080 1654]]

In [10]:

index = faiss.index_factory(d, "IDMap, Flat")
index.add_with_ids(data, ids)
dis, ind = index.search(data[:5], 10)
print(ind)   # 返回的结果是我们自己定义的id
[[100000 179800 187900 122300 198100 240100 245800 217400 191900 102600]
 [100100 198100 252400 263900 294900 247200 216200 192300 184000 130000]
 [100200 288600 137500 235100 151800 273500 255100 295800 139000 269500]
 [100300 245900 133100 138900 165500 294300 248300 272300 267200 285900]
 [100400 101300 171500 247000 160800 145900 188800 185000 208000 265400]]

关心内存开销

需要注意的是faiss在索引时必须将index读入内存。

如果不在意内存占用空间,使用“HNSWx”

如果内存空间很大,数据库很小,HNSW是最好的选择,速度快,精度高,一般4<=x<=64。不支持add_with_ids,不支持移除向量,不需要训练,不支持GPU。

In [12]:

index = faiss.index_factory(d, "HNSW8")
index.add(data)
dis, ind = index.search(data[:5], 10)
print(ind)
[[ 879  981   26 1132  807 1639   28 1334 1832 1821]
 [   1  981 1524 1639 1949 1472 1162  923  840  300]
 [   2 1886  375 1351  518 1958  390 1695 1707 1080]
 [   3 1459  331  389  655 1483 1723 1672 1859  650]
 [   4   13  715 1470  608  459 1080 1654  665  154]]

如果稍微有点在意,使用“..., Flat“

"..."是聚类操作,聚类之后将每个向量映射到相应的bucket。该索引类型并不会保存压缩之后的数据,而是保存原始数据,所以内存开销与原始数据一致。通过nprobe参数控制速度/精度。
支持GPU,但是要注意,选用的聚类操作必须也支持。

In [14]:

index = faiss.index_factory(d, "IVF100, Flat")
index.train(data)
index.add(data)
dis, ind = index.search(data[:5], 10)
print(ind)
[[   0  879  981 1401  919  143    2  807 1515 1393]
 [   1  511 1504  987  747  422 1911  638  851 1198]
 [   2  879  807  981 1401 1143  733  441 1324 1280]
 [   3  740  155 1337 1578 1181 1743  290  588 1340]
 [   4 1176  256 1186  574 1459  218  480 1828  942]]

如果很在意,使用”PCARx,...,SQ8“

如果保存全部原始数据的开销太大,可以用这个索引方式。包含三个部分,
1.降维
2.聚类
3.scalar 量化,每个向量编码为8bit 不支持GPU

In [19]:

index = faiss.index_factory(d, "PCAR16,IVF50,SQ8")  #每个向量降为16维
index.train(data)
index.add(data)
dis, ind = index.search(data[:5], 10)
print(ind)
[[   0  671  196 1025  624 1521  724  879 1281  533]
 [   1 1008  698  206  101  657  294  383  700  574]
 [   2 1594  754 1850  266  559  154 1723 1949 1910]
 [   3 1758  820  869 1067   14  211 1214   78 1445]
 [   4 1457  466  557 1604 1951  912  736 1974  836]]

如果非常非常在意,使用"OPQx_y,...,PQx"

y需要是x的倍数,一般保持y<=d,y<=4*x。 支持GPU。

In [26]:

index = faiss.index_factory(d, "OPQ32_512,IVF50,PQ32")  
index.train(data)
index.add(data)
dis, ind = index.search(data[:5], 10)
print(ind)
[[   0 1686 1186 1552   47  517 1563 1738 1748  125]
 [   1  747 1816   41 1599  380 1179  803 1964  422]
 [   2 1610 1886  928  397  874  676  535 1401  929]
 [   3  548   89  509 1337  865 1472 1210 1181 1578]
 [   4  260 1781 1001 1179   41   20  747 1803 1055]]

数据集的大小

在高效检索的index中,聚类是其中的基础操作,数据量的大小主要影响聚类过程。

如果小于1M, 使用"...,IVFx,..."

N是数据集中向量个数,x一般取值[4sqrt(N),16sqrt(N)],需要30x ~ 256x个向量的数据集去训练。

如果在1M-10M,使用"...,IMI2x10,..."

使用k-means将训练集聚类为2^10个类,但是执行过程是在数据集的两半部分独立执行,即聚类中心有2^(2*10)个。

如果在10M-100M,使用"...,IMI2x12,..."

最后

以上就是老迟到白云为你收集整理的faiss选择合适的index类型选择合适的index类型的全部内容,希望文章能够帮你解决faiss选择合适的index类型选择合适的index类型所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部