向量搜索查询faiss、annoy

news2024/10/5 16:27:59

首先介绍annoy :
转发空间:https://download.csdn.net/blog/column/10872374/114665212

Annoy是高维空间求近似最近邻的一个开源库。

Annoy构建一棵二叉树,查询时间为O(logn)。

Annoy通过随机挑选两个点,并使用垂直于这个点的等距离超平面将集合划分为两部分。

如图所示,图中灰色线是连接两个点,超平面是加粗的黑线。按照这个方法在每个子集上迭代进行划分。
在这里插入图片描述

依此类推,直到每个集合最多剩余k个点,下图是一个k = 10 的情况。

在这里插入图片描述

在这里插入图片描述

n_trees在构建时提供,并影响构建时间和索引大小。 较大的值将给出更准确的结果,但更大的索引。

search_k在运行时提供,并影响搜索性能。 较大的值将给出更准确的结果,但将需要更长的时间返回。

代码实现:

pip install annoy == 1.17.0 -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn

from tqdm import tqdm
import pandas as pd
import time
import numpy as np
from annoy import AnnoyIndex
from sentence_transformers import SentenceTransformer, InputExample
from sentence_transformers import models, losses
from torch.utils.data import DataLoader
from sentence_transformers import SentenceTransformer, util
from sentence_transformers import SentenceTransformer, SentencesDataset, InputExample, evaluation, losses, models
from torch.utils.data import DataLoader
model = SentenceTransformer(r'327_6epoch_64batchdjwSaveModel/djwSaveModel')
emb1 = model.encode("美赞臣安婴儿A+亲舒婴儿奶粉1段850克0-12个月宝宝")
print(emb1.shape)
emb2 = model.encode("美赞臣亲舒一段领券满减")
emb3 = model.encode("真手表打火机带手电筒真车钥匙电子手表打火机充电防风送男友潮")
cos_sim = util.pytorch_cos_sim(emb1, emb2)
cos_sim1 = util.pytorch_cos_sim(emb3, emb2)
print("Cosine-Similarity:", cos_sim,cos_sim1)
corpus_data = pd.read_csv("corpus.tsv",sep="\t",header=None,names=['doc_id','title'])#读取csv文件
corpus_title_data=corpus_data['title'].values
qrels_train_data = pd.read_csv("qrels.train.tsv",sep="\t",header=None,names=['query_id','doc_id'])#读取csv文件
dev_id_query_data =[]
dev_querytxt_data=[]
with open("dev.query.txt","r",encoding='utf-8') as f:
    lines=f.readlines()
    for line in lines:
        dev_id_query_data.append(line.split("\n")[0].split("\t"))
        dev_querytxt_data.append(line.split("\n")[0].split("\t")[1])
print(len(dev_querytxt_data))
print(dev_querytxt_data[0:10])
f=128
t = AnnoyIndex(f, 'angular')  # Length of item vector that will be indexed
for index_i, i in tqdm(enumerate(dev_querytxt_data)):  # len 是1000
    embi = model.encode(i)
    t.add_item(index_i, embi)
    # if index_i==100:break
for index_j, j in tqdm(enumerate(corpus_title_data)):  # 1001500
    embj = model.encode(j)
    t.add_item(index_j + 1000, embj)
    # if index_j == 100: break
t.build(500)
t.save('327_6epoch_64batchdjwSaveModel_embeedding.ann')

两个超参数需要考虑: 树的数量n_trees和搜索过程中检查的节点数量search_k

基本上,建议在可用负载量的情况下尽可能大地设置n_trees,并且考虑到查询的时间限制,建议将search_k设置为尽可能大。

n_trees: 在构建期间提供,影响构建时间和索引大小。值越大,结果越准确,但索引越大。

search_k: 在运行时提供,并影响搜索性能。值越大,结果越准确,但返回的时间越长。如果不提供,就是n_trees * n, n是最近邻的个数

u = AnnoyIndex(f, 'angular')
u.load('ceshi_embeedding.ann')
for i in range(100):
    temp=u.get_nns_by_item(i,4)
    print(dev_querytxt_data[i])
    for idx in temp[1:]:
        print(corpus_title_data[idx-1000])
    print("------------------------------------------------------------")
 Facebook: 亿级向量相似度检索库Faiss原理
Faiss的核心原理其实就两个部分:
Product Quantizer, 简称PQ.
Inverted File System, 简称IVF.

2 Product Quantizer

在这里插入图片描述

在做PQ之前,首先需要指定一个参数M,这个M就是指定向量要被切分成多少段,在上图中M=4,所以向量库的每一个向量就被切分成了4段,然后把所有向量的第一段取出来做Clustering得到256个簇心(256是一个作者拍的经验值);再把所有向量的第二段取出来做Clustering得到256个簇心,直至对所有向量的第N段做完Clustering,从而最终得到了256*M个簇心。

做完Cluster,就开始对所有向量做Assign操作。这里的Assign就是把原来的N维的向量映射到M个数字,以N=128,M=4为例,首先把向量切成四段,然后对于每一段向量,都可以找到对应的最近的簇心 ID,4段向量就对应了4个簇心 ID,一个128维的向量就变成了一个由4个ID组成的向量,这样就可以完成了Assign操作的过程 – 现在,128维向量变成了4维,每个位置都只能取0~127,这就完成了向量的压缩。

完成了PQ的Pre-train,就可以看看如何基于PQ做向量检索了
在这里插入图片描述

同样是以N=128,M=4为例,对于每一个查询向量,以相同的方法把128维分成4段32维向量,然后计算每一段向量与之前预训练好的簇心的距离,得到一个4*256的表。然后就可以开始计算查询向量与库里面的向量的距离。此时,库的向量已经被量化成M个簇心 ID,而查询向量的M段子向量与各自的256个簇心距离已经预计算好了,所以在计算两个向量的时候只用查M次表,比如的库里的某个向量被量化成了[124, 56, 132, 222], 那么首先查表得到查询向量第一段子向量与其ID为124的簇心的距离,然后再查表得到查询向量第二段子向量与其ID为56的簇心的距离…最后就可以得到四个距离d1、d2、d3、d4,查询向量跟库里向量的距离d = d1+d2+d3+d4。所以在提出的例子里面,使用PQ只用4×256次128/4维向量距离计算加上4xN次查表,而最原始的暴力计算则有N次128维向量距离计算,很显然随着向量个数N的增加,后者相较于前者会越来越耗时。

2 Inverted File System
要想减少需要计算的目标向量的个数,做法就是直接对库里所有向量做KMeans Clustering,假设簇心个数为1024。那么每来一个query向量,首先计算其与1024个粗聚类簇心的距离,然后选择距离最近的top N个簇,只计算查询向量与这几个簇底下的向量的距离,计算距离的方法就是前面说的PQ。Faiss具体实现有一个小细节,就是在计算查询向量和一个簇底下的向量的距离的时候,所有向量都会被转化成与簇心的残差,这应该就是类似于归一化的操作,使得后面用PQ计算距离更准确一点。使用了IVF过后,需要计算距离的向量个数就少了几个数量级,最终向量检索就变成一个很快的操作。

import faiss

nlist = 100
m = 8 ##每个向量分8段
k = 4 ##求4-近邻
quantizer = faiss.IndexFlatL2(d)    # 内部的索引方式依然不变
index = faiss.IndexIVFPQ(quantizer, d, nlist, m, 8) # 每个向量都被编码为8个字节大小
index.train(xb)
index.add(xb)
index.nprobe = 10                
D, I = index.search(xq, k)          # 检索
print(I[-5:])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1437829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图数据库neo4j入门

neo4j 一、安装二、简单操作<一>、创建<二>、查询<三>、关系<四>、修改<五>、删除 三、常见报错<一>、默认的数据库密码是neo4j,打开浏览器http://localhost:7474登录不上,报错: Neo.ClientError.Security.Unauthorized: The client is un…

Tkinter教程21:Listbox列表框+OptionMenu选项菜单+Combobox下拉列表框控件的使用+绑定事件

------------★Tkinter系列教程★------------ Tkinter教程21&#xff1a;Listbox列表框OptionMenu选项菜单Combobox下拉列表框控件的使用绑定事件 Tkinter教程20&#xff1a;treeview树视图组件&#xff0c;表格数据的插入与表头排序 Python教程57&#xff1a;tkinter中如何…

【SpringBoot篇】解决Redis分布式锁的 误删问题 和 原子性问题

文章目录 &#x1f354;Redis的分布式锁&#x1f6f8;误删问题&#x1f388;解决方法&#x1f50e;代码实现 &#x1f6f8;原子性问题&#x1f339;Lua脚本 ⭐利用Java代码调用Lua脚本改造分布式锁&#x1f50e;代码实现 &#x1f354;Redis的分布式锁 Redis的分布式锁是通过利…

【RT-DETR有效改进】轻量级下采样方法ContextGuided(参数量下降700W,轻量又涨点)

&#x1f451;欢迎大家订阅本专栏&#xff0c;一起学习RT-DETR&#x1f451; 一、本文介绍 本文给大家带来的是改进机制是一种替换Conv的模块Context Guided Block (CG block) &#xff0c;其是在CGNet论文中提出的一种模块&#xff0c;其基本原理是模拟人类视觉系统依赖上…

dbeaver免费、跨平台数据管理软件

下载 dbeaver是一款的数据库连接工具&#xff0c;免费&#xff0c;跨平台。 官网&#xff1a;DBeaver Community | Free Universal Database Tool下载地址&#xff1a;Download | DBeaver Community 点击下载 安装 修改安装路径 点击安装 点击完成 使用 连接mysql 已连接 点…

一个 SpringBoot 项目能同时处理多少请求?

目录 1 问题分析 2 Demo 3 答案 4 怎么来的&#xff1f; 5 标准答案及影响参数一Tomcat配置 6 影响参数二 Web容器 7 影响参数三 Async 1 问题分析 一个 SpringBoot 项目能同时处理多少请求&#xff1f; 不知道你听到这个问题之后的第一反应是什么&#xff1f; 我大概…

Maven - 编译报错:程序包 XXX 不存在(多模块项目)

问题描述 编译报错&#xff1a;程序包 XXX 不存在&#xff08;多模块项目&#xff09; 原因分析 检查依赖模块 pom 文件&#xff0c;看是不是引入了如下插件 <plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-pl…

STM32/C51开发环境搭建(KeilV5安装)

Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统&#xff0c;与汇编相比&#xff0c;C语言在功能上、结构性、可读性、可维护性上有明显的优势&#xff0c;因而易学易用。Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等…

5.electron之主进程起一个本地服务

如果可以实现记得点赞分享&#xff0c;谢谢老铁&#xff5e; Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 Electron 将 Chromium 和 Node.js 嵌入到了一个二进制文件中&#xff0c;因此它允许你仅需一个代码仓库&#xff0c;就可以撰写支持 Windows、…

信钰证券:稀土板块集体爆发,十余股涨停!脑机接口新进展

脑机接口迎多重利好。 大盘指数早间延续反弹&#xff0c;深证成指一度涨逾3%&#xff0c;半导体芯片、医药医疗、军工等方向涨幅居前。白酒股震荡拉升&#xff0c;金徽酒涨超7%&#xff0c;老白干酒涨超5%&#xff0c;金种子酒、迎驾贡酒等跟涨。 高股息股逆势走弱&#xff0c…

使用ChatGpt和文心一言辅助文章创作

近期在写数字水浒系列文章&#xff0c;使用了ChatGpt和文心一言进行辅助创作&#xff0c;整体感受不错&#xff0c;提高了工作效率。 在使用过程中&#xff0c;感觉文心的中文能力更强一些&#xff0c;主要体现在&#xff1a; 1 语料库更大&#xff0c;比如对水浒传了解的更多…

Flask 入门7:使用 Flask-Moment 本地化日期和时间

如果Web应用的用户来自世界各地&#xff0c;那么处理日期和时间可不是一个简单的任务。服务器需要统一时间单位&#xff0c;这和用户所在的地理位置无关&#xff0c;所以一般使用协调世界时&#xff08;UTC&#xff09;。不过用户看到 UTC 格式的时间会感到困惑&#xff0c;他们…

数据结构-->线性表-->顺序表

对我个人来说&#xff0c;C语言基础相关的知识基本学完了&#xff0c;随后就该学数据结构了&#xff0c;希望以后自己复习能够用上今天自己写的哈哈。 如果你不理解什么是物理结构和逻辑结构&#xff0c;这里附上一个链接&#xff1a;逻辑结构和物理结构&#xff1a;逻辑结构与…

c语言贪食蛇游戏

演示视频 目录 一.概述 二.游戏开始前 修改控制台程序标题和大小 Win32 API GetStdHandle函数 GetConsoleCursorInfo函数和SetConsoleCursorInfo函数 SetConsoleCursorPosition函数 游戏开篇界面处理 创建地图 蛇身节点以及食物节点初始化 蛇身的初始化 整体蛇节点…

通过 docker-compose 部署 Flink

概要 通过 docker-compose 以 Session Mode 部署 flink 前置依赖 Docker、docker-composeflink 客户端docker-compose.yml version: "2.2" services:jobmanager:image: flink:1.17.2ports:- "8081:8081"command: jobmanagervolumes:- ${PWD}/checkpoin…

JSDoc 注释规范

JSDoc 注释 在 前端项目中&#xff0c;注释格式包含了一些特殊标记&#xff0c;如 param、returns 等&#xff0c;这种注释通常是用来标记函数或方法的参数和返回值的数据类型和描述。 这种注释格式通常被称为 JSDoc 注释。在实际开发中&#xff0c;这样的注释可以被一些工具解…

[总结]HTML+JS逆向混淆混合

国外的题果然考得与众不同 [secrypt_cen.html] 这次是HTML网页&#xff0c;然后JS加密判断 翻看JS代码 {width"5.75in" height"3.375in"} 很显然&#xff0c;关键的代码在checkPassword JS混淆是必备的 去混淆一条龙走起 先将关键代码提取出来 JavaScriptf…

Java项目使用jasypt加密和解密配置文件中关键信息

一、使用背景 项目中application.yml 配置文件中&#xff0c;如数据库、redis、加密算法的私钥等各种配置的username&#xff0c;password的值都是明文的&#xff0c;其实存在一定的安全隐患&#xff0c;如果被人拿到这些配置文件&#xff0c;将直接对系统安全构成极大威胁&…

Python库-PyAutoGUI

pyautogui是一个Python库&#xff0c;可以自动控制键盘和鼠标&#xff0c;非常适合进行自动化任务。它可以用于各种场景&#xff0c;比如自动化测试、数据录入任务&#xff0c;甚至是简单的游戏机器人。下面是一个关于pyautogui的入门教程&#xff0c;包括它的安装、基本使用方…

Hadoop-IDEA开发平台搭建

1.安装下载Hadoop文件 1&#xff09;hadoop-3.3.5 将下载的文件保存到英文路径下&#xff0c;名称一定要短。否则容易出问题&#xff1b; 2&#xff09;解压下载下来的文件&#xff0c;配置环境变量 3&#xff09;我的电脑-属性-高级设置-环境变量 4.详细配置文件如下&#…