【Faiss】indexes 前(后)处理(五)

2024-08-27 17:58
文章标签 处理 indexes faiss

本文主要是介绍【Faiss】indexes 前(后)处理(五),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Pre and post processing

在某些情形下,需要对Index做前处理或后处理。

ID映射

默认情况下,faiss会为每个输入的向量记录一个次序id,在使用中也可以为向量指定任意我们需要的id。
部分index类型有add_with_ids方法,可以为每个向量对应一个64-bit的id,搜索的时候返回这个指定的id。

#导入faiss
import sys
sys.path.append('/home/maliqi/faiss/python/')
import faiss
import numpy as np #获取数据和Id
d = 512
n_data = 2000
data = np.random.rand(n_data, d).astype('float32')
ids = np.arange(100000, 102000)  #id设定为6位数整数

 

nlist = 10
quantizer = faiss.IndexFlatIP(d)
index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)
index.train(data)
index.add_with_ids(data, ids)
d, i = index.search(data[:5], 5)
print(i)  #返回的id应该是我们自己设定的
[[100000 100383 101007 101444 100729][100001 100880 101693 100004 100964][100002 101113 101998 101017 101768][100003 100694 101701 101608 100831][100004 100111 100564 100541 100513]]

但是对有些Index类型,并不支持add_with_ids,因此需要与其他Index类型结合,将默认的id映射到指定id,用IndexIDMap类实现。
指定的ids不能是字符串,只能是整数。

index = faiss.IndexFlatL2(data.shape[1]) 
index.add_with_ids(data, ids)  #报错
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-5-4de928a09ab9> in <module>()1 index = faiss.IndexFlatL2(data.shape[1])
----> 2 index.add_with_ids(data, ids)/home/maliqi/faiss/python/faiss/__init__.py in replacement_add_with_ids(self, x, ids)104         assert d == self.d105         assert ids.shape == (n, ), 'not same nb of vectors as ids'
--> 106         self.add_with_ids_c(n, swig_ptr(x), swig_ptr(ids))107 108     def replacement_assign(self, x, k):/home/maliqi/faiss/python/faiss/swigfaiss.py in add_with_ids(self, n, x, xids)1316 1317     def add_with_ids(self, n, x, xids):
-> 1318         return _swigfaiss.Index_add_with_ids(self, n, x, xids)1319 1320     def search(self, n, x, k, distances, labels):RuntimeError: Error in virtual void faiss::Index::add_with_ids(faiss::Index::idx_t, const float*, const long int*) at Index.cpp:46: add_with_ids not implemented for this type of index
index2 = faiss.IndexIDMap(index)  
index2.add_with_ids(data, ids)  #将index的id映射到index2的id,会维持一个映射表

数据转换

有些时候需要在索引之前转换数据。转换类继承了VectorTransform类,将输入向量转换为输出向量。
1)随机旋转,类名RandomRotationMatri,用以均衡向量中的元素,一般在IndexPQ和IndexLSH之前;
2)PCA,类名PCAMatrix,降维;
3)改变维度,类名RemapDimensionsTransform,可以升高或降低向量维数

举例:PCA降维(通过IndexPreTransform)

输入向量是2048维,需要减少到16byte。

data = np.random.rand(n_data, 2048).astype('float32')
# the IndexIVFPQ will be in 256D not 2048
coarse_quantizer = faiss.IndexFlatL2 (256) 
sub_index = faiss.IndexIVFPQ (coarse_quantizer, 256, 16, 16, 8)
# PCA 2048->256
# 降维后随机旋转 (第四个参数)
pca_matrix = faiss.PCAMatrix (2048, 256, 0, True) #- the wrapping index
index = faiss.IndexPreTransform (pca_matrix, sub_index)# will also train the PCA
index.train(data)  #数据需要是2048维
# PCA will be applied prior to addition
index.add(data)

举例:升维

有时候需要在向量中插入0升高维度,一般是我们需要 1)d是4的整数倍,有利于举例计算; 2)d是M的整数倍。

d = 512
M = 8   #M是在维度方向上分割的子空间个数
d2 = int((d + M - 1) / M) * M
remapper = faiss.RemapDimensionsTransform (d, d2, True)
index_pq = faiss.IndexPQ(d2, M, 8)
index = faiss.IndexPreTransform (remapper, index_pq) #后续可以添加数据/索引

对搜索结果重新排序

当查询向量时,可以用真实距离值对结果进行重新排序。
在下面的例子中,搜索阶段会首先选取4*10个结果,然后对这些结果计算真实距离值,再从中选取10个结果返回。IndexRefineFlat保存了全部的向量信息,内存开销不容小觑。

data = np.random.rand(n_data, d).astype('float32')
nbits_per_index = 4
q = faiss.IndexPQ (d, M, nbits_per_index)
rq = faiss.IndexRefineFlat (q)
rq.train (data)
rq.add (data)
rq.k_factor = 4
dis, ind = rq.search (data[:5], 10)
print(ind)
[[   0  434 1647 1501  867  658  822 1164  490 1430][   1 1035  369  392  866 1645 1961 1469 1946  175][   2  466 1183  403  427  505  394  759  633  746][   3 1668 1798 1293  965 1484  755  315 1633 1453][   4  309  715 1204  996  239 1381   48  707 1311]]

综合多个index返回的结果

当数据集分布在多个index中,需要在每个index中都执行搜索,然后使用IndexShards综合得到结果。同样也适用于index分布在不同的GPU的情况。

这篇关于【Faiss】indexes 前(后)处理(五)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1112376

相关文章

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp