Python利用Faiss库实现ANN近邻搜索的方法详解


Posted in Python onAugust 03, 2020

Embedding的近邻搜索是当前图推荐系统非常重要的一种召回方式,通过item2vec、矩阵分解、双塔DNN等方式都能够产出训练好的user embedding、item embedding,对于embedding的使用非常的灵活:

  • 输入user embedding,近邻搜索item embedding,可以给user推荐感兴趣的items
  • 输入user embedding,近邻搜搜user embedding,可以给user推荐感兴趣的user
  • 输入item embedding,近邻搜索item embedding,可以给item推荐相关的items

然而有一个工程问题,一旦user embedding、item embedding数据量达到一定的程度,对他们的近邻搜索将会变得非常慢,如果离线阶段提前搜索好在高速缓存比如redis存储好结果当然没问题,但是这种方式很不实时,如果能在线阶段上线几十MS的搜索当然效果最好。

Faiss是Facebook AI团队开源的针对聚类和相似性搜索库,为稠密向量提供高效相似度搜索和聚类,支持十亿级别向量的搜索,是目前最为成熟的近似近邻搜索库。

接下来通过jupyter notebook的代码,给大家演示下使用faiss的简单流程,内容包括:

  • 读取训练好的Embedding数据
  • 构建faiss索引,将待搜索的Embedding添加进去
  • 取得目标Embedding,实现搜索得到ID列表
  • 根据ID获取电影标题,返回结果

对于已经训练好的Embedding怎样实现高速近邻搜索是一个工程问题,facebook的faiss库可以构建多种embedding索引实现目标embedding的高速近邻搜索,能够满足在线使用的需要

安装命令:

conda install -c pytorch faiss-cpu

提前总结下faiss使用经验:

1. 为了支持自己的ID,可以用faiss.IndexIDMap包裹faiss.IndexFlatL2即可

2. embedding数据都需要转换成np.float32,包括索引中的embedding以及待搜索的embedding

3. ids需要转换成int64类型

1. 准备数据

import pandas as pd
import numpy as np
df = pd.read_csv("./datas/movielens_sparkals_item_embedding.csv")
df.head()

id features
0 10 [0.25866490602493286, 0.3560594320297241, 0.15…
1 20 [0.12449632585048676, -0.29282501339912415, -0…
2 30 [0.9557555317878723, 0.6764761805534363, 0.114…
3 40 [0.3184879720211029, 0.6365472078323364, 0.596…
4 50 [0.45523127913475037, 0.34402626752853394, -0….

构建ids

ids = df["id"].values.astype(np.int64)
type(ids), ids.shape
(numpy.ndarray, (3706,))
ids.dtype
dtype('int64')
ids_size = ids.shape[0]
ids_size
3706

构建datas

import json
import numpy as np
datas = []
for x in df["features"]:
 datas.append(json.loads(x))
datas = np.array(datas).astype(np.float32)
datas.dtype
dtype('float32')
datas.shape
(3706, 10)
datas[0]
array([ 0.2586649 , 0.35605943, 0.15589039, -0.7067125 , -0.07414215,
 -0.62500805, -0.0573845 , 0.4533663 , 0.26074877, -0.60799956],
 dtype=float32)
# 维度
dimension = datas.shape[1]
dimension
10

2. 建立索引

import faiss
index = faiss.IndexFlatL2(dimension)
index2 = faiss.IndexIDMap(index)
ids.dtype
dtype('int64')
index2.add_with_ids(datas, ids)
index.ntotal
3706

4. 搜索近邻ID列表

df_user = pd.read_csv("./datas/movielens_sparkals_user_embedding.csv")
df_user.head()
id features

id features
0 10 [0.5974288582801819, 0.17486965656280518, 0.04…
1 20 [1.3099910020828247, 0.5037978291511536, 0.260…
2 30 [-1.1886241436004639, -0.13511677086353302, 0….
3 40 [1.0809299945831299, 1.0048035383224487, 0.986…
4 50 [0.42388680577278137, 0.5294889807701111, -0.6…
user_embedding = np.array(json.loads(df_user[df_user["id"] == 10]["features"].iloc[0]))
user_embedding = np.expand_dims(user_embedding, axis=0).astype(np.float32)
user_embedding
array([[ 0.59742886, 0.17486966, 0.04345559, -1.3193961 , 0.5313592 ,
 -0.6052168 , -0.19088413, 1.5307966 , 0.09310367, -2.7573566 ]],
 dtype=float32)
user_embedding.shape
(1, 10)
user_embedding.dtype
dtype('float32')
topk = 30
D, I = index.search(user_embedding, topk) # actual search
I.shape
(1, 30)
I
array([[3380, 2900, 1953, 121, 3285, 999, 617, 747, 2351, 601, 2347,
 42, 2383, 538, 1774, 980, 2165, 3049, 2664, 367, 3289, 2866,
 2452, 547, 1072, 2055, 3660, 3343, 3390, 3590]])

5. 根据电影ID取出电影信息

target_ids = pd.Series(I[0], name="MovieID")
target_ids.head()
0 3380
1 2900
2 1953
3 121
4 3285
Name: MovieID, dtype: int64
df_movie = pd.read_csv("./datas/ml-1m/movies.dat",
  sep="::", header=None, engine="python",
  names = "MovieID::Title::Genres".split("::"))
df_movie.head()

MovieID Title Genres
0 1 Toy Story (1995) Animation|Children's|Comedy
1 2 Jumanji (1995) Adventure|Children's|Fantasy
2 3 Grumpier Old Men (1995) Comedy|Romance
3 4 Waiting to Exhale (1995) Comedy|Drama
4 5 Father of the Bride Part II (1995) Comedy
df_result = pd.merge(target_ids, df_movie)
df_result.head()

MovieID Title Genres
0 3380 Railroaded! (1947) Film-Noir
1 2900 Monkey Shines (1988) Horror|Sci-Fi
2 1953 French Connection, The (1971) Action|Crime|Drama|Thriller
3 121 Boys of St. Vincent, The (1993) Drama
4 3285 Beach, The (2000) Adventure|Drama

总结

到此这篇关于Python利用Faiss库实现ANN近邻搜索的文章就介绍到这了,更多相关Python用Faiss库ANN近邻搜索内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
高性能web服务器框架Tornado简单实现restful接口及开发实例
Jul 16 Python
python subprocess 杀掉全部派生的子进程方法
Jan 16 Python
python编程实现希尔排序
Apr 13 Python
python 输出上个月的月末日期实例
Apr 11 Python
python实现彩色图转换成灰度图
Jan 15 Python
Python 元组操作总结
Sep 18 Python
Python jieba库用法及实例解析
Nov 04 Python
使用python批量转换文件编码为UTF-8的实现
Apr 03 Python
Python常驻任务实现接收外界参数代码解析
Jul 21 Python
Python接收手机短信的代码整理
Aug 02 Python
详解python方法之绑定方法与非绑定方法
Aug 17 Python
python中zip()函数遍历多个列表方法
Feb 18 Python
Python pexpect模块及shell脚本except原理解析
Aug 03 #Python
python爬虫使用正则爬取网站的实现
Aug 03 #Python
python获取整个网页源码的方法
Aug 03 #Python
flask开启多线程的具体方法
Aug 02 #Python
基于opencv实现简单画板功能
Aug 02 #Python
django下创建多个app并设置urls方法
Aug 02 #Python
Django如何在不停机的情况下创建索引
Aug 02 #Python
You might like
高分R级DC动画剧《哈莉·奎茵》第二季正式预告首发
2020/04/09 欧美动漫
MySQL中create table语句的基本语法是
2007/01/15 PHP
php实现用于删除整个目录的递归函数
2015/03/16 PHP
PHP上传文件及图片到七牛的方法
2018/07/25 PHP
可以文本显示的公告栏的js代码
2007/03/11 Javascript
理解Javascript_08_函数对象
2010/10/15 Javascript
Js表格万条数据瞬间加载实现代码
2014/02/20 Javascript
ext combobox动态加载数据库数据(附前后台)
2014/06/17 Javascript
javascript正则表达式之search()用法实例
2015/01/19 Javascript
vue.js指令v-model实现方法
2016/12/05 Javascript
详解闭包解决jQuery中AJAX的外部变量问题
2017/02/22 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
vue项目打包部署_nginx代理访问方法详解
2018/09/20 Javascript
JavaScript作用域链实例详解
2019/01/21 Javascript
微信小程序自定义弹窗实现详解(可通用)
2019/07/04 Javascript
Python中的高级数据结构详解
2015/03/27 Python
详解Python中的静态方法与类成员方法
2017/02/28 Python
Python实现一个Git日志统计分析的小工具
2017/12/14 Python
Django Rest framework之权限的实现示例
2018/12/17 Python
Python3标准库总结
2019/02/19 Python
Python玩转加密的技巧【推荐】
2019/05/13 Python
django写用户登录判定并跳转制定页面的实例
2019/08/21 Python
pytorch 实现张量tensor,图片,CPU,GPU,数组等的转换
2020/01/13 Python
Python中私有属性的定义方式
2020/03/05 Python
python opencv 图像边框(填充)添加及图像混合的实现方法(末尾实现类似幻灯片渐变的效果)
2020/03/09 Python
python中get和post有什么区别
2020/06/19 Python
Virtualenv 搭建 Py项目运行环境的教程详解
2020/06/22 Python
python中查看.db文件中表格的名字及表格中的字段操作
2020/07/07 Python
经验丰富程序员才知道的8种高级Python技巧
2020/07/27 Python
英国最受信任的在线眼镜商之一:Fashion Eyewear
2019/10/31 全球购物
农村党支部先进事迹
2014/01/14 职场文书
机关搬迁方案
2014/05/18 职场文书
旅游与酒店管理专业求职信
2014/07/21 职场文书
民主生活会汇报材料
2014/12/15 职场文书
个人总结与自我评价2015
2015/03/11 职场文书
超市收银员岗位职责
2015/04/07 职场文书