大规模向量检索库Faiss学习总结记录
因为最近要使用到faiss来做检索和查询,所以这里只好抽出点时间来学习下,本文主要是自己最近学习的记录,来源于网络资料查询总结,仅用作个人学习总结记录。
Faiss的全称是Facebook AI Similarity Search,是FaceBook的AI团队针对大规模相似度检索问题开发的一个工具,使用C++编写,有python接口,对10亿量级的索引可以做到毫秒级检索的性能。
简单来说,Faiss的工作,就是把我们自己的候选向量集封装成一个index数据库,它可以加速我们检索相似向量TopK的过程,其中有些索引还支持GPU构建,可谓是强上加强。
faiss官方项目地址在这里,如下所示:
安装的话有cpu和gpu两个版本,根据自己需要选择即可,我直接使用的是cpu版本的:
pip install faiss-cpu==1.7.3
faiss整体流程图如下所示:
Faiss检索相似向量TopK的工程基本都能分为三步:
1、得到向量库;
2、用faiss 构建index,并将向量添加到index中;
3、用faiss index 检索。
faiss库的运行是基于索引的,这个索引与传统数据库中的Index不同,它是包含向量集,训练和查询方法等的类。
Index类信息汇总如下表所示:
Method | Class name | index_factory | Main parameters | Bytes/vector | Exhaustive | Comments |
Exact Search for L2 | IndexFlatL2 | Flat | d | 4*d | yes | brute-force |
Exact Search for Inner Product | IndexFlatIP | Flat | d | 4*d | yes | also for cosine (normalize vectors beforehand) |
Hierarchical Navigable Small World graph exploration | IndexHNSWFlat | NSWx,Flat | d, M | 4*d + 8 * M | no | |
Inverted file with exact post-verification | IndexIVFFlat | IVFx,Flat | quantizer, d, nlists, metric | 4*d | no | Take another index to assign vectors to inverted lists |
Locality-Sensitive Hashing (binary flat index) | IndexLSH | - | d, nbits | nbits/8 | yes | optimized by using random rotation instead of random projections |
Scalar quantizer (SQ) in flat mode | IndexScalarQuantizer | SQ8 | d | d | yes | 4 bit per component is also implemented, but the impact on accuracy may be inacceptable |
Product quantizer (PQ) in flat mode | IndexPQ | PQx | d, M, nbits | M (if nbits=8) | yes | |
IVF and scalar quantizer | IndexIVFScalarQuantizer | IVFx,SQ4 IVFx,SQ8 | quantizer, d, nlists, qtype | SQfp16: 2 * d, SQ8: d or SQ4: d/2 | no | there are 2 encodings: 4 bit per dimension and 8 bit per dimension |
IVFADC (coarse quantizer+PQ on residuals) | IndexIVFPQ | IVFx,PQy | quantizer, d, nlists, M, nbits | M+4 or M+8 | no | the memory cost depends on the data type used to represent ids (int or long), currently supports only nbits <= 8 |
IVFADC+R (same as IVFADC with re-ranking based on codes) | IndexIVFPQR | IVFx,PQy+z | quantizer, d, nlists, M, nbits, M_refine, nbits_refine | M+M_refine+4 or M+M_refine+8 | no |
faiss 三个最基础的 index. 分别是 IndexFlatL2, IndexIVFFlat, IndexIVFPQ
搜索时,可以以查询向量为中心,返回距离在一定范围内的结果,如返回数据库中与查询向量距离小于0.3的结果。不是所有的Index都支持按距离检索,但是下面三种Index都支持,只支持在CPU使用。
一、IndexFlatL2 - 最基础的Index
Flat索引只是将向量简单的编码为固定大小的代码,并将它们存储在 ntotal * code_size的数组中,不对向量数据进行压缩或折叠等操作。在搜索时,对所有的索引向量依次与查询向量比较。
优点:该方法是Faiss所有index中最准确的,召回率最高的方法,没有之一;
缺点:速度慢,占内存大。
使用情况:向量候选集很少,在50万以内,并且内存不紧张。
import numpy as np
import faiss
import timedef demo_IndexFlatL2():d = 2048 # 2048维的数据nb = 2 # database sizenq = 1 # nb of queriesnp.random.seed(1234)index = faiss.IndexFlatL2(d)print(index.is_trained)# 随机nb个数据插入索引xb = np.random.random((nb, d)).astype('float32')xb[:, 0] += np.arange(nb) / 1000.index.add(xb)# 再随机nb个数据插入索引xb1 = np.random.random((nb, d)).astype('float32')xb1[:, 0] += np.arange(nb) / 1000.index.add(xb1)print('index.ntotal:', index.ntotal)# 随机nq个数据用于查询xq = np.random.random((nq, d)).astype('float32')xq[:, 0] += np.arange(nq) / 1000.k = 4 # 查询距离最近的4个D, I = index.search(xq, k) # 返回值D是距离 I是索引print("I: ", I)# 按照距离查询dist = 1000 # 定义一个半径/阈值_, D, I = index.range_search(xb[[2], :], dist) # 用第2个向量查询print('range_search res:', I)# 删除元素,dtype=np.int64非常重要print('remove之前ntotal:', index.ntotal)index.remove_ids(np.asarray((2,3), dtype=np.int64))print('remove之后ntotal:', index.ntotal)if __name__ == '__main__':demo_IndexFlatL2()
二、更快的搜索 - IndexIVFFlat
为了加快搜索速度,可以将数据集分割成几部分。我们在d维空间中定义Voronoi单元格,并且每个数据库矢量都落入其中一个单元格中。在搜索时,只有查询x所在单元中包含的数据库向量y与少数几个相邻查询向量进行比较。(划分搜索空间)
这种类型的索引需要一个训练的过程,可以在与数据库向量具有相同分布的任何向量集合上执行。
这IndexIVFFlat还需要另一个索引,即量化器(quantizer),它将矢量分配给Voronoi单元。每个单元由一个质心定义,找到一个矢量所在的Voronoi单元包括在质心集中找到该矢量的最近邻居。这是另一个索引的任务,通常是索引IndexFlatL2。
搜索方法有两个参数:
nlist 划分单元的数量
nprobe 执行搜索访问的单元格数(不包括nlist)
nprobe 参数始终是调整结果速度和准确度之间折中的一种方式 。设置 nprobe = nlist 将给出与蛮力搜索(但会更慢)相同的结果。
优点:IVF主要利用倒排的思想,在文档检索场景下的倒排技术是指,一个kw后面挂上很多个包含该词的doc,由于kw数量远远小于doc,因此会大大减少了检索的时间。在向量中如何使用倒排呢?可以拿出每个聚类中心下的向量ID,每个中心ID后面挂上一堆非中心向量,每次查询向量的时候找到最近的几个中心ID,分别搜索这几个中心下的非中心向量。通过减小搜索范围,提升搜索效率。
缺点:速度也还不是很快。
使用情况:相比Flat会大大增加检索的速度,建议百万级别向量可以使用。
参数:IVFx中的x是k-means聚类中心的个数
import numpy as np
import faiss
import timedef demo_IndexIVFFlat():d = 64 # 向量维度nb = 200 # 向量集大小nq = 10000 # 查询次数np.random.seed(1234) # 随机种子,使结果可复现nlist = 100k = 4quantizer = faiss.IndexFlatL2(d) # the other indexindex = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)# here we specify METRIC_L2, by default it performs inner-product searchxb = np.random.random((nb, d)).astype('float32')xb[:, 0] += np.arange(nb) / 1000.index.train(xb)index.add(xb) # 添加索引可能会有一点慢print('index.ntotal:', index.ntotal)xb1 = np.random.random((nb, d)).astype('float32')xb1[:, 0] += np.arange(nb) / 1000.index.train(xb1)index.add(xb1) # 添加索引可能会有一点慢print('index.ntotal:', index.ntotal)xq = np.random.random((nq, d)).astype('float32')xq[:, 0] += np.arange(nq) / 1000.D, I = index.search(xq, k) # 搜索print(I[-5:]) # 最初五次查询的结果index.nprobe = 10 # 执行搜索访问的单元格数 默认 nprobe 是1 ,可以设置的大一些试试D, I = index.search(xq, k)print(I[-5:]) # 最后五次查询的结果# 按照距离查询dist = 1000 # 定义一个半径/阈值_, D, I = index.range_search(xb[[2], :], dist) # 用第2个向量查询print('range_search res:', I)# 删除元素,dtype=np.int64非常重要print('remove之前ntotal:', index.ntotal)index.remove_ids(np.asarray((2,3), dtype=np.int64))print('remove之后ntotal:', index.ntotal)if __name__ == '__main__':demo_IndexIVFFlat()
三 、IVFx Flat :倒排暴力检索
优点:IVF主要利用倒排的思想,在文档检索场景下的倒排技术是指,一个kw后面挂上很多个包含该词的doc,由于kw数量远远小于doc,因此会大大减少了检索的时间。在向量中如何使用倒排呢?可以拿出每个聚类中心下的向量ID,每个中心ID后面挂上一堆非中心向量,每次查询向量的时候找到最近的几个中心ID,分别搜索这几个中心下的非中心向量。通过减小搜索范围,提升搜索效率。
缺点:速度也还不是很快。
使用情况:相比Flat会大大增加检索的速度,建议百万级别向量可以使用。
参数:IVFx中的x是k-means聚类中心的个数
import numpy as np
d = 64 # 向量维度
nb = 100000 # index向量库的数据量
nq = 10000 # 待检索query的数目
np.random.seed(1234)
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000. # index向量库的向量
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000. # 待检索的query向量dim, measure = 64, faiss.METRIC_L2
param = 'IVF100,Flat' # 代表k-means聚类中心为100,
index = faiss.index_factory(dim, param, measure)
print(index.is_trained) # 此时输出为False,因为倒排索引需要训练k-means,
index.train(xb) # 因此需要先训练index,再add向量
index.add(xb)
四 、PQx :乘积量化
乘积量化的核心思想还是聚类。其主要分为两个步骤,Cluster 和 Assign,也即聚类和量化。
乘积量化有个重要的参数m_split ,这个参数控制着向量被切分的段数,如图所示,假设每个向量的维度为128,每个向量被切分为4段,这样就得到了4个小的向量,对每段小向量分别进行聚类,聚类个数为256个,这就完成了Cluster。然后做Assign操作,先每个聚类进行编码,然后分别对每个向量来说,先切分成四段小的向量,对每一段小向量,分别计算其对应的最近的簇心,然后使用这个簇心的ID当做该向量的第一个量化编码,依次类推,每个向量都可以由4个ID进行编码。
每个ID可以由一个字节保存,每个向量只需要用4个字节就可以编码,这样就完成的向量的压缩,节省了大量的内存,压缩比率2000+。
这一步其实就是Faiss训练的部分,目的是为了获取索引Index。在完成向量压缩,获取索引之后,就要考虑如何进行向量查询,下图表示了某个查询向量Query进行查询时的操作流程:
优点:利用乘积量化的方法,改进了普通检索,将一个向量的维度切成x段,每段分别进行检索,每段向量的检索结果取交集后得出最后的TopK。因此速度很快,而且占用内存较小,召回率也相对较高。
缺点:召回率相较于暴力检索,下降较多。
使用情况:内存及其稀缺,并且需要较快的检索速度,不那么在意召回率
参数:PQx中的x为将向量切分的段数,因此,x需要能被向量维度整除,且x越大,切分越细致,时间复杂度越高
import numpy as np
d = 64 # 向量维度
nb = 100000 # index向量库的数据量
nq = 10000 # 待检索query的数目
np.random.seed(1234)
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000. # index向量库的向量
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000. # 待检索的query向量dim, measure = 64, faiss.METRIC_L2
param = 'PQ16'
index = faiss.index_factory(dim, param, measure)
print(index.is_trained) # 此时输出为False,因为倒排索引需要训练k-means,
index.train(xb) # 因此需要先训练index,再add向量
index.add(xb)
五、更低的内存占用 - IndexIVFPQ
索引IndexFlatL2和IndexIVFFlat都存储完整的向量。 为了扩展到非常大的数据集,Faiss提供了基于产品量化器的有损压缩来压缩存储的向量的变体。压缩的方法基于乘积量化(Product Quantizer)。
在这种情况下,由于矢量没有精确存储,搜索方法返回的距离也是近似值。
import numpy as np
import faiss
import timedef demo_IndexIVFPQ():d = 64 # 向量维度nb = 100000 # 向量集大小nq = 10000 # 查询次数np.random.seed(1234) # 随机种子,使结果可复现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.nlist = 100m = 8k = 4quantizer = faiss.IndexFlatL2(d) # 内部的索引方式依然不变index = faiss.IndexIVFPQ(quantizer, d, nlist, m, 8)# 每个向量都被编码为8个字节大小index.train(xb)index.add(xb)D, I = index.search(xb[:5], k) # 测试print(I)print(D)index.nprobe = 10 # 与以前的方法相比D, I = index.search(xq, k) # 检索print(I[-5:])# 按照距离查询dist = 1000 # 定义一个半径/阈值_, D, I = index.range_search(xb[[2], :], dist) # 用第2个向量查询print('range_search res:', I)# 删除元素,dtype=np.int64非常重要print('remove之前ntotal:', index.ntotal)index.remove_ids(np.asarray((2,3), dtype=np.int64))print('remove之后ntotal:', index.ntotal)if __name__ == '__main__':demo_IndexIVFPQ()
六、IVFxPQy 倒排乘积量化
优点:工业界大量使用此方法,各项指标都均可以接受,利用乘积量化的方法,改进了IVF的k-means,将一个向量的维度切成x段,每段分别进行k-means再检索。
缺点:集百家之长,自然也集百家之短
使用情况:一般来说,各方面没啥特殊的极端要求的话,最推荐使用该方法!
参数:IVFx,PQy,其中的x和y同上
import numpy as np
d = 64 # 向量维度
nb = 100000 # index向量库的数据量
nq = 10000 # 待检索query的数目
np.random.seed(1234)
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000. # index向量库的向量
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000. # 待检索的query向量dim, measure = 64, faiss.METRIC_L2
param = 'IVF100,PQ16'
index = faiss.index_factory(dim, param, measure)
print(index.is_trained) # 此时输出为False,因为倒排索引需要训练k-means,
index.train(xb) # 因此需要先训练index,再add向量 index.add(xb)
七、LSH 局部敏感哈希
原理:哈希对大家再熟悉不过,向量也可以采用哈希来加速查找,我们这里说的哈希指的是局部敏感哈希(Locality Sensitive Hashing,LSH),不同于传统哈希尽量不产生碰撞,局部敏感哈希依赖碰撞来查找近邻。高维空间的两点若距离很近,那么设计一种哈希函数对这两点进行哈希计算后分桶,使得他们哈希分桶值有很大的概率是一样的,若两点之间的距离较远,则他们哈希分桶值相同的概率会很小。
优点:训练非常快,支持分批导入,index占内存很小,检索也比较快
缺点:召回率非常拉垮。
使用情况:候选向量库非常大,离线检索,内存资源比较稀缺的情况
import numpy as np
d = 64 # 向量维度
nb = 100000 # index向量库的数据量
nq = 10000 # 待检索query的数目
np.random.seed(1234)
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000. # index向量库的向量
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000. # 待检索的query向量dim, measure = 64, faiss.METRIC_L2
param = 'LSH'
index = faiss.index_factory(dim, param, measure)
print(index.is_trained) # 此时输出为True
index.add(xb)
八、HNSWx (最重要的放在最后说)
优点:该方法为基于图检索的改进方法,检索速度极快,10亿级别秒出检索结果,而且召回率几乎可以媲美Flat,最高能达到惊人的97%。检索的时间复杂度为loglogn,几乎可以无视候选向量的量级了。并且支持分批导入,极其适合线上任务,毫秒级别体验。
缺点:构建索引极慢,占用内存极大(是Faiss中最大的,大于原向量占用的内存大小)
参数:HNSWx中的x为构建图时每个点最多连接多少个节点,x越大,构图越复杂,查询越精确,当然构建index时间也就越慢,x取4~64中的任何一个整数。
使用情况:不在乎内存,并且有充裕的时间来构建index
import numpy as np
d = 64 # 向量维度
nb = 100000 # index向量库的数据量
nq = 10000 # 待检索query的数目
np.random.seed(1234)
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000. # index向量库的向量
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000. # 待检索的query向量dim, measure = 64, faiss.METRIC_L2
param = 'HNSW64'
index = faiss.index_factory(dim, param, measure)
print(index.is_trained) # 此时输出为True
index.add(xb)
IndexBinary是二进制索引,其表示的向量集中每个维度只有 0 和 1 两种数值,查询时计算待查向量与DataBase的汉明距离。向量在内存中按字节存储,每个维度占用1bit,总的内存空间为(dimension / 8)bytes,所以这类向量只支持维度为8的整数倍的向量集,否则需要对向量进行扩展或压缩。
九、IndexBinaryFlat
穷举搜索,在查询时会计算索引集中所有向量,该索引针对256维向量进行了特殊优化。
import faiss# 向量维度
d = 256# 建立索引的向量,可视为DataBase
db = ...# 需从Index中查询的目标向量
queries = ... # 初始化Index
index = faiss.IndexBinaryFlat(d)# 添加db到index中
index.add(db)# 每个查询向量要检索的最近邻居数
k = ...;# 查询索引, D是存放最近K个距离的容器, I是D中每个距离的向量在db中的下标
D, I = index.search(queries, k)
十、IndexBinaryIVF
该索引会对向量进行聚类来加快查询速度。聚类搜索需要先进行训练,相当于无监督学习。训练过程主要是量化器学习对数据进行聚类,划分为nlist个簇。这里采用的聚类方法是按距离划分。IndexBinaryIVF索引查询与IndexBinaryFlat的方式不同,前者是基于聚类的。
import faiss# 向量维度
d = 256# 建立索引的向量,可视为DataBase
db = ...# 训练用的向量集
training = ...# 需从Index中查询的目标向量
queries = ...# 初始化量化器
quantizer = faiss.IndexBinaryFlat(d)# 设置向量集中簇的个数
nlist = ...# 初始化索引
index = faiss.IndexBinaryIVF(quantizer, d, nlist)
# 设置每次查询的簇的数量
index.nprobe = 4# 训练
index.train(training)# 将向量集添加进索引
index.add(db)# 每个查询向量要检索的最近邻居数
k = ...# 查询索引, D是存放最近K个距离的容器, I是D中每个距离的向量在db中的下标
D, I = index.search(queries, k)
混合索引表示使用了上述多种索引方法以增强查询性能。
十一、IndexPQ
m = 16 # number of subquantizers
n_bits = 8 # bits allocated per subquantizer
pq = faiss.IndexPQ (d, m, n_bits) # Create the index
pq.train (x_train) # Training
pq.add (x_base) # Populate the index
D, I = pq.search (x_query, k) # Perform a search
十二、IndexIVFPQ
coarse_quantizer = faiss.IndexFlatL2 (d)
index = faiss.IndexIVFPQ (coarse_quantizer, d,ncentroids, code_size, 8)
index.nprobe = 5
十三、粗略PQ索引
乘积量化器(PQ)也可以作为初始索引,对应于多索引[The inverted multi-index, Babenko & Lempitsky, CVPR'12],对于具有m个段(每个段编码为c个质心)的PQ,反向列表的数量为c ^ m。因此,m = 2是唯一可行的选择。在FAISS中,相应的粗略量化器索引是MultiIndexQuantizer。该索引没有添加向量。因此,必须在IndexIVF上设置特定标志(quantizer_trains_alone)。
nbits_mi = 12 # c
M_mi = 2 # m
coarse_quantizer_mi = faiss.MultiIndexQuantizer(d, M_mi, nbits_mi)
ncentroids_mi = 2 ** (M_mi * nbits_mi)index = faiss.IndexIVFFlat(coarse_quantizer_mi, d, ncentroids_mi)
index.nprobe = 2048
index.quantizer_trains_alone = True
十四、预过滤PQ索引
比较汉明距离比使用PQ算法快6倍,但是通过对量化质心进行适当的重新排序,PQ码之间的汉明距离将与真实距离相关。通过在汉明距离上应用阈值,可以避免最昂贵的PQ代码比较。
设置阈值的原则:
阈值应在0和每个代码的位数之间(在这种情况下为128 = 16 * 8),并且代码遵循二项式分布;
阈值设置应小于代码位数的1/2。
#
#For an IndexPQ:
#
index = faiss.IndexPQ (d, 16, 8)
# before training
index.do_polysemous_training = true
index.train (...)
# before searching
index.search_type = faiss.IndexPQ.ST_polysemous
index.polysemous_ht = 54 # the Hamming threshold
index.search (...)#
#For an IndexIVFPQ:
#
index = faiss.IndexIVFPQ (coarse_quantizer, d, 16, 8)
# before training
index. do_polysemous_training = true
index.train (...)# before searching
index.polysemous_ht = 54 # the Hamming threshold
index.search (...)
对于Index相关的内容整体总结如下所示:
Faiss提供的索引多种多样,虽然它们都能完成既定的任务,但是对于不同的应用场景,表现的性能差异是非常大的。针对不同的应用场景,如何选择最好的索引,可以遵循下列因素:
【搜索量】
如果搜索量比较小(比如1000 - 10000),那么建立索引的时间在整个搜索过程中的占比会比较大,所以可以直接计算。
【结果精确度】
如果对结果要求绝对的准备,那么选择带有"Flat"关键字的索引。只有IndexFlatL2 或 IndexFlatIP能保证绝对的准确。它们为其他索引的结果提供了基准值。
【内存敏感性】
如果对内存没有要求,选择"HNSWx",其中x(4 - 64)表示每个向量的link数,x值越大,结果越精确,占用内存也越大;
要求不高,选择"... , Flat",其中"..."表示先对数据进行聚类。
要求比较高,选择"PCARx,...,SQ8"
对内存要求非常高,选择"OPQx_y,...,PQx"
【dataset大小】
小于1M, 选择"...,IVFx,..."
1M - 10M之间,选择 "...,IVF65536_HNSW32,..."
10M - 100M:之间, 选择"...,IVF262144_HNSW32,..."
100M - 1B:之间, 选择"...,IVF1048576_HNSW32,..."
Faiss的前后处理主要进行重新映射向量ID,对数据进行转换,并使用更好的索引对搜索结果重新排序等操作。
默认情况下Faiss按顺序将向量添加到索引,并设置ID。一些Index类实现了add_with_ids方法,其中除了向量之外,还可以提供64位向量ID。在搜索时,该类将返回存储的ID,而不是初始向量。映射ID可以使用IndexIDMap方法,该方法封装了另一个索引,并在添加和搜索时转换ID。它维护带有映射的表。
index = faiss.IndexFlatL2(xb.shape[1])
ids = np.arange(xb.shape[0])
index.add_with_ids(xb, ids) # this will crash, because IndexFlatL2 does not support add_with_ids
index2 = faiss.IndexIDMap(index)
index2.add_with_ids(xb, ids) # works, the vectors are stored in the underlying index
由于输入数据量过大等原因,在对数据进行索引前,往往需要进行数据转换,如压缩,降维等。所有的数据预转换方法都继承自VectorTransform类。该类对维度为d_in的输入向量进行转换,输出维度为d_out的输出向量。
数据预转换方法如下表:
【 PCAMatrix : 使用PCA降维】
将向量维度从2048D减到16字节
# the IndexIVFPQ will be in 256D not 2048coarse_quantizer = faiss.IndexFlatL2 (256)sub_index = faiss.IndexIVFPQ (coarse_quantizer, 256, ncoarse, 16, 8)# PCA 2048->256# also does a random rotation after the reduction (the 4th argument)pca_matrix = faiss.PCAMatrix (2048, 256, 0, True) #- the wrapping indexindex = faiss.IndexPreTransform (pca_matrix, sub_index)# will also train the PCAindex.train(...)# PCA will be applied prior to additionindex.add(...)
【RemapDimensionsTransform:增加维度】
可以通过添加零值的方式给向量增加维度
# input is in dimension d, but we want a multiple of Md2 = int((d + M - 1) / M) * Mremapper = faiss.RemapDimensionsTransform (d, d2, true)# the index in d2 dimensions index_pq = faiss.IndexPQ(d2, M, 8) # the index that will be used for add and search index = faiss.IndexPreTransform (remapper, index_pq)
【IndexRefineFlat:重新排列搜索结果】
查询向量时,使用实际距离计算对搜索结果重新排序可能会很有用。以下示例使用IndexPQ搜索索引,然后通过计算实际距离对第一个结果进行排名:
q = faiss.IndexPQ (d, M, nbits_per_index)rq = faiss.IndexRefineFlat (q)rq.train (xt)rq.add (xb)rq.k_factor = 4D, I = rq:search (xq, 10)
最后放上在总结学习过程中参考的博文【对所有作者表示感谢】:
https://blog.csdn.net/rangfei/category_10080429.html
Home · facebookresearch/faiss Wiki · GitHub
GitHub - facebookresearch/faiss: A library for efficient similarity search and clustering of dense vectors.
faiss 三种基础索引方式_faiss.indexflatl2_小殊小殊的博客-CSDN博客
Faiss入门及应用经验记录 - 知乎
https://blog.csdn.net/weixin_43791511/article/details/122513786
相关文章:
大规模向量检索库Faiss学习总结记录
因为最近要使用到faiss来做检索和查询,所以这里只好抽出点时间来学习下,本文主要是自己最近学习的记录,来源于网络资料查询总结,仅用作个人学习总结记录。 Faiss的全称是Facebook AI Similarity Search,是FaceBook的A…...
SpringCloudAlibaba之Sentinel(一)流控篇
前言: 为什么使用Sentinel,这是一个高可用组件,为了使我们的微服务高可用而生 我们的服务会因为什么被打垮? 一,流量激增 缓存未预热,线程池被占满 ,无法响应 二,被其他服务拖…...
哪种模式ip更适合你的爬虫项目?
作为一名爬虫程序员,对于数据的采集和抓取有着浓厚的兴趣。当谈到爬虫ip时,你可能会听说过两种常见的爬虫ip类型:Socks5爬虫ip和HTTP爬虫ip。但到底哪一种在你的爬虫项目中更适合呢?本文将帮助你进行比较和选择。 首先,…...
优维低代码实践:对接数据
优维低代码技术专栏,是一个全新的、技术为主的专栏,由优维技术委员会成员执笔,基于优维7年低代码技术研发及运维成果,主要介绍低代码相关的技术原理及架构逻辑,目的是给广大运维人提供一个技术交流与学习的平台。 优维…...
docker 离线模式-部署容器
有网络的情况下下载需要的镜像 比如(下面以tomcat为例子,其他镜像类似) docker pull tomcat打包镜像文件到本地 docker save tomcat -o tomcat.tar将tomcat.tar 上传到内网服务器(无外网环境) 导入镜像 docker load -i tomcat.tar创建容器…...
MDN-HTTP
参考资料 文章目录 HTTP简介HTTP 和 HTTPSHTTP消息典型的HTTP会话HTTP响应状态HTTP安全HTTP CookieHTTP压缩 HTTP简介 HTTP(Hypertext Transfer Protocol)是一种用于在计算机网络中传输超文本和其他资源的应用层协议。他是互联网的基础协议之一&#x…...
【数据库】PostgreSQL中使用`SELECT DISTINCT`和`SUBSTRING`函数实现去重查询
在PostgreSQL中,我们可以使用SELECT DISTINCT和SUBSTRING函数来实现对某个字段进行去重查询。本文将介绍如何使用这两个函数来实现对resource_version字段的去重查询。 1. SELECT DISTINCT语句 SELECT DISTINCT语句用于从表中选择不重复的记录。如果没有指定列名&…...
笔记本WIFI连接无网络【实测有效,不用重启电脑】
笔记本Wifi连接无网络实测有效解决方案 问题描述: 笔记本买来一段时间后,WIFI网络连接开机一段时间还正常连接,但是过一段时间显示网络连接不上,重启电脑太麻烦,选择编写重启网络脚本解决。三步解决问题。 解决方案&a…...
Java课题笔记~ Spring 概述
Spring 框架 一、Spring 概述 1、Spring 框架是什么 Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,它是为了解决企业应用开发的复杂性而创建的。Spring 的核心是控制反转(IoC)和面向切面编程(AOP)。 Spring…...
2022 robocom 世界机器人开发者大赛-本科组(国赛)
RC-u1 智能红绿灯 题目描述: RC-u1 智能红绿灯 为了最大化通行效率同时照顾老年人穿行马路,在某养老社区前,某科技公司设置了一个智能红绿灯。 这个红绿灯是这样设计的: 路的两旁设置了一个按钮,老年人希望通行马路时会…...
【雕爷学编程】Arduino动手做(195)---HT16k33 矩阵 8*8点阵屏模块6
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…...
Typescript]基础篇之 tsc 命令解析
[Typescript]基础[TOC]([Typescript]基础篇之 tsc 命令解析 tsc 命令概览编译参数说明--declaration--watch 这里是对 tsc 的一个详细介绍 tsc 命令概览 安装 Typescript 后可以使用 tsc 编译 ts 文件,tsc 命令是否支持其它参数 如果需要查看 tsc 支持的命令,或者…...
测试人员简单使用Jenkins
一、测试人员使用jenkins干什么? 部署测试环境 二、相关配置说明 一般由开发人员进行具体配置 1.Repository URL:填写git地址 2.填写开发分支,测试人员可通过相应分支进行测试环境的构建部署 当多个版本并行时,开发人员可以通过…...
使用RecyclerView构建灵活的列表界面
使用RecyclerView构建灵活的列表界面 1. 引言 在现代移动应用中,列表界面是最常见的用户界面之一,它能够展示大量的数据,让用户可以浏览和操作。无论是社交媒体的动态流、商品展示、新闻列表还是任务清单,列表界面都扮演着不可或…...
linux ubuntu安装mysql
在 Ubuntu 上安装 MySQL 的步骤如下: 更新系统软件包列表: sudo apt update 安装 MySQL 服务器: sudo apt install mysql-server 安装完成,可以使用以下命令检查 MySQL 服务器是否正在运行: sudo systemctl status mysql 如果 MyS…...
计算机网络各层的功能以及常用协议
目录 1. 物理层(Physical Layer)2. 数据链路层(Data Link Layer)3. 网络层(Network Layer)4. 传输层(Transport Layer)5. 应用层(Application Layer) 计算机网…...
M. Minimal and Maximal XOR Sum 2023“钉耙编程”中国大学生算法设计超级联赛(7)hdu7359
Problem - 7359 题目大意:给出一个n个数的排列,可以将任意区间内的所有数头尾翻转,每次操作的费用等于区间长度,要求将其变成一个递增排列,求消耗费用的异或和的最小值和最大值 1<n<1e5 思路:操作…...
C++基础篇(五)内存模型及详细示例
目录 一、内存分区模型二、内存分区代码示例三、new 运算符详解 一、内存分区模型 C程序在运行时,将内存分为四个区域,不同的区域赋予不同的生命周期,以提供强大的灵活编程。 代码区:存储程序的二进制代码,通常是只读…...
基于 JMeter API 开发性能测试平台
目录 背景: 常用的 JMeter 类和功能的解释: JMeter 编写性能测试脚本的大致流程示意图: 源码实现方式: (1) 环境初始化 (2) 环境初始化 (3) 创建测试计划 (4) 创建 ThreadGroup (5) 创建循环控制器 (6) 创建 Sampler (…...
HBase-写流程
写流程顺序正如API编写顺序,首先创建HBase的重量级连接 (1)读取本地缓存中的Meta表信息;(第一次启动客户端为空) (2)向ZK发起读取Meta表所在位置的请求; (…...
[mongo]应用场景及选型
应用场景及选型 MongoDB 数据库定位 OLTP 数据库横向扩展能力,数据量或并发量增加时候架构可以自动扩展灵活模型,适合迭代开发,数据模型多变场景JSON 数据结构,适合微服务/REST API基于功能选择 MongoDB 关系型数据库迁移 从基…...
linux c語言之crc16错误检测的使用
一、是什么? CRC16是循环冗余校验的一种,是一种根据数据产生校验码的方法。它是一种比较常用的校验算法,可以用于错误检测和纠正等方面。CRC16是16位的校验码,可以检测出32位以内的错误。在通信协议、网络传输等领域中,CRC16被广泛应用. 二、使用步骤 1.引入库 代码如…...
搭建本地开发服务器
搭建本地开发服务器 :::warning 注意 在上一个案例的基础上添加本地开发服务器,请保留上个案例的代码。如需要请查看 Webpack 使用。 ::: 搭建本地开发服务器这一个环节是非常有必要的,我们不可能每次修改源代码就重新打包一次。这样的操作是不是太繁琐…...
linux脚本
程序后台运行: nohup java -jar xxx.jar &>hello.log & 后台运行java-jar命令,并且将日志输出到hello.log文件 防火墙: 开启防火墙:systemctl start firewalld 开放指定端口:firewall-cmd --zonepublic --…...
企升编辑器word编写插件
面向用户群体招投标人员,用统一的模板来编写标书,并最终合并标书。项目经理,编写项目开发计划书,项目验收文档等。开发人员,编写项目需求规格说明书、设计说明书、技术总结等文档。其他文档编写工作量较多的岗位人员。…...
怎么在JMeter中的实现关联
我们一直用的phpwind这个系统做为演示系统, 如果没有配置好的同学, 请快速配置之后接着往下看哦. phpwind发贴时由于随着登陆用户的改变, verifycode是动态变化的, 因此需要用到关联. LoadRunner的关联函数是reg_save_param, Jmeter的关联则是利用后置处理器来完成. 在需要查…...
算法通关村第六关——如何使用中序和后序来恢复一颗二叉树
1 树的基础知识 1.1 树的定义 树(Tree):表现得是一种层次关系,为 n ( n ≥ 0 ) n(n≥0) n(n≥0)个节点构成的有限集合,当n0时,称为空树,对于任一…...
leetcode算法题--判断是否能拆分数组
原题链接:https://leetcode.cn/problems/check-if-it-is-possible-to-split-array/ 一开始思路想错了。。导致浪费很多时间 其实只要能找到存在一个子数组,子数组长度为2,这个子数组符合条件就一定能拆分。。 func canSplitArray(nums []i…...
基于Flask的模型部署
基于Flask的模型部署 一、背景 Flask:一个使用Python编写的轻量级Web应用程序框架; 首先需要明确模型部署的两种方式:在线和离线; 在线:就是将模型部署到类似于服务器上,调用需要通过网络传输数据&…...
【资料分享】全志科技T507-H开发板规格书
1 评估板简介 创龙科技TLT507-EVM是一款基于全志科技T507-H处理器设计的4核ARM Cortex-A53国产工业评估板,主频高达1.416GHz,由核心板和评估底板组成。核心板CPU、ROM、RAM、电源、晶振等所有器件均采用国产工业级方案,国产化率100%。同时,评估底板大部分元器件亦采用国产…...
微信企业网站源码下载/不需要验证码的广告平台
//Retry机制public static class Retry{/// <summary>/// 重试零个参数无返回值的方法/// </summary>/// <param name"action">执行方法方法</param>/// <param name"retryInterval">重试间隔</param>/// <param n…...
做外贸建网站/免费建站网站网页
问题及代码: /*。 *Copyright(c)2014,烟台大学计算机学院 *All right reserved, *文件名:test.cpp *作者:liu_feng_zi_ *完成日期:2014年12月9日 *版本号:v1.0 * 问题描述: *输入描述: *程序输…...
网站制作排名/网站收录查询站长工具
安装tensorflow: pip install tensorflow-gpu2.3.0 -i https://pypi.tuna.tsinghua.edu.cn/simple pip install tensorflow 安装最新版tensorflow pip install tensorflow2.9.0 安装指定版本的tensorflow 查看Anaconda环境是否安装成功: conda --ve…...
wordpress安装后后台无css/南宁网站关键词推广
在开始之前先了解下js数据类型 js基本数据类型: null undefined number boolean string js引用数据类型: function object array 一说instanceof 就想到typeof ,这里也介绍下typeof: typeof是用来判断数据类型的,就一个参数 ,使用…...
建设银行电子银行网站/关键字排名查询工具
一、使用响应式表单的步骤1、在模块(一般是app.module.ts)中引入ReactiveFormsModule2、在组件的ts文件中使用响应式表单import { Component, OnInit } from angular/core;import { FormGroup, FormBuilder, Validators, FormControl } from angular/forms;Component({selector…...
网站建设收费价格/举例说明seo
#include “stdio.h” #include “math.h” int main() { int year, s,sum0, month[12] { 31,28,31,30,31,30,31,31,30,31,30,31 },i,j,flag0; printf(“请输入年、月、日,格式为:年 月 日(2015 12 10)”); scanf("%d%d%d&q…...