推荐算法:HNSW【推荐出与用户搜索的类似的/用户感兴趣的商品】

news2024/11/25 6:40:03

HNSW算法概述

HNSW(Hierarchical Navigable Small Word)算法算是目前推荐领域里面常用的ANN(Approximate Nearest Neighbor)算法了。其目的就是在极大量的候选集当中如何快速地找到一个query最近邻的k个元素

要找到一个query的k个最近邻元素,一个朴素的思想就是我去计算这个query和所有的总量N 个候选元素的距离,然后选择其中的前k 个最小元素,这个经典算法的算法复杂度是O(Nlog(k)),显然这个算法复杂度实在是太高了,无法适用于实际的使用场景。

而要解决这个问题,可以有多种实现方法,这里所要说的HNSW算法就是目前比较常用的一种搜索算法,它算是其前作NSW算法的一个升级版本,但是两者的本质都是基于一个朴素的思路,就是通过图连接的方式给所有的N 个候选元素事先地定义好一个图连接关系,从而可以将前述的算法复杂度当中的N 的部分给减小掉,从而优化整体的检索效率

其整体的一个图结果可以用下图进行表达:

解决的问题做高效率相似性查找。推荐系统中,如何找到与用户query最相近的几个item,然后推荐出去【也就是推荐出与用户搜索的类似的/用户感兴趣的商品】

解决方法有:Annoy,KD-Tree, LSH, PQ,NSW, HNSW等。

近似最近邻搜索算法(Approximate Nearest Neighbor Search,ANNS)发展:近邻图(Proximity Graph)–> NSW --> Skip List --> HNSW

近似最近邻搜索算法(Approximate Nearest Neighbor Search,ANNS)

1. 近邻图(Proximity Graph)

近邻图(Proximity Graph): 最朴素的图算法

思路: 构建一张图, 每一个顶点连接着最近的 N 个顶点。 Target (红点)是待查询的向量。在搜索时, 选择任意一个顶点出发。 首先遍历它的友节点, 找到距离与 Target 最近的某一节点, 将其设置为起始节点, 再从它的友节点出发进行遍历, 反复迭代, 不断逼近, 最后找到与 Target 距离最近的节点时搜索结束。

存在的问题:

  1. 图中的K点无法被查询到。
  2. 如果要查找距离Target (红点)最近的topK个点, 而如果点之间无连线, 将影响查找效率。
  3. D点有这么多友节点吗? 增加了构造复杂度。谁是谁的友节点如何确定?
  4. 如果初始点选择地不好(比如很远),将进行多步查找。

2. NSW算法原理

NSW,即没有分层的可导航小世界的结构(Navigable-Small-World-Graph )。

针对上面的问题,解决办法:

  1. 某些点无法被查询到 -> 规定构图时所有节点必须有友节点。
  2. 相似点不相邻的问题 -> 规定构图时所有距离相近到一定程度的节点必须互为友节点。
  3. 关于某些点有过多友节点 -> 规定限制每个节点的友节点数量。
  4. 初始点选择地很远 -> 增加高速公路机制。

2.1 NSW构图算法

图中插入新节点时,通过随机存在的一个节点出发查找到距离新节点最近的m个节点(规定最多m个友节点,m由用户设置),连接新节点到这最近的m个节点。节点的友节点在新的节点插入的过程中会不断地被更新。

m=3(每个点在插入时找3个紧邻友点)。

第1次构造:图为空,随机插入A,初始点为A。图中只有A,故无法挑选友节点。插入B,B点只有A点可选,所以连接BA。

第2次构造:插入F,F只有A和B可以选,所以连接FA,FB。

第3次构造:插入C,C点只有A,B,F可选,连接CA,CB,CF。

第4次构造:插入E,从A,B,C,F任意一点出发,计算出发点与E的距离和出发点的所有“友节点”和E的距离,选出最近的一点作为新的出发点,如果选出的点就是出发点本身,那么看我们的m等于几,如果不够数,就继续找第二近的点或者第三近的点,本着不找重复点的原则,直到找到3个近点为止。找到了E的三个近点,连接EA,EC,EF。

第5次构造:插入D,与E点的插入一模一样,都是在“现成”的图中查找到3个最近的节点作为“友节点”,并做连接。

第6次构造:插入G,与E点的插入一模一样,都是在“现成”的图中查找到3个最近的节点作为“友节点”,并做连接。

在图构建的早期,很有可能构建出“高速公路”。

第n次构造:在这个图的基础上再插入6个点,这6个点有3个和E很近,有3个和A很近,那么距离E最近的3个点中没有A,距离A最近的3个点中也没有E,但因为A和E是构图早期添加的点,A和E有了连线,我们管这种连线叫“高速公路”,在查找时可以提高查找效率(当进入点为E,待查找距离A很近时,我们可以通过AE连线从E直接到达A,而不是一小步一小步分多次跳转到A)。

结论:一个点,越早插入就越容易形成与之相关的“高速公路”连接,越晚插入就越难形成与之相关的“高速公路”连接。

这个算法设计的妙处就在于扔掉德劳内三角构图法,改用“无脑添加”(NSW朴素插入算法),降低了构图算法时间复杂度的同时还带来了数量有限的“高速公路”,加速了查找。

2.2 NSW查找算法

NSW.png

图中的边有两个不同的目的:

  1. Short-range edges,用作贪婪搜索算法所需的近似 Delaunay 图。
  2. Long-range edges,用于贪婪搜索的对数缩放。负责构造图形的可导航小世界(NSW)属性。

优化查找:

  1. 建立一个废弃列表visitedSet,在一次查找任务中遍历过的点不再遍历。
  2. 建立一个动态列表result,把距离查找点最近的n个点存储在表中,并行地对这n个点进行同时计算“友节点”和待查找点的距离,在这些“友节点”中选择n个点与动态列表中的n个点进行并集操作,在并集中选出n个最近的友点,更新动态列表。

推荐算法:HNSW算法简介-CSDN博客

检索模型-粗排HNSW_hnsw模型-CSDN博客

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

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

相关文章

【ChatGLM3】第三代大语言模型多GPU部署指南

关于ChatGLM3 ChatGLM3是智谱AI与清华大学KEG实验室联合发布的新一代对话预训练模型。在第二代ChatGLM的基础之上, 更强大的基础模型: ChatGLM3-6B 的基础模型 ChatGLM3-6B-Base 采用了更多样的训练数据、更充分的训练步数和更合理的训练策略。在语义、…

2023 ACDU 中国行 · 西安站 | 数据库技术发展及实践

ACDU 中国行西安站由中国数据库联盟联合浪潮数据库等单位共同主办,特邀中国计算机学会(CCF)为本次活动的指导单位。 作为中国数据库联盟的品牌活动之一,【ACDU 中国行】在线下汇集数据库领域的行业知名人士,共同探讨数…

JIS-CTF

环境配置 正常打开虚拟机,找不到IP地址,解决方案是登录到靶机: 账号 technawi 口令 3vilHksor 然后启用网卡:sudo ifconfig ens33 up 分配IP:sudo dhclient 信息收集 # nmap -sn 192.168.1.0/24 -oN live.nmap …

【cocotb】【达坦科技DatenLord】Cocotb Workshop分享

https://www.bilibili.com/video/BV19e4y1k7EE/?spm_id_from333.337.search-card.all.click&vd_sourcefd0f4be6d0a5aaa0a79d89604df3154a 方便RFM实现 cocotb_test 替代makefile , 类似python 函数执行

pytest + yaml 框架 -59.用例失败重跑机制pytest-rerunfailures

前言 有些接口可能不太稳定,第一次跑的时候由于网络原因或者其它原因失败,但是重新跑2次又成功了。 对于这种需要重新跑几次的场景,可以使用用例失败重跑机制,需安装pytest-rerunfailures 插件。 场景示例 失败重跑需要依赖 py…

19 redis缓存数据同步问题

1、缓存穿透 指缓存和数据库中都没有的数据,而用户不断发起请求。由于缓存不命中,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,缓存就没有意义了。 在…

[CQOI2014] 危桥

[CQOI2014] 危桥 题目描述 Alice 和 Bob 居住在一个由 \(N\) 座岛屿组成的国家,岛屿被编号为 \(0\) 到 \(N-1\)。某些岛屿之间有桥相连,桥上的道路是双向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两…

【sqli靶场】第二关和第三关通关思路

目录 前言 一、sqli靶场第二关 1.1 判断注入类型 1.2 判断数据表中的列数 1.3 使用union联合查询 1.4 使用group_concat()函数 1.5 爆出users表中的列名 1.6 爆出users表中的数据 二、sqli靶场第三关 2.1 判断注入类型 2.2 观察报错 2.3 判断数据表中的列数 2.4 使用union联合…

电脑出现错误0x80004005怎么解决,解决0x80004005的问题

当电脑出现0x80004005错误时,通常是由于系统或应用程序之间的通信问题或文件系统损坏引起的。该错误代码表示未指定错误,在Windows系统中较为常见。 一.解决0x80004005错误的步骤 重新启动电脑 有时候,错误只是一个暂时的问题,重…

C语言常用字符串

目录 1.什么是字符串 2.如何定义字符串 第3和第4定义的区别:3是字符串变量,4是字符串常量,不予许被修改 3.strlen和sizeof的区别 4.地址分配(malloc,realloc,free,memset) 案例 5.字符串拷贝(strcpy,strncpy) …

【docker】容器使用(Nginx 示例)

查看 Docker 客户端命令选项 docker上面这三张图都是 常用命令: run 从映像创建并运行新容器exec 在运行的容器中执行命令ps 列出容器build 从Dockerfile构建映像pull 从注册表下载图像push 将图像上载到注册表…

windows启动出现 zookeeper此处不应有java

可能是Java 路径出了问题,这个programFiles直接有空格,没错就有空格,笔者一开始以为这么点算什么空格,需要把这个对应的Java文件到别的英文路径下,并且修改环境变量。就可以启动的。 还可以启动方式有很多种&#xff0…

【操作系统和计网从入门到深入】(二)进程

前言 这个专栏其实是博主在复习操作系统和计算机网络时候的笔记,所以如果是博主比较熟悉的知识点,博主可能就直接跳过了,但是所有重要的知识点,在这个专栏里面都会提到!而且我也一定会保证这个专栏知识点的完整性&…

python——第十七天

方法重写(overwrite) 、方法覆盖(override ):在继承的基础上,子类继承了父类的方法,如果不能满足自己使用,我们就可以重写或覆盖该方法 函数重载(overload): 在强数据类型的编程语言中(如Java、C、C等等): 函数名称…

高通平台开发系列讲解(USB篇)MBIM驱动详解

文章目录 一、数据结构二、源码分析三、adroid_mbim创建四、读写 /dev/adroid_mbim4.1、读gsi_ctrl_dev_read4.2、写gsi_ctrl_dev_write沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本文主要介绍高通平台USB网卡MBIM驱动。 一、数据结构 目录:drivers/usb/gadget/…

Python使用分段函数拟合数据

Python使用分段函数拟合数据 前言前提条件相关介绍实验环境使用分段函数拟合数据代码实现输出结果 前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可点击进入Python日常小操作专栏、OpenCV-Python小应用专栏、YOLO系列专栏…

【LeetCode】每日一题 2023_12_12 下一个更大元素 IV(堆,优先级队列/单调栈)

文章目录 刷题前唠嗑题目:下一个更大元素 IV题目描述代码与解题思路 刷题前唠嗑 LeetCode?启动!!! 时隔两天,LeetCode 每日一题重新开张,流感已经不能阻挡我的脚步了! 题目&#x…

【FAQ】推送前台应用的通知处理功能没生效,如何进行排查?

一、前台应用的通知处理简介 在调用推送接口时可以设置“foreground_show”字段控制前台应用的通知栏消息是否通过NC展示。“foreground_show”默认值为“true”,应用在前台时由NC展示通知栏消息;当设置为“false”时,应用在前台时&#xff…

<习题集><LeetCode><链表><61/83/82/86/92>

目录 61. 旋转链表 83. 删除排序链表中的重复元素 82. 删除排序链表中的重复元素 II 86. 分隔链表 92. 反转链表 II 61. 旋转链表 https://leetcode.cn/problems/rotate-list/ public ListNode rotateRight(ListNode head, int k) {//k等于0,或者head为空&…

高效利用内存资源之动态内存管理详解

目录 一、为什么存在动态内存分配 二、动态内存函数的介绍 2.1malloc 2.2free 2.3calloc 2.4realloc 三、常见的动态内存错误 3.1对NULL指针的解引用操作 3.2对动态开辟空间的越界访问 3.3对非动态开辟内存使用free释放 3.4使用free释放一块动态开辟内存的一部分 3.…