近似最近邻(ANN)算法库实战
引言:从“精确”到“近似”的思维跃迁
在电商推荐系统中,每秒需要为上百万用户找到最相关的商品——传统KNN的暴力搜索甚至无法完成一次查询,而近似最近邻(ANN)算法库如Faiss(Facebook)和Annoy(Spotify)却能轻松应对。
核心价值:通过牺牲少量精度,将搜索时间从小时级压缩到毫秒级。本文将深入解析ANN算法原理,并用代码实战展示十亿级数据的处理能力。
一、近似最近邻(ANN)的核心逻辑
1. 精度与效率的权衡
-
暴力搜索:100%精确,但无法扩展。
-
ANN算法:允许5%~10%的误差,换取百倍速度提升。
-
数学保障:Johnson-Lindenstrauss引理证明,高维数据可低损压缩至低维。
2. ANN算法分类
| 算法类型 | 代表库 | 适用场景 |
|---|---|---|
| 树型分割 | Annoy | 中低维数据(d < 1000) |
| 量化编码 | Faiss | 高维数据(d > 1000) |
| 图索引 | HNSW | 高精度召回 |
二、Faiss:十亿级向量的GPU加速引擎
1. 核心优化技术
-
倒排索引(IVF):将数据聚类为多个桶,搜索时仅扫描最近几个桶。
-
乘积量化(PQ):将向量切分为子向量并分别量化,大幅压缩内存占用。
2. 代码实战:十亿级向量构建与查询
import faiss
import numpy as np# 生成10亿条128维随机数据(模拟商品特征)
d = 128
nb = 1_000_000_000
np.random.seed(1234)
vectors = np.random.random((nb, d)).astype('float32')# 构建索引(IVF + PQ)
nlist = 1024 # 聚类中心数
m = 16 # 子向量数(必须能被d整除)
quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFPQ(quantizer, d, nlist, m, 8) # 8 bits编码# 训练索引(需要少量样本)
index.train(vectors[:10000]) # 随机采样1万条训练# 添加数据(分批次防止内存溢出)
batch_size = 1000000
for i in range(0, nb, batch_size):index.add(vectors[i:i+batch_size])# 保存索引
faiss.write_index(index, "billion_vector.index")# 查询(搜索最近10个邻居)
query = np.random.random((1, d)).astype('float32')
k = 10
distances, indices = index.search(query, k)
print(f"最近邻索引: {indices}")
3. 性能对比(128维数据)
| 数据规模 | 方法 | 构建时间 | 单次查询时间 | 内存占用 |
|---|---|---|---|---|
| 1亿 | 暴力搜索 | - | 1200ms | 48GB |
| 1亿 | Faiss(IVF) | 25min | 6ms | 1.2GB |
| 10亿 | Faiss(IVFPQ) | 3.5h | 15ms | 5GB |
结论:Faiss在十亿级数据下仍保持毫秒级响应,内存仅为暴力搜索的1/10!
三、Annoy:轻量级树型ANN库
1. 核心原理
-
随机投影树(RP-Tree):通过超平面递归分割数据空间。
-
森林提升鲁棒性:构建多棵树,综合投票结果减少随机性误差。
2. 代码实战:百万级新闻推荐
from annoy import AnnoyIndex# 配置参数
d = 300 # 词向量维度
n_trees = 50 # 树的数量(越多精度越高,内存越大)# 初始化索引
t = AnnoyIndex(d, 'angular') # 余弦相似度# 加载数据(假设已有100万条新闻向量)
for i in range(1_000_000):vector = load_news_vector(i) # 自定义加载函数t.add_item(i, vector)# 构建索引
t.build(n_trees)# 保存与加载
t.save('news.ann')
u = AnnoyIndex(d, 'angular')
u.load('news.ann')# 查询第666号新闻的相似内容
similar_ids = u.get_nns_by_item(666, 10) # 返回10个最相似新闻ID
3. 参数调优指南
-
n_trees:树的数量(默认10),增加可提升精度,但增加内存和构建时间。
-
search_k:搜索时检查的节点数(默认n_trees*n),越大越精确但越慢。
四、案例实战:Spotify音乐推荐系统优化
1. 原始痛点
-
数据规模:5000万歌曲特征,用户实时播放时需秒级推荐。
-
传统方法:暴力搜索耗时超过5秒,用户体验差。
2. Annoy优化方案
# 使用100棵树构建索引
t = AnnoyIndex(128, 'euclidean')
t.load('music_vectors.ann')# 实时查询加速
@app.route('/recommend', methods=['POST'])
def recommend():user_vector = request.json['vector']ids = t.get_nns_by_vector(user_vector, 20) # 20ms内返回结果return jsonify(ids)
优化结果:
-
查询时间:5000ms → 20ms
-
准确率:98% → 94%(用户无感知差异)
五、陷阱与注意事项
-
数据分布敏感:Annoy对聚类数据效果佳,均匀分布数据可能低效。
-
动态更新限制:Faiss索引一旦构建无法增量更新,需全量重建。
-
精度验证:必须通过召回率(Recall@K)评估ANN效果,避免盲目追求速度。
六、延伸思考
问题:当数据持续动态更新时(如每日新增百万用户特征),如何设计高效的ANN索引更新策略?
相关文章:
近似最近邻(ANN)算法库实战
引言:从“精确”到“近似”的思维跃迁 在电商推荐系统中,每秒需要为上百万用户找到最相关的商品——传统KNN的暴力搜索甚至无法完成一次查询,而近似最近邻(ANN)算法库如Faiss(Facebook)和Annoy…...
Linux与UDP应用2:简易聊天室
UDP应用2:简易聊天室 本篇介绍 在前面的基本使用过程中已经完成了本地和网络通信,既然一个人和一台服务器可以进行通信,那么多个人连接一台服务器也可以和这台服务器实现通信。在这个基础上,如果服务器可以将某个人发给服务器的…...
张雪峰教育观点及争议分析
李升伟 整理 张雪峰(网络常用名,本名张子彪)是中国知名的考研辅导教师、教育领域自媒体人,因其幽默犀利的语言风格和直击痛点的教育观点走红网络。以下是对他的基本介绍及综合评价: --- ### **一、基本情况** 1. **个…...
从0开始的IMX6ULL学习篇——裸机篇之分析粗略IMX6ULL与架构
目录 简单的说一下Cortex-A7架构 讨论ARMv7a-cortex系列的运行模式 寄存器 后言 让我们到NXP的官网上扫一眼。 i.MX 6ULL应用处理器_Arm Cortex-A7单核,频率为900 MHz | NXP 半导体 我们先看CPU Platform,这个是我们的核心。 这里我们的芯片是基于Ar…...
面向实时性的超轻量级动态感知视觉SLAM系统
一、重构后的技术架构设计(基于ROS1 ORB-SLAM2增强) #mermaid-svg-JEJte8kZd7qlnq3E {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JEJte8kZd7qlnq3E .error-icon{fill:#552222;}#mermaid-svg-JEJte8kZd7qlnq3E .…...
Hue UI展示中文
个人博客地址:Hue UI展示中文 | 一张假钞的真实世界 如果使用开发分支代码如master分支)编译安装,需要自己编译语言文件。例如Hue安装目录为“/opt/hue”,则安装后执行以下命令: $ cd /opt/hue $ make locales 如果…...
C#贪心算法
贪心算法:生活与代码中的 “最优选择大师” 在生活里,我们常常面临各种选择,都希望能做出最有利的决策。比如在超市大促销时,面对琳琅满目的商品,你总想用有限的预算买到价值最高的东西。贪心算法,就像是一…...
【新人系列】Python 入门专栏合集
✍ 个人博客:https://blog.csdn.net/Newin2020?typeblog 📝 专栏地址:https://blog.csdn.net/newin2020/category_12801353.html 📣 专栏定位:为 0 基础刚入门 Python 的小伙伴提供详细的讲解,也欢迎大佬们…...
SQL命令详解之数据的查询操作
目录 1 简介 2 基础查询 2.1 基础查询语法 2.2 基础查询练习 3 条件查询 3.1 条件查询语法 3.2 条件查询练习 4 排序查询 4.1 排序查询语法 4.2 排序查询练习 5 聚合函数 5.1 一般语法: 5.2 聚合函数练习 6 分组查询 6.1 分组查询语法 6.2 分组查询…...
序列化选型:字节流抑或字符串
序列化既可以将对象转换为字节流,也可以转换为字符串,具体取决于使用的序列化方式和场景。 转换为字节流 常见工具及原理:在许多编程语言中,都有将对象序列化为字节流的机制。例如 Python 中的 pickle 模块、Java 中的对象序列化…...
使用C#控制台调用本地部署的DeepSeek
1、背景 春节期间大火的deepseek,在医疗圈也是火的不要不要的。北京这边的医院也都在搞“deepseek竞赛”。友谊、北医三院等都已经上了,真是迅速啊! C#也是可以进行对接,并且非常简单。 2、具体实现 1、使用Ollama部署DeepSeek…...
Linux环境安装Nginx及版本升级指南
Linux环境安装Nginx及版本升级指南 一、安装Nginx 1. 安装前准备 # 更新系统软件包(Ubuntu/Debian) sudo apt update && sudo apt upgrade -y# CentOS/RHEL sudo yum update -y2. 安装依赖库 # Ubuntu/Debian sudo apt install -y curl wget…...
选开源CMS建站系统时,插件越多越好吗?
在选择开源CMS建站系统时,插件数量并不是唯一的衡量标准,更不能简单地说“插件越多就越好”,还是需要综合评估来考虑选择结果,以下是有关选择开源CMS系统时对插件数量的考量。 插件数量的优势插件数量可能带来的问题功能丰富性&a…...
Windows对比MacOS
Windows对比MacOS 文章目录 Windows对比MacOS1-环境变量1-Windows添加环境变量示例步骤 1:打开环境变量设置窗口步骤 2:添加系统环境变量 2-Mac 系统添加环境变量示例步骤 1:打开终端步骤 2:编辑环境变量配置文件步骤 3࿱…...
使用 Python 实现基于 AGA8 GERG - 2008 方程计算掺氢天然气压缩因子的示例代码
AGA8 GERG - 2008 方程是用于计算天然气混合物热力学性质的一种方法,下面是一个使用 Python 实现基于 AGA8 GERG - 2008 方程计算掺氢天然气压缩因子的示例代码。需要注意的是,AGA8 GERG - 2008 方程非常复杂,完整实现需要大量的系数和详细的…...
开源绝版经典小游戏合集
随着生活节奏的日益加快,我们常常需要一些小游戏来缓解疲惫的身心。过去,Windows 7自带的扫雷、蜘蛛纸牌等小游戏深受大家喜爱,但随着系统的更新换代,这些经典游戏逐渐淡出了人们的视野。我也曾花费不少时间寻找这些游戏ÿ…...
给虚拟机配置IP
虚拟机IP这里一共有三个地方要设置,具体说明如下: (1)配置vm虚拟机网段 如果不进行设置,每次启动机器时都可能是随机的IP,不方便我们后续操作。具体操作是:点击编辑→虚拟网络编辑器 选择VMne…...
YOLOv12以注意力机制为核心的架构:主要特点、创新点、使用方法
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
GD32F450 使用
GB32F450使用 1. 相关知识2. 烧写程序3. SPI3.1 spi基础3.2 spi代码 4. 串口4.1 串口引脚4.2 串口通信代码 问题记录1. 修改晶振频率 注意:GD32F450 总共有三种封装形式,本文所述的相关代码和知识,均为 GD32F450IX 系列。 1. 相关知识 参数配…...
Linux 动静态库和_make_进度条(一)
文章目录 一、如何理解条件编译二、动静态库1. 理论2. 实践3. 解决普通用户的sudo问题4. 技术上理解库 三、make和make_file 一、如何理解条件编译 1. gcc code.c -o code -DM 命令行级别的宏定义预处理的本质就是修改编辑我们的文本代码 头文件展开到源文件中去注释宏替换条…...
Android 图片压缩详解
在 Android 开发中,图片压缩是一个重要的优化手段,旨在提升用户体验、减少网络传输量以及降低存储空间占用。以下是几种主流的图片压缩方法,结合原理、使用场景和优缺点进行详细解析。 效果演示 直接先给大家对比几种图片压缩的效果 质量压缩 质量压缩:根据传递进去的质…...
C# 牵手DeepSeek:打造本地AI超能力
一、引言 在人工智能飞速发展的当下,大语言模型如 DeepSeek 正掀起新一轮的技术变革浪潮,为自然语言处理领域带来了诸多创新应用。随着数据隐私和安全意识的提升,以及对模型部署灵活性的追求,本地部署 DeepSeek 成为众多开发者和…...
普通人高效使用DeepSeek指南?
李升伟 整理 DeepSeek(深度求索)作为一款智能搜索引擎或AI工具,普通人可以通过以下方式高效利用它,提升学习、工作和生活效率: --- ### **一、基础功能:精准搜索** 1. **明确需求提问** 用自然语言…...
卢卡斯定理判断组合数奇偶(Codeforces Round 1006 (Div. 3)——F)
文章目录 组合数奇偶判断题意思路综上 组合数奇偶判断 【用杨辉三角阐释Lucas定理】https://www.bilibili.com/video/BV14F411P7ES?vd_source67186f29c3efb728bcff34035cf5aba2 这个视频可以简单的领会一下精神,卢卡斯定理也就是用于组合数取模。 奇偶性通过对2…...
ECharts组件封装教程:Vue3中的实践与探索
在日常的前端开发中,ECharts 作为一款强大且易用的图表库,被广泛应用于数据可视化场景。为了更好地在 Vue3 项目中复用 ECharts 功能,我们可以将其封装成一个组件。本文将带大家一步步实现 ECharts 的 Vue3 组件封装,并演示如何在父组件中调用和使用。 一、封装 ECharts 组…...
LLM中的Benchmark是什么
LLM中的Benchmark是什么 “DeepSeek推动价值重估Benchmark” DeepSeek这家公司或其相关技术的发展,促使Benchmark这家机构对相关资产或企业的价值进行重新评估。“Benchmark”在这里是一家研究机构或金融分析机构。 “Benchmark”常见的意思是“基准;水准点,基准点”,作…...
【新加坡】软件工程师工签政策、求职指南
文章目录 关键要点就业准证要求求职平台注意事项详细报告就业准证(EP)要求求职平台与投递渠道注意事项与求职建议表格:求职平台对比额外考虑关键引用 关键要点 去新加坡工作需要申请就业准证(EP),通常要求…...
梯度下降法(Gradient Descent) -- 现代机器学习的血液
梯度下降法(Gradient Descent) – 现代机器学习的血液 梯度下降法是现代机器学习最核心的优化引擎。本文从数学原理、算法变种、应用场景到实践技巧,用三维可视化案例和代码实现揭示其内在逻辑,为你构建完整的认知体系。 优化算法 一、梯度下降法的定义…...
CMake宏定义管理:如何优雅处理第三方库的宏冲突
在C/C项目开发中,我们常常会遇到这样的困境: 当引入一个功能强大的第三方库时,却发现它定义的某个宏与我们的项目产生冲突。比如: 库定义了 BUFFER_SIZE 1024,而我们需要 BUFFER_SIZE 2048库内部使用 DEBUG 宏控制日志…...
【计算机网络】常见tcp/udp对应的应用层协议,端口
TCP 和 UDP 对应的常见应用层协议 📌 基于 TCP 的应用层协议 协议全称用途默认端口HTTPHyperText Transfer Protocol超文本传输协议80HTTPSHTTP Secure加密的超文本传输协议443FTPFile Transfer Protocol文件传输协议(20 传输数据,21 控制连…...
