向量数据库Annoy和Milvus

Annoy 和 Milvus 都是用于向量索引和相似度搜索的开源库,它们可以高效地处理大规模的向量数据。

Annoy(Approximate Nearest Neighbors Oh Yeah):

  • Annoy 是一种近似最近邻搜索算法,它通过构建一个树状结构来加速最近邻搜索。
  • Annoy 支持支持欧氏距离,曼哈顿距离,余弦距离,汉明距离或点(内)乘积距离等多种度量方式。
  • Annoy 是一个轻量级的库,易于使用和集成,如果向量维度不是太多(例如<100维),效果会比较好。
  • 目前 Annoy 主要支持 Python 和 C++ 接口。

Milvus:

  • Milvus 是一个基于向量相似度搜索的开源引擎,它可以将大规模向量数据快速存储和检索。
  • Milvus 使用了各种索引和算法优化技术,提供了高效的向量搜索能力。
  • Milvus 支持欧式距离、内积相似度等多种度量方式,且具有扩展性和可定制性。
  • Milvus 提供了 Python、Java 和 Go 等多种编程语言的接口。
  • Milvus 还提供了图形用户界面 (GUI) 和可视化工具来辅助管理和查询向量数据库。

选择 Annoy 还是 Milvus 取决于您的具体需求和应用场景:

  • 如果对于近似最近邻搜索的速度轻量级集成更为关注,可以选择 Annoy。(demo入门)
  • 如果需要管理和查询大规模的向量数据库,并希望具备更多的功能和可扩展性,可以选择 Milvus。(工业级应用)

1. Annoy

Annoy (Approximate Nearest Neighbors Oh Yeah)是一个带有Python bindings的C ++库,用于搜索空间中给定查询点的近邻点。它还会创建大型的基于文件的只读数据结构,并将其映射到内存中,以便许多进程可以共享相同的数据。annoy的学习成本非常低,能较快的掌握,非常适合项目的快速开发,于此对比的是,faiss和Milvus的学习成本较高,用起来较为复杂。

用于空间检索近邻的数据。检索过程分成三步:

  • 建立索引过程;
  • 近邻查询过程;
  • 返回最终近邻节点;

首先先来一张2D数据分布图:
在这里插入图片描述

接下来按照步骤1,2和3进行分析。

1.1 建立索引过程

Annoy的目标是建立一个数据结构,使得查询一个点的最近邻点的时间复杂度是次线性。Annoy 通过建立一个二叉树来使得每个点查找时间复杂度是O(log n)。以下图为例,随机选择两个点,以这两个节点为初始中心节点,执行聚类数为2的kmeans过程,最终产生收敛后两个聚类中心点。这两个聚类中心点之间连一条线段(灰色短线),建立一条垂直于这条灰线,并且通过灰线中心点的线(黑色粗线)。这条黑色粗线把数据空间分成两部分。在多维空间的话,这条黑色粗线可以看成等距垂直超平面。
在这里插入图片描述

在划分的子空间内进行不停的递归迭代继续划分,直到每个子空间最多只剩下K个数据节点。

在这里插入图片描述

通过多次递归迭代划分的话,最终原始数据会形成类似下图的二叉树结构。二叉树底层是叶子节点记录原始数据节点其他中间节点记录的是分割超平面的信息。Annoy建立这样的二叉树结构是希望满足这样的一个假设: 相似的数据节点应该在二叉树上位置更接近,一个分割超平面不应该把相似的数据节点分割二叉树的不同分支上。

在这里插入图片描述
根据上述步骤,建立多棵二叉树树,构成一个森林。

1.2 近邻查询过程

上面已完成节点索引建立过程。如何进行对一个数据点进行查找相似节点集合呢?比如下图的红色节点,查找的过程就是不断看他在分割超平面的哪一边。从二叉树索引结构来看,就是从根节点不停的往叶子节点遍历的过程。通过对二叉树每个中间节点(分割超平面相关信息)和查询数据节点进行相关计算来确定二叉树遍历过程是往这个中间节点左孩子节点走还是右孩子节点走。通过以上方式完成查询过程。

在这里插入图片描述

查询过程采用优先队列机制:采用一个优先队列来遍历二叉树,从根节点往下的路径,根据查询节点与当前分割超平面距离进行排序。

在这里插入图片描述

1.3 返回最终近邻节点

步骤1会构建多棵二叉树树,每棵树都返回一堆近邻点后,如何得到最终的Top N相似集合呢?首先所有树返回近邻点都插入到优先队列中,求并集去重, 然后计算和查询点距离,最终根据距离值从近距离到远距离排序,返回Top-N近邻节点集合。

1.4 完整的Python API

  • AnnoyIndex(f, metric)返回可读写的新索引,用于存储f维度向量。metric 可以"angular""euclidean""manhattan""hamming""dot"
  • a.add_item(i, v)用于给索引添加向量v,i(任何非负整数)是给向量v的表示。
  • a.build(n_trees)用于构建 n_trees 的森林。查询时,树越多,精度越高。在调用build后,无法再添加任何向量。
  • a.save(fn, prefault=False)将索引保存到磁盘。保存后,不能再添加任何向量。
  • a.load(fn, prefault=False)从磁盘加载索引。如果prefault设置为True,它将把整个文件预读到内存中。默认值为False。
  • a.unload() 释放索引。
  • a.get_nns_by_item(i, n, search_k=-1, include_distances=False)返回第i 个item的n个最近邻的item。在查询期间,它将检索多达search_k(默认n_trees * n)个点。search_k为您提供了更好的准确性和速度之间权衡。如果设置include_distances为True,它将返回一个包含两个列表的2元素元组:第二个包含所有对应的距离。
  • a.get_nns_by_vector(v, n, search_k=-1, include_distances=False)与上面的相同,但按向量v查询。
  • a.get_item_vector(i)返回第i个向量前添加的向量。
  • a.get_distance(i, j)返回向量i和向量j之间的距离。注意:此函数用于返回平方距离。
  • a.get_n_items() 返回索引中的向量数。
  • a.get_n_trees() 返回索引中的树的数量。
  • a.on_disk_build(fn) 用以在指定文件而不是RAM中建立索引(在添加向量之前执行,在建立之后无需保存)。

Notes:
Annoy使用归一化向量的欧式距离作为其角距离,对于两个向量u,v,其等于 sqrt(2(1-cos(u,v)))
C ++ API非常相似:调用annoy只需使用#include "annoylib.h"

权衡
调整Annoy仅需要两个主要参数:树的数量 n_trees 和搜索期间要检查的节点的数量search_k

  • n_trees在构建索引期间提供该值,并且会影响构建时间和索引大小。较大的值将给出更准确的结果,但索引较大。
  • search_k是在运行时提供的,并且会影响搜索性能。较大的值将给出更准确的结果,但返回时间将更长。

如果search_k未提供,它将默认为n * n_trees * Dn是近似最近邻居的数目,并且D是一个常数,取决于向量维度。否则,search_kn_trees是大致独立的,即如果search_k保持不变,n_trees不会影响搜索时间,反之亦然。基本上,在您可以负担的内存使用量的情况下建议在n_trees可能大的值,并且在给定查询时间的限制的情况下建议设置search_k尽可能大。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

并行和并发的区别

从操作系统的角度来看&#xff0c;线程是CPU分配的最小单位。 并行就是同一时刻&#xff0c;两个线程都在执行。这就要求有两个CPU去分别执行两个线程。并发就是同一时刻&#xff0c;只有一个执行&#xff0c;但是一个时间段内&#xff0c;两个线程都执行了。并发的实现依赖于…

旅游APP外包开发注意事项

旅游类APP通常具有多种功能&#xff0c;以提供给用户更好的旅行体验。以下分享常见的旅游类APP功能以及在开发和使用这些APP时需要注意的问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 常见功能…

【HCIE】01.IGP高级特性

高级特性&#xff1a;一条命令解决一个问题 OSPF快速收敛机制 发生故障重新计算拓扑的过程叫做收敛&#xff0c;设备现在本身就是PRC算法和I-SPF算法 PRC&#xff08;针对叶子节点&#xff0c;叶子代表路由&#xff09; 不需要命令配置&#xff0c;就是ospf的特性&#xff…

LeetCode —— 复写零(双指针)

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 将数组中出现的每个零复写一遍&#xff0c;然后将其他元素向右平移&#xff0c;数组长度不能改变。 法一&#xff1a;使用额外空间的做法 class Solution { public:void duplica…

Redis7入门概述

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…

DiffBIR: Towards Blind Image Restoration with Generative Diffusion Prior

DiffBIR: 基于生成扩散先验的盲图像恢复 论文链接&#xff1a;https://arxiv.org/abs/2308.15070 项目链接&#xff1a;https://github.com/XPixelGroup/DiffBIR Abstract 我们提出了DiffBIR&#xff0c;它利用预训练的文本到图像扩散模型来解决盲图像恢复问题。我们的框架采…

Golang单元测试举例

1.第一个例子 cal.go package mainfunc addUpper(n int) int {res : 0for i : 1; i < n; i {res i}return res }func getSub(n1 int, n2 int) int {return n1 - n2 }cal_test.go package main//测试文件名必须是_test.go结尾 //测试函数必须Test开头 import ("fmt…

C/C++语言简易图形库EasyX库和EGE图形库

有些学校直接拿 VC 来讲 C 语言&#xff0c;因为 VC 的编辑和调试环境都很优秀&#xff0c;并且 VC 有适合教学的免费版本。可惜在 VC 里面只能做一些文字性的练习题&#xff0c;想画条直线或一个圆都很难&#xff0c;例如需要注册窗口类、建消息循环等等&#xff0c;初学者会受…

Vue + Element UI 前端篇(七):功能组件封装

组件封装 为了避免组件代码的臃肿&#xff0c;这里对主要的功能部件进行封装&#xff0c;保证代码的模块化和简洁度。 组件结构 组件封装重构后&#xff0c;试图组件结构如下图所示 代码一览 Home组件被简化&#xff0c;包含导航、头部和主内容三个组件。 Home.vue <te…

2023年数维杯数学建模A题河流-地下水系统水体污染研求解全过程文档及程序

2023年数维杯数学建模 A题 河流-地下水系统水体污染研 原题再现&#xff1a; 河流对地下水有着直接地影响&#xff0c;当河流补给地下水时&#xff0c;河流一旦被污染&#xff0c;容易导致地下水以及紧依河流分布的傍河水源地将受到不同程度的污染&#xff0c;这将严重影响工…

Python测试框架 Pytest —— mock使用(pytest-mock)

pytest-mock 安装&#xff1a;pip install pytest-mock 这里的mock和unittest的mock基本上都是一样的&#xff0c;唯一的区别在于pytest.mock需要导入mock对象的详细路径。 # weateher_r.py class Mock_weather():def weather(self):天气接口passdef weather_result(self):模…

异常-java

目录 一、异常的概念和体系结构 1.1 异常的概念 1.2 异常的体系结构 1.3 异常的分类 二、异常的处理 2.1 防御式编程 2.2 异常抛出 2.3 异常捕获 2.4 异常处理流程 三、自定义异常类 一、异常的概念和体系结构 1.1 异常的概念 程序员在开发过程中&#xff0c;想要将代码写得…

《代码随想录》刷题笔记——链表篇【java实现】

链表节点定义 public class ListNode {// 结点的值int val;// 下一个结点ListNode next;// 节点的构造函数(无参)public ListNode() {}// 节点的构造函数(有一个参数)public ListNode(int val) {this.val val;}// 节点的构造函数(有两个参数)public ListNode(int val, ListNo…

Go实现LogCollect:海量日志收集系统【上篇——LogAgent实现】

Go实现LogCollect&#xff1a;海量日志收集系统【上篇——LogAgent实现】 下篇&#xff1a;Go实现LogCollect&#xff1a;海量日志收集系统【下篇——开发LogTransfer】 项目架构图&#xff1a; 0 项目背景与方案选择 背景 当公司发展的越来越大&#xff0c;业务越来越复杂…

虚拟机扩容

系统环境centos8&#xff0c;分两步&#xff0c;第一步先在vmware扩容&#xff0c;第二部在虚拟机内部扩容 1.vmware分配磁盘空间 2.虚拟机内部扩容 查看当前磁盘信息&#xff0c;这个是扩容之前的&#xff0c;扩容完成才会显示新的 df -h查看系统分区信息 fdisk -l查看目录…

javaee spring aop 注解实现

切面类 package com.test.advice;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*;//切面类 Aspect public class MyAdvice {//定义切点表达式Pointcut("execution(* com.test.service.impl.*.add(..))")public void pc(){}//B…

Git管理

Git管理 ①对于项目目录中有.git的&#xff0c;可以在idea里面更改远程提交地址 Git->>Manage Remotes 中修改远程提交地址 ②对于没有.git目录的项目 在项目的根目录下进入cmd&#xff0c;使用下面的语句初始化.git目录 ##初始化 git init

Leetcode 1486.数组异或操作

给你两个整数&#xff0c;n 和 start 。 数组 nums 定义为&#xff1a;nums[i] start 2*i&#xff08;下标从 0 开始&#xff09;且 n nums.length 。 请返回 nums 中所有元素按位异或&#xff08;XOR&#xff09;后得到的结果。 示例 1&#xff1a; 输入&#xff1a;n 5, …

springcloud-Eureka

1.Eureka注册中心 1.1 简介与依赖导入 1.2 服务注册与发现 启动eureka模块 访问Eureka 将user-service,book-service,borrow-service作为eureka的客户端&#xff0c;先导包。三个导入方式一样。 配置文件&#xff0c;三个模块下都一样配置 然后分别启动三个模块 发现注册…

MySQL性能分析工具的使用

1. 数据库服务器的优化步骤 当我们遇到数据库调优问题的时候&#xff0c;该如何思考呢&#xff1f;这里把思考的流程整理成下面这张图。 整个流程划分成了 观察&#xff08; Show status &#xff09; 和 行动&#xff08; Action &#xff09; 两个部分。字母 S 的部分…