时间:2021-05-22
Embedding的近邻搜索是当前图推荐系统非常重要的一种召回方式,通过item2vec、矩阵分解、双塔DNN等方式都能够产出训练好的user embedding、item embedding,对于embedding的使用非常的灵活:
然而有一个工程问题,一旦user embedding、item embedding数据量达到一定的程度,对他们的近邻搜索将会变得非常慢,如果离线阶段提前搜索好在高速缓存比如redis存储好结果当然没问题,但是这种方式很不实时,如果能在线阶段上线几十MS的搜索当然效果最好。
Faiss是Facebook AI团队开源的针对聚类和相似性搜索库,为稠密向量提供高效相似度搜索和聚类,支持十亿级别向量的搜索,是目前最为成熟的近似近邻搜索库。
接下来通过jupyter notebook的代码,给大家演示下使用faiss的简单流程,内容包括:
对于已经训练好的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 pdimport numpy as npdf = 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.dtypedtype('int64')ids_size = ids.shape[0]ids_size3706构建datas
import jsonimport numpy as npdatas = []for x in df["features"]: datas.append(json.loads(x))datas = np.array(datas).astype(np.float32)datas.dtypedtype('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]dimension102. 建立索引
import faissindex = faiss.IndexFlatL2(dimension)index2 = faiss.IndexIDMap(index)ids.dtypedtype('int64')index2.add_with_ids(datas, ids)index.ntotal37064. 搜索近邻ID列表
df_user = pd.read_csv("./datas/movielens_sparkals_user_embedding.csv")df_user.head()id featuresid 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_embeddingarray([[ 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.dtypedtype('float32')topk = 30D, I = index.search(user_embedding, topk) # actual searchI.shape(1, 30)Iarray([[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 33801 29002 19533 1214 3285Name: MovieID, dtype: int64df_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近邻搜索内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例讲述了Python栈的实现方法。分享给大家供大家参考,具体如下:Python实现栈栈的数组实现:利用python列表方法代码如下:#列表实现栈,利用py
前言在论坛上看到了用Python登录微信并实现自动签到,才了解到一个新的Python库:itchat利用Python微信库itchat,可以实现自动回复等多种功
做了个Python的小练习,网上有人是利用PIL中的Image来实现的,觉得Opencv库挺方便的,于是利用Opencv库来实现了一下,代码如下:#-*-cod
在Python探索之SocketServer详解中我们介绍了Python标准库中的SocketServer模块,了解了要实现网络通信服务,就要构建一个服务器类和
python将数据换为txt的方法有很多,可以用xlrd库实现。本人比较懒,不想按太多用的少的插件,利用已有库pandas将excel文件转换为txt文件。直接