搜索引擎项目2 | 青训营笔记

161 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记

上一次介绍了本次以图搜图使用resnet34,将图片特征转化为512长度的向量,并存储,那么如何将这个存储之后形成的库,输入一张新的图片转化成512的向量之后,快速检索出和这个新向量最相似的向量,这需要用到faiss库和topk算法.

faiss是Facebook Ai团队开源的一个近似最近邻搜索库,内部用C++高效实现了局部敏感哈希、乘积量化、Kmeans和PCA等算法,在单个服务器的内存中,支持对数十亿的稠密向量进行高效的相似性搜索。faiss提供了python的API,和numpy进行完美交互。

faiss提供了一个index_factory的方法,可以直译为:索引工厂函数。这个索引工厂函数是用来干嘛的呢?faiss库在构建索引时,为了进一步提高计算效率或减少内存压力,会综合运用更多的算法。比如上面已经用了倒排索引+PQ编码,还可以预先用PCA对向量进行降维。如此一来,在写代码的时候,我们就需要分三步:首先进行PCA降维(数据预处理),然后倒排(聚类),最后PQ编码(编码)。为了省事,干脆直接用一个字符串,把数据预处理、聚类、编码的方法和参数拼接在一起,放入索引工厂函数中,一行代码就生成了复合索引。下面就用索引工厂函数来构建索引:

index = faiss.read_index('index_file.index')
print('索引记录数:', index.ntotal)
# 索引记录数: 17125
model = load_model()
def index_search(feat,topK ):
    """
        feat: 检索的图片特征
        topK: 返回最高topK相似的图片
        
    """
    
    feat = np.expand_dims( np.array(feat),axis=0 )
    feat = feat.astype('float32')
    
    start_time = time.time()
    dis,ind = index.search( feat,topK )
    end_time = time.time()
    
    print( 'index_search consume time:{}ms'.format(  int(end_time - start_time) * 1000  ) )
    return dis,ind # 距离,相似图片id