DeepMatch :用于推荐广告的深度召回匹配算法库
今天介紹一下我們的一個開源項目DeepMatch,提供了若干主流的深度召回匹配算法的實現,并支持快速導出用戶和物品向量進行ANN檢索。非常適合同學們進行快速實驗和學習,解放算法工程師的雙手!
目前支持的算法下面分別從開發背景,安裝和使用方法以及貢獻和交流幾個方面介紹一下這個項目。文末提供了交流群感興趣的同學不要錯過,歡迎找bug和提意見~
背景
眾所周知,目前主流的推薦廣告算法架構體系是一個召回排序的兩階段流程,召回模塊從海量的候選池中召回多樣的相關的候選物料,排序模塊根據用戶偏好和上下文信息給出用戶最可能感興趣的一個有序列表。
隨著深度學習技術的普及,越來越多的深度學習算法被應用到了工業界中。筆者自去年畢業進入企業后,有幸參與了某新業務的推薦系統搭建以及用戶體驗和業務指標的優化當中,其中在召回部分也進行過一些基于向量召回的探索并取得了一些收益。
之前在讀研期間出于個人興趣開發過一個基于深度學習的點擊率預測算法庫DeepCTR(https://github.com/shenweichen/DeepCTR),隨著時間的迭代得到了一些同學的支持和認可,自己也親身使用到了里面的算法應用到了自己的業務當中并取得了顯著的收益。
相比于排序中各種點擊率預估模型,自己對于召回模塊的了解還有很多欠缺,借著這個機會,抱著學習的心態,和幾位熱心的優秀小伙伴一起做了DeepMatch這個項目,希望它能夠幫助到大家!
下面簡單介紹一下如何安裝和使用
安裝和使用
通過pip安裝
pip install -U deepmatch
文檔
https://deepmatch.readthedocs.io/en/latest/
使用例子
這篇文章是基于v0.1.0寫的,如果以后版本升級了發現運行不了,可以選擇回退到v0.1.0版本,或者去git倉庫里examples目錄下運行最新的代碼。(https://github.com/shenweichen/DeepMatch)
下面以大家比較熟悉的YoutubeDNN為例子,給大家介紹如何使用deepmatch進行召回模型的訓練,用戶和物品向量的導出,以及使用faiss進行近似最近鄰搜索。其他算法的接口和任務流程基本一樣~
整段代碼不到100行,可以是非常的方便進行學習和使用了~
完整代碼見鏈接 https://github.com/shenweichen/DeepMatch/blob/master/examples/run_youtubednn_sampledsoftmax.py
import?pandas?as?pd from?deepctr.inputs?import?SparseFeat,?VarLenSparseFeat from?preprocess?import?gen_data_set,?gen_model_input from?sklearn.preprocessing?import?LabelEncoder from?tensorflow.python.keras?import?backend?as?K from?tensorflow.python.keras.models?import?Modelfrom?deepmatch.models?import?* from?deepmatch.utils?import?sampledsoftmaxloss#?以movielens數據為例,取200條樣例數據進行流程演示data?=?pd.read_csvdata?=?pd.read_csv("./movielens_sample.txt") sparse_features?=?["movie_id",?"user_id","gender",?"age",?"occupation",?"zip",?] SEQ_LEN?=?50 negsample?=?0#?1.?首先對于數據中的特征進行ID化編碼,然后使用?`gen_date_set`?and?`gen_model_input`來生成帶有用戶歷史行為序列的特征數據features?=?['user_id',?'movie_id',?'gender',?'age',?'occupation',?'zip'] feature_max_idx?=?{} for?feature?in?features:lbe?=?LabelEncoder()data[feature]?=?lbe.fit_transform(data[feature])?+?1feature_max_idx[feature]?=?data[feature].max()?+?1user_profile?=?data[["user_id",?"gender",?"age",?"occupation",?"zip"]].drop_duplicates('user_id')item_profile?=?data[["movie_id"]].drop_duplicates('movie_id')user_profile.set_index("user_id",?inplace=True)user_item_list?=?data.groupby("user_id")['movie_id'].apply(list)train_set,?test_set?=?gen_data_set(data,?negsample)train_model_input,?train_label?=?gen_model_input(train_set,?user_profile,?SEQ_LEN) test_model_input,?test_label?=?gen_model_input(test_set,?user_profile,?SEQ_LEN)#?2.?配置一下模型定義需要的特征列,主要是特征名和embedding詞表的大小embedding_dim?=?16user_feature_columns?=?[SparseFeat('user_id',?feature_max_idx['user_id'],?embedding_dim),SparseFeat("gender",?feature_max_idx['gender'],?embedding_dim),SparseFeat("age",?feature_max_idx['age'],?embedding_dim),SparseFeat("occupation",?feature_max_idx['occupation'],?embedding_dim),SparseFeat("zip",?feature_max_idx['zip'],?embedding_dim),VarLenSparseFeat(SparseFeat('hist_movie_id',?feature_max_idx['movie_id'],?embedding_dim,embedding_name="movie_id"),?SEQ_LEN,?'mean',?'hist_len'),]item_feature_columns?=?[SparseFeat('movie_id',?feature_max_idx['movie_id'],?embedding_dim)]# 3. 定義一個YoutubeDNN模型,分別傳入用戶側特征列表`user_feature_columns`和物品側特征列表`item_feature_columns`。然后配置優化器和損失函數,開始進行訓練。K.set_learning_phase(True)model?=?YoutubeDNN(user_feature_columns,?item_feature_columns,?num_sampled=5,?user_dnn_hidden_units=(64,?16)) #?model?=?MIND(user_feature_columns,item_feature_columns,dynamic_k=True,p=1,k_max=2,num_sampled=5,user_dnn_hidden_units=(64,16),init_std=0.001)model.compile(optimizer="adagrad",?loss=sampledsoftmaxloss)??#?"binary_crossentropy")history?=?model.fit(train_model_input,?train_label,??#?train_label,batch_size=256,?epochs=1,?verbose=1,?validation_split=0.0,?)# 4. 訓練完整后,由于在實際使用時,我們需要根據當前的用戶特征實時產生用戶側向量,并對物品側向量構建索引進行近似最近鄰查找。這里由于是離線模擬,所以我們導出所有待測試用戶的表示向量,和所有物品的表示向量。test_user_model_input?=?test_model_input all_item_model_input?=?{"movie_id":?item_profile['movie_id'].values,?"movie_idx":?item_profile['movie_id'].values}#?以下兩行是deepmatch中的通用使用方法,分別獲得用戶向量模型和物品向量模型 user_embedding_model?=?Model(inputs=model.user_input,?outputs=model.user_embedding) item_embedding_model?=?Model(inputs=model.item_input,?outputs=model.item_embedding) #?輸入對應的數據拿到對應的向量 user_embs?=?user_embedding_model.predict(test_user_model_input,?batch_size=2?**?12) #?user_embs?=?user_embs[:,?i,?:]??i?in?[0,k_max)?if?MIND item_embs?=?item_embedding_model.predict(all_item_model_input,?batch_size=2?**?12)print(user_embs.shape) print(item_embs.shape)#?5.?[可選的]如果有安裝faiss庫的同學,可以體驗以下將上一步導出的物品向量構建索引,然后用用戶向量來進行ANN查找并評估效果test_true_label?=?{line[0]:[line[2]]?for?line?in?test_set} import?numpy?as?np import?faiss from?tqdm?import?tqdm from?deepmatch.utils?import?recall_N index?=?faiss.IndexFlatIP(embedding_dim) #?faiss.normalize_L2(item_embs) index.add(item_embs) #?faiss.normalize_L2(user_embs) D,?I?=?index.search(user_embs,?50) s?=?[] hit?=?0 for?i,?uid?in?tqdm(enumerate(test_user_model_input['user_id'])):try:pred?=?[item_profile['movie_id'].values[x]?for?x?in?I[i]]filter_item?=?Nonerecall_score?=?recall_N(test_true_label[uid],?pred,?N=50)s.append(recall_score)if?test_true_label[uid]?in?pred:hit?+=?1except:print(i) print("recall",?np.mean(s)) print("hr",?hit?/?len(test_user_model_input['user_id']))貢獻者
一個人的力量有限,感謝一起參與開發的小伙伴們~~他們分別是:
王喆 京東廣告算法工程師
blog: https://zhuanlan.zhihu.com/c_1218845039004119040
github: https://github.com/wangzhegeek
蔡慶亮 字節跳動高級廣告算法工程師
blog: https://blog.csdn.net/cqlboat
github:https://github.com/LeoCai
楊婕妤,浙江大學研二找工作????,瘋狂求各大公司收留
mail: yangjieyu@zju.edu.cn
github:https://github.com/Eleanoryuyuyu
最后
這個項目其實從立項到第一次發布拖了比較長的時間,一方面是大家主要還是工作的同學居多,可能更多的是利用周末的時間進行開發,響應時間會比較長。另一方面,我在開始的時候其實也不知道要做什么樣子,也是摸著石頭過河,各種接口中途改了很多次,核心還是希望用戶在使用的時候不會感到困惑也能夠方便大家的理解。
還是希望大家多多支持,可以給我們來個star! https://github.com/shenweichen/DeepMatch
【點擊閱讀原文直達】 另外悄悄透露下:我們還有若干算法已經開發完成,等待測試好了就會公布!
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習在線手冊深度學習在線手冊AI基礎下載(pdf更新到25集)本站qq群1003271085,加入微信群請回復“加群”獲取一折本站知識星球優惠券,請回復“知識星球”喜歡文章,點個在看
總結
以上是生活随笔為你收集整理的DeepMatch :用于推荐广告的深度召回匹配算法库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于逻辑回归,面试官们都怎么问
- 下一篇: 特殊时期之下的 AI 成功“逆行”,技术