深度学习在美团点评推荐平台排序中的应用 widedeep推荐系统模型--学习笔记
gbdt+lr的模型之前是知道怎么搞的,dnn+lr的模型也是知道的,但是都沒有試驗(yàn)過
?
深度學(xué)習(xí)在美團(tuán)點(diǎn)評推薦平臺排序中的運(yùn)用
原創(chuàng)?2017-07-28?潘暉?美團(tuán)點(diǎn)評技術(shù)團(tuán)隊(duì)
美團(tuán)點(diǎn)評作為國內(nèi)最大的生活服務(wù)平臺,業(yè)務(wù)種類涉及食、住、行、玩、樂等領(lǐng)域,致力于讓大家吃得更好,活得更好,有數(shù)億用戶以及豐富的用戶行為。隨著業(yè)務(wù)的飛速發(fā)展,美團(tuán)點(diǎn)評的用戶和商戶數(shù)在快速增長。在這樣的背景下,通過對推薦算法的優(yōu)化,可以更好的給用戶提供感興趣的內(nèi)容,幫用戶更快速方便的找到所求。我們目標(biāo)是根據(jù)用戶的興趣及行為,向用戶推薦感興趣的內(nèi)容,打造一個(gè)高精準(zhǔn)性、高豐富度且讓用戶感到欣喜的推薦系統(tǒng)。為了達(dá)到這個(gè)目的,我們在不停的嘗試將新的算法、新的技術(shù)進(jìn)引入到現(xiàn)有的框架中。
?
1. 引言
?
自2012年ImageNet大賽技驚四座后,深度學(xué)習(xí)已經(jīng)成為近年來機(jī)器學(xué)習(xí)和人工智能領(lǐng)域中關(guān)注度最高的技術(shù)。在深度學(xué)習(xí)出現(xiàn)之前,人們借助SIFT、HOG等算法提取具有良好區(qū)分性的特征,再結(jié)合SVM等機(jī)器學(xué)習(xí)算法進(jìn)行圖像識別。然而SIFT這類算法提取的特征是有局限性的,導(dǎo)致當(dāng)時(shí)比賽的最好結(jié)果的錯(cuò)誤率也在26%以上。卷積神經(jīng)網(wǎng)絡(luò)(CNN)的首次亮相就將錯(cuò)誤率一下由26%降低到15%,同年微軟團(tuán)隊(duì)發(fā)布的論文中顯示,通過深度學(xué)習(xí)可以將ImageNet 2012資料集的錯(cuò)誤率降到4.94%。
?
隨后的幾年,深度學(xué)習(xí)在多個(gè)應(yīng)用領(lǐng)域都取得了令人矚目的進(jìn)展,如語音識別、圖像識別、自然語言處理等。鑒于深度學(xué)習(xí)的潛力,各大互聯(lián)網(wǎng)公司也紛紛投入資源開展科研與運(yùn)用。因?yàn)槿藗円庾R到,在大數(shù)據(jù)時(shí)代,更加復(fù)雜且強(qiáng)大的深度模型,能深刻揭示海量數(shù)據(jù)里所承載的復(fù)雜而豐富的信息,并對未來或未知事件做更精準(zhǔn)的預(yù)測。
?
美團(tuán)點(diǎn)評作為一直致力于站在科技前沿的互聯(lián)網(wǎng)公司,也在深度學(xué)習(xí)方面進(jìn)行了一些探索,其中在自然語言處理領(lǐng)域,我們將深度學(xué)習(xí)技術(shù)應(yīng)用于文本分析、語義匹配、搜索引擎的排序模型等;在計(jì)算機(jī)視覺領(lǐng)域,我們將其應(yīng)用于文字識別、圖像分類、圖像質(zhì)量排序等。本文就是筆者所在團(tuán)隊(duì),在借鑒了Google在2016年提出的Wide & Deep Learning 的思想上,基于自身業(yè)務(wù)的一些特點(diǎn),在大眾點(diǎn)評推薦系統(tǒng)上做出的一些思考和取得的實(shí)踐經(jīng)驗(yàn)。
?
2. 點(diǎn)評推薦系統(tǒng)介紹
?
與大部分的推薦系統(tǒng)不同,美團(tuán)點(diǎn)評的場景由于自身業(yè)務(wù)的多樣性,使得我們很難準(zhǔn)確捕獲用戶的興趣點(diǎn)或用戶的實(shí)時(shí)意圖。而且我們推薦的場景也會隨著用戶興趣、地點(diǎn)、環(huán)境、時(shí)間等變化而變化。點(diǎn)評推薦系統(tǒng)主要面臨以下幾點(diǎn)挑戰(zhàn):
?
-
業(yè)務(wù)形態(tài)多樣性:除了推薦商戶外,我們還根據(jù)不同的場景,進(jìn)行實(shí)時(shí)判斷,從而推出不同形態(tài)的業(yè)務(wù),如團(tuán)單、酒店、景點(diǎn)、霸王餐等。
-
用戶消費(fèi)場景多樣性:用戶可以選擇在家消費(fèi):外賣,到店消費(fèi):團(tuán)單、閃惠,或者差旅消費(fèi):預(yù)定酒店等。
?
針對上述問題,我們定制了一套完善的推薦系統(tǒng)框架,包括基于機(jī)器學(xué)習(xí)的多選品召回與排序策略,以及從海量大數(shù)據(jù)的離線計(jì)算到高并發(fā)在線服務(wù)的推薦引擎。推薦系統(tǒng)的策略主要分為召回和排序兩個(gè)過程,召回主要負(fù)責(zé)生成推薦的候選集,排序負(fù)責(zé)將多個(gè)算法策略的結(jié)果進(jìn)行個(gè)性化排序。
?
召回層:我們通過用戶行為、場景等進(jìn)行實(shí)時(shí)判斷,通過多個(gè)召回策略召回不同候選集。再對召回的候選集進(jìn)行融合。候選集融合和過濾層有兩個(gè)功能,一是提高推薦策略的覆蓋度和精度;另外還要承擔(dān)一定的過濾職責(zé),從產(chǎn)品、運(yùn)營的角度制定一些人工規(guī)則,過濾掉不符合條件的Item。下面是一些我們常用到的召回策略:
?
-
User-Based 協(xié)同過濾:找出與當(dāng)前User X最相似的N個(gè)User,并根據(jù)N個(gè)User對某Item的打分估計(jì)X對該Item的打分。在相似度算法方面,我們采用了Jaccard Similarity:
-
Model-Based 協(xié)同過濾:用一組隱含因子來聯(lián)系用戶和商品。其中每個(gè)用戶、每個(gè)商品都用一個(gè)向量來表示,用戶u對商品i的評價(jià)通過計(jì)算這兩個(gè)向量的內(nèi)積得到。算法的關(guān)鍵在于根據(jù)已知的用戶對商品的行為數(shù)據(jù)來估計(jì)用戶和商品的隱因子向量。
-
Item-Based 協(xié)同過濾:我們先用word2vec對每個(gè)Item取其隱含空間的向量,然后用Cosine Similarity計(jì)算用戶u用過的每一個(gè)Item與未用過Item?i之間的相似性。最后對Top N的結(jié)果進(jìn)行召回。
-
Query-Based:是根據(jù)Query中包含的實(shí)時(shí)信息(如地理位置信息、WiFi到店、關(guān)鍵詞搜索、導(dǎo)航搜索等)對用戶的意圖進(jìn)行抽象,從而觸發(fā)的策略。
-
Location-Based:移動設(shè)備的位置是經(jīng)常發(fā)生變化的,不同的地理位置反映了不同的用戶場景,可以在具體的業(yè)務(wù)中充分利用。在推薦的候選集召回中,我們也會根據(jù)用戶的實(shí)時(shí)地理位置、工作地、居住地等地理位置觸發(fā)相應(yīng)的策略。
?
排序?qū)?#xff1a;每類召回策略都會召回一定的結(jié)果,這些結(jié)果去重后需要統(tǒng)一做排序。點(diǎn)評推薦排序的框架大致可以分為三塊:
?
-
離線計(jì)算層:離線計(jì)算層主要包含了算法集合、算法引擎,負(fù)責(zé)數(shù)據(jù)的整合、特征的提取、模型的訓(xùn)練、以及線下的評估。
-
近線實(shí)時(shí)數(shù)據(jù)流:主要是對不同的用戶流實(shí)施訂閱、行為預(yù)測,并利用各種數(shù)據(jù)處理工具對原始日志進(jìn)行清洗,處理成格式化的數(shù)據(jù),落地到不同類型的存儲系統(tǒng)中,供下游的算法和模型使用。
-
在線實(shí)時(shí)打分:根據(jù)用戶所處的場景,提取出相對應(yīng)的特征,并利用多種機(jī)器學(xué)習(xí)算法,對多策略召回的結(jié)果進(jìn)行融合和打分重排。
?
具體的推薦流程圖如下:
?
?
從整體框架的角度看,當(dāng)用戶每次請求時(shí),系統(tǒng)就會將當(dāng)前請求的數(shù)據(jù)寫入到日志當(dāng)中,利用各種數(shù)據(jù)處理工具對原始日志進(jìn)行清洗,格式化,落地到不同類型的存儲系統(tǒng)中。在訓(xùn)練時(shí),我們利用特征工程,從處理過后的數(shù)據(jù)集中選出訓(xùn)練、測試樣本集,并借此進(jìn)行線下模型的訓(xùn)練和預(yù)估。我們采用多種機(jī)器學(xué)習(xí)算法,并通過線下AUC、NDCG、Precision等指標(biāo)來評估他們的表現(xiàn)。線下模型經(jīng)過訓(xùn)練和評估后,如果在測試集有比較明顯的提高,會將其上線進(jìn)行線上AB測試。同時(shí),我們也有多種維度的報(bào)表對模型進(jìn)行數(shù)據(jù)上的支持。
?
3. 深度學(xué)習(xí)在點(diǎn)評推薦排序系統(tǒng)中應(yīng)用
?
對于不同召回策略所產(chǎn)生的候選集,如果只是根據(jù)算法的歷史效果決定算法產(chǎn)生的Item的位置顯得有些簡單粗暴,同時(shí),在每個(gè)算法的內(nèi)部,不同Item的順序也只是簡單的由一個(gè)或者幾個(gè)因素決定,這些排序的方法只能用于第一步的初選過程,最終的排序結(jié)果需要借助機(jī)器學(xué)習(xí)的方法,使用相關(guān)的排序模型,綜合多方面的因素來確定。
?
3.1 現(xiàn)有排序框架介紹
?
?
到目前為止,點(diǎn)評推薦排序系統(tǒng)嘗試了多種線性、非線性、混合模型等機(jī)器學(xué)習(xí)方法,如邏輯回歸、GBDT、GBDT+LR等。通過線上實(shí)驗(yàn)發(fā)現(xiàn),相較于線性模型,傳統(tǒng)的非線性模型如GBDT,并不一定能在線上AB測試環(huán)節(jié)對CTR預(yù)估有比較明顯的提高。而線性模型如邏輯回歸,因?yàn)樽陨矸蔷€性表現(xiàn)能力比較弱,無法對真實(shí)生活中的非線性場景進(jìn)行區(qū)分,會經(jīng)常對歷史數(shù)據(jù)中出現(xiàn)過的數(shù)據(jù)過度記憶。下圖就是線性模型根據(jù)記憶將一些歷史點(diǎn)擊過的單子排在前面:
從圖中我們可以看到,系統(tǒng)在非常靠前的位置推薦了一些遠(yuǎn)距離的商戶,因?yàn)檫@些商戶曾經(jīng)被用戶點(diǎn)過,其本身點(diǎn)擊率較高,那么就很容易被系統(tǒng)再次推薦出來。但這種推薦并沒有結(jié)合當(dāng)前場景給用戶推薦出一些有新穎性的Item。為了解決這個(gè)問題,就需要考慮更多、更復(fù)雜的特征,比如組合特征來替代簡單的“距離”特征。怎么去定義、組合特征,這個(gè)過程成本很高,并且更多地依賴于人工經(jīng)驗(yàn)。
?
而深度神經(jīng)網(wǎng)絡(luò),可以通過低維密集的特征,學(xué)習(xí)到以前沒出現(xiàn)過的一些Item和特征之間的關(guān)系,并且相比于線性模型大幅降低了對于特征工程的需求,從而吸引我們進(jìn)行探索研究。
?
在實(shí)際的運(yùn)用當(dāng)中,我們根據(jù)Google在2016年提出的Wide & Deep Learning模型,并結(jié)合自身業(yè)務(wù)的需求與特點(diǎn),將線性模型組件和深度神經(jīng)網(wǎng)絡(luò)進(jìn)行融合,形成了在一個(gè)模型中實(shí)現(xiàn)記憶和泛化的寬深度學(xué)習(xí)框架。在接下來的章節(jié)中,將會討論如何進(jìn)行樣本篩選、特征處理、深度學(xué)習(xí)算法實(shí)現(xiàn)等。
?
3.2 樣本的篩選
?
數(shù)據(jù)及特征,是整個(gè)機(jī)器學(xué)習(xí)中最重要的兩個(gè)環(huán)節(jié),因?yàn)槠浔旧砭蜎Q定了整個(gè)模型的上限。點(diǎn)評推薦由于其自身多業(yè)務(wù)(包含外賣、商戶、團(tuán)購、酒旅等)、多場景(用戶到店、用戶在家、異地請求等)的特色,導(dǎo)致我們的樣本集相比于其他產(chǎn)品更多元化。我們的目標(biāo)是預(yù)測用戶的點(diǎn)擊行為。有點(diǎn)擊的為正樣本,無點(diǎn)擊的為負(fù)樣本,同時(shí),在訓(xùn)練時(shí)對于購買過的樣本進(jìn)行一定程度的加權(quán)。而且,為了防止過擬合/欠擬合,我們將正負(fù)樣本的比例控制在10%。最后,我們還要對訓(xùn)練樣本進(jìn)行清洗,去除掉Noise樣本(特征值近似或相同的情況下,分別對應(yīng)正負(fù)兩種樣本)。
?
同時(shí),推薦業(yè)務(wù)作為整個(gè)App首頁核心模塊,對于新穎性以及多樣性的需求是很高的。在點(diǎn)評推薦系統(tǒng)的實(shí)現(xiàn)中,首先要確定應(yīng)用場景的數(shù)據(jù),美團(tuán)點(diǎn)評的數(shù)據(jù)可以分為以下幾類:
?
-
用戶畫像:性別、常駐地、價(jià)格偏好、Item偏好等。
-
Item畫像:包含了商戶、外賣、團(tuán)單等多種Item。其中商戶特征包括:商戶價(jià)格、商戶好評數(shù)、商戶地理位置等。外賣特征包括:外賣平均價(jià)格、外賣配送時(shí)間、外賣銷量等。團(tuán)單特征包括:團(tuán)單適用人數(shù)、團(tuán)單訪購率等。
-
場景畫像:用戶當(dāng)前所在地、時(shí)間、定位附近商圈、基于用戶的上下文場景信息等。
?
3.3 深度學(xué)習(xí)中的特征處理
?
機(jī)器學(xué)習(xí)的另一個(gè)核心領(lǐng)域就是特征工程,包括數(shù)據(jù)預(yù)處理,特征提取,特征選擇等。
?
特征提取:從原始數(shù)據(jù)出發(fā)構(gòu)造新的特征的過程。方法包括計(jì)算各種簡單統(tǒng)計(jì)量、主成分分析、無監(jiān)督聚類,在構(gòu)造方法確定后,可以將其變成一個(gè)自動化的數(shù)據(jù)處理流程,但是特征構(gòu)造過程的核心還是手動的。
特征選擇:從眾多特征中挑選出少許有用特征。與學(xué)習(xí)目標(biāo)不相關(guān)的特征和冗余特征需要被剔除,如果計(jì)算資源不足或者對模型的復(fù)雜性有限制的話,還需要選擇丟棄一些不重要的特征。特征選擇方法常用的有以下幾種:
?
?
特征選擇開銷大、特征構(gòu)造成本高,在推薦業(yè)務(wù)開展的初期,我們對于這方面的感覺還不強(qiáng)烈。但是隨著業(yè)務(wù)的發(fā)展,對點(diǎn)擊率預(yù)估模型的要求越來越高,特征工程的巨大投入對于效果的提升已經(jīng)不能滿足我們需求,于是我們想尋求一種新的解決辦法。
?
深度學(xué)習(xí)能自動對輸入的低階特征進(jìn)行組合、變換,得到高階特征的特性,也促使我們轉(zhuǎn)向深度學(xué)習(xí)進(jìn)行探索。深度學(xué)習(xí)“自動提取特征”的優(yōu)點(diǎn),在不同的領(lǐng)域有著不同的表現(xiàn)。例如對于圖像處理,像素點(diǎn)可以作為低階特征輸入,通過卷積層自動得到的高階特征有比較好的效果。在自然語言處理方面,有些語義并不來自數(shù)據(jù),而是來自人們的先驗(yàn)知識,利用先驗(yàn)知識構(gòu)造的特征是很有幫助的。
?
因此,我們希望借助于深度學(xué)習(xí)來節(jié)約特征工程中的巨大投入,更多地讓點(diǎn)擊率預(yù)估模型和各輔助模型自動完成特征構(gòu)造和特征選擇的工作,并始終和業(yè)務(wù)目標(biāo)保持一致。下面是一些我們在深度學(xué)習(xí)中用到的特征處理方式:
?
3.3.1 組合特征
?
對于特征的處理,我們沿用了目前業(yè)內(nèi)通用的辦法,比如歸一化、標(biāo)準(zhǔn)化、離散化等。但值得一提的是,我們將很多組合特征引入到模型訓(xùn)練中。因?yàn)椴煌卣髦g的組合是非常有效的,并有很好的可解釋性,比如我們將"商戶是否在用戶常駐地"、"用戶是否在常駐地"以及"商戶與用戶當(dāng)前距離"進(jìn)行組合,再將數(shù)據(jù)進(jìn)行離散化,通過組合特征,我們可以很好的抓住離散特征中的內(nèi)在聯(lián)系,為線性模型增加更多的非線性表述。組合特征的定義為:
?
?
3.3.2 歸一化
?
歸一化是依照特征矩陣的行處理數(shù)據(jù),其目的在于樣本向量在點(diǎn)乘運(yùn)算或其他核函數(shù)計(jì)算相似性時(shí),擁有統(tǒng)一的標(biāo)準(zhǔn),也就是說都轉(zhuǎn)化為“單位向量”。在實(shí)際工程中,我們運(yùn)用了兩種歸一化方法:
?
Min-Max:
?
Min是這個(gè)特征的最小值,Max是這個(gè)特征的最大值。
?
Cumulative Distribution Function(CDF):CDF也稱為累積分布函數(shù),數(shù)學(xué)意義是表示隨機(jī)變量小于或等于其某一個(gè)取值x的概率。其公式為:
?
在我們線下實(shí)驗(yàn)中,連續(xù)特征在經(jīng)過CDF的處理后,相比于Min-Max,CDF的線下AUC提高不足0.1%。我們猜想是因?yàn)橛行┻B續(xù)特征并不滿足在(0,1)上均勻分布的隨機(jī)函數(shù),CDF在這種情況下,不如Min-Max來的直觀有效,所以我們在線上采用了Min-Max方法。
?
3.3.3 快速聚合
?
為了讓模型更快的聚合,并且賦予網(wǎng)絡(luò)更好的表現(xiàn)形式,我們對原始的每一個(gè)連續(xù)特征設(shè)置了它的super-liner和sub-liner,即對于每個(gè)特征x,衍生出2個(gè)子特征:
?
?
實(shí)驗(yàn)結(jié)果表示,通過對每一個(gè)連續(xù)變量引入2個(gè)子特征,會提高線下AUC的表現(xiàn),但考慮到線上計(jì)算量的問題,并沒有在線上實(shí)驗(yàn)中添加這2個(gè)子特征。
?
3.4 優(yōu)化器(Optimizer)的選擇
?
在深度學(xué)習(xí)中,選擇合適的優(yōu)化器不僅會加速整個(gè)神經(jīng)網(wǎng)絡(luò)訓(xùn)練過程,并且會避免在訓(xùn)練的過程中困到鞍點(diǎn)。文中會結(jié)合自己的使用情況,對使用過的優(yōu)化器提出一些自己的理解。
?
3.4.1 Stochastic Gradient Descent (SGD)
?
SGD 是一種常見的優(yōu)化方法,即每次迭代計(jì)算Mini-Batch的梯度,然后對參數(shù)進(jìn)行更新。其公式為:
?
?
缺點(diǎn)是對于損失方程有比較嚴(yán)重的振蕩,并且容易收斂到局部最小值。
?
3.4.2 Momentum
?
為了克服SGD振蕩比較嚴(yán)重的問題,Momentum將物理中的動量概念引入到SGD當(dāng)中,通過積累之前的動量來替代梯度。即:
?
?
相較于SGD,Momentum就相當(dāng)于在從山坡上不停的向下走,當(dāng)沒有阻力的話,它的動量會越來越大,但是如果遇到了阻力,速度就會變小。也就是說,在訓(xùn)練的時(shí)候,在梯度方向不變的維度上,訓(xùn)練速度變快,梯度方向有所改變的維度上,更新速度變慢,這樣就可以加快收斂并減小振蕩。
?
3.4.3 Adagrad
?
相較于SGD,Adagrad相當(dāng)于對學(xué)習(xí)率多加了一個(gè)約束,即:
?
Adagrad的優(yōu)點(diǎn)是,在訓(xùn)練初期,由于gt較小,所以約束項(xiàng)能夠加速訓(xùn)練。而在后期,隨著gt的變大,會導(dǎo)致分母不斷變大,最終訓(xùn)練提前結(jié)束。
?
3.4.4 Adam
?
Adam是一個(gè)結(jié)合了Momentum與Adagrad的產(chǎn)物,它既考慮到了利用動量項(xiàng)來加速訓(xùn)練過程,又考慮到對于學(xué)習(xí)率的約束。利用梯度的一階矩估計(jì)和二階矩估計(jì)動態(tài)調(diào)整每個(gè)參數(shù)的學(xué)習(xí)率。Adam的優(yōu)點(diǎn)主要在于經(jīng)過偏置校正后,每一次迭代學(xué)習(xí)率都有個(gè)確定范圍,使得參數(shù)比較平穩(wěn)。其公式為:
?
?
其中:
?
?
小結(jié)
?
通過實(shí)踐證明,Adam結(jié)合了Adagrad善于處理稀疏梯度和Momentum善于處理非平穩(wěn)目標(biāo)的優(yōu)點(diǎn),相較于其他幾種優(yōu)化器效果更好。同時(shí),我們也注意到很多論文中都會引用SGD,Adagrad作為優(yōu)化函數(shù)。但相較于其他方法,在實(shí)踐中,SGD需要更多的訓(xùn)練時(shí)間以及可能會被困到鞍點(diǎn)的缺點(diǎn),都制約了它在很多真實(shí)數(shù)據(jù)上的表現(xiàn)。
?
3.5 損失函數(shù)的選擇
?
深度學(xué)習(xí)同樣有許多損失函數(shù)可供選擇,如平方差函數(shù)(Mean Squared Error),絕對平方差函數(shù)(Mean Absolute Error),交叉熵函數(shù)(Cross Entropy)等。而在理論與實(shí)踐中,我們發(fā)現(xiàn)Cross Entropy相比于在線性模型中表現(xiàn)比較好的平方差函數(shù)有著比較明顯的優(yōu)勢。其主要原因是在深度學(xué)習(xí)通過反向傳遞更新W和b的同時(shí),激活函數(shù)Sigmoid的導(dǎo)數(shù)在取大部分值時(shí)會落入左、右兩個(gè)飽和區(qū)間,造成參數(shù)的更新非常緩慢。具體的推導(dǎo)公式如下:
?
一般的MSE被定義為:
?
?
其中y是我們期望的輸出,a為神經(jīng)元的實(shí)際輸出a=σ(Wx+b)。由于深度學(xué)習(xí)反向傳遞的機(jī)制,權(quán)值W與偏移量b的修正公式被定義為:
?
?
因?yàn)镾igmoid函數(shù)的性質(zhì),導(dǎo)致σ′(z)在z取大部分值時(shí)會造成飽和現(xiàn)象。
?
Cross Entropy的公式為:
?
?
如果有多個(gè)樣本,則整個(gè)樣本集的平均交叉熵為:
?
?
其中n表示樣本編號,i表示類別編號。 如果用于Logistic分類,則上式可以簡化成:
?
?
與平方損失函數(shù)相比,交叉熵函數(shù)有個(gè)非常好的特質(zhì):
?
?
可以看到,由于沒有了σ′這一項(xiàng),這樣一來在更新w和b就不會受到飽和性的影響。當(dāng)誤差大的時(shí)候,權(quán)重更新就快,當(dāng)誤差小的時(shí)候,權(quán)重的更新就慢。
?
3.6 寬深度模型框架
?
在實(shí)驗(yàn)初期,我們只將單獨(dú)的5層DNN模型與線性模型進(jìn)行了比對。通過線下/線上AUC對比,我們發(fā)現(xiàn)單純的DNN模型對于CTR的提升并不明顯。而且單獨(dú)的DNN模型本身也有一些瓶頸,例如,當(dāng)用戶本身是非活躍用戶時(shí),由于其自身與Item之間的交互比較少,導(dǎo)致得到的特征向量會非常稀疏,而深度學(xué)習(xí)模型在處理這種情況時(shí)有可能會過度的泛化,導(dǎo)致推薦與該用戶本身相關(guān)較少的Item。因此,我們將廣泛線性模型與深度學(xué)習(xí)模型相結(jié)合,同時(shí)又包含了一些組合特征,以便更好的抓住Item-Feature-Label三者之間的共性關(guān)系。我們希望在寬深度模型中的寬線性部分可以利用交叉特征去有效地記憶稀疏特征之間的相互作用,而在深層神經(jīng)網(wǎng)絡(luò)部分通過挖掘特征之間的相互作用,提升模型之間的泛化能力。下圖就是我們的寬深度學(xué)習(xí)模型框架:
?
?
在離線階段,我們采用基于Theano、Tensorflow的Keras作為模型引擎。在訓(xùn)練時(shí),我們分別對樣本數(shù)據(jù)進(jìn)行清洗和提權(quán)。在特征方面,對于連續(xù)特征,我們用Min-Max方法做歸一化。在交叉特征方面,我們結(jié)合業(yè)務(wù)需求,提煉出多個(gè)在業(yè)務(wù)場景意義比較重大的交叉特征。在模型方面我們用Adam做為優(yōu)化器,用Cross Entropy做為損失函數(shù)。在訓(xùn)練期間,與Wide & Deep Learning論文中不同之處在于,我們將組合特征作為輸入層分別輸入到對應(yīng)的Deep組件和Wide組件中。然后在Deep部分將全部輸入數(shù)據(jù)送到3個(gè)ReLU層,在最后通過Sigmoid層進(jìn)行打分。我們的Wide&Deep模型在超過7000萬個(gè)訓(xùn)練數(shù)據(jù)中進(jìn)行了訓(xùn)練,并用超過3000萬的測試數(shù)據(jù)進(jìn)行線下模型預(yù)估。我們的Batch-Size設(shè)為50000,Epoch設(shè)為20。
?
4. 深度學(xué)習(xí)線下/線上效果
?
在實(shí)驗(yàn)階段,分別將深度學(xué)習(xí)、寬深度學(xué)習(xí)以及邏輯回歸做了一系列的對比,將表現(xiàn)比較好的寬深度模型放在線上與原本的Base模型進(jìn)行AB實(shí)驗(yàn)。從結(jié)果上來看,寬深度學(xué)習(xí)模型在線下/線上都有比較好的效果。具體結(jié)論如下:
?
?
隨著隱藏層寬度的增加,線下訓(xùn)練的效果也會隨著逐步的提升。但考慮到線上實(shí)時(shí)預(yù)測的性能問題,我們目前采用256->128->64的框架結(jié)構(gòu)。
?
?
下圖是包含了組合特征的寬深度模型與Base模型的線上實(shí)驗(yàn)效果對比圖:
?
?
從線上效果來看,寬深度學(xué)習(xí)模型一定程度上解決了歷史點(diǎn)擊過的團(tuán)單在遠(yuǎn)距離會被召回的問題。同時(shí),寬深度模型也會根據(jù)當(dāng)前的場景推薦一些有新穎性的Item。
?
?
5. 總結(jié)
?
排序是一個(gè)非常經(jīng)典的機(jī)器學(xué)習(xí)問題,實(shí)現(xiàn)模型的記憶和泛化功能是推薦系統(tǒng)中的一個(gè)挑戰(zhàn)。記憶可以被定義為在推薦中將歷史數(shù)據(jù)重現(xiàn),而泛化是基于數(shù)據(jù)相關(guān)性的傳遞性,探索過去從未或很少發(fā)生的Item。寬深度模型中的寬線性部分可以利用交叉特征去有效地記憶稀疏特征之間的相互作用,而深層神經(jīng)網(wǎng)絡(luò)可以通過挖掘特征之間的相互作用,提升模型之間的泛化能力。在線實(shí)驗(yàn)結(jié)果表明,寬深度模型對CTR有比較明顯的提高。同時(shí),我們也在嘗試將模型進(jìn)行一系列的演化:
?
將RNN融入到現(xiàn)有框架。現(xiàn)有的Deep & Wide模型只是將DNN與線性模型做融合,并沒有對時(shí)間序列上的變化進(jìn)行建模。樣本出現(xiàn)的時(shí)間順序?qū)τ谕扑]排序同樣重要,比如當(dāng)一個(gè)用戶按照時(shí)間分別瀏覽了一些異地酒店、景點(diǎn)時(shí),用戶再次再請求該異地城市,就應(yīng)該推出該景點(diǎn)周圍的美食。
引入強(qiáng)化學(xué)習(xí),讓模型可以根據(jù)用戶所處的場景,動態(tài)地推薦內(nèi)容。
?
深度學(xué)習(xí)和邏輯回歸的融合使得我們可以兼得二者的優(yōu)點(diǎn),也為進(jìn)一步的點(diǎn)擊率預(yù)估模型設(shè)計(jì)和優(yōu)化打下了堅(jiān)實(shí)的基礎(chǔ)。
?
6. 參考文獻(xiàn)
?
H. Cheng, L. Koc, J. Harmsen etc, Wide & Deep Learning for Recommender Systems, Published by ACM 2016 Article,?https://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/45530.pdf
P. Covington, J. Adams, E. Sargin, Deep Neural Networks for YouTube Recommendations, RecSys '16 Proceedings of the 10th ACM Conference on Recommender Systems,https://arxiv.org/pdf/1606.07792.pdf
H. Wang, N. Wang, D. Yeung, Collaborative Deep Learning for Recommender Systems.
?
7. 作者簡介
?
潘暉,美團(tuán)點(diǎn)評高級算法工程師。2015年博士畢業(yè)后加入微軟,主要從事自然語言處理的研發(fā)。2016年12月加入美團(tuán)點(diǎn)評,現(xiàn)在負(fù)責(zé)大眾點(diǎn)評的排序業(yè)務(wù),致力于用大數(shù)據(jù)和機(jī)器學(xué)習(xí)技術(shù)解決業(yè)務(wù)問題,提升用戶體驗(yàn)。
?
搜索推薦技術(shù)中心:負(fù)責(zé)點(diǎn)評側(cè)基礎(chǔ)檢索框架及通用搜索推薦平臺的建設(shè);通過大數(shù)據(jù)及人工智能技術(shù),優(yōu)化搜索列表的端到端用戶體驗(yàn),提升推薦展位的精準(zhǔn)性及新穎性;構(gòu)建智能技術(shù)平臺,支持點(diǎn)評側(cè)業(yè)務(wù)的智能化需求。我們的使命是用搜索推薦技術(shù)有效連接人,商家及服務(wù),幫助用戶精準(zhǔn)高效地發(fā)現(xiàn)信息內(nèi)容,優(yōu)化用戶體驗(yàn),擴(kuò)展用戶需求,推動業(yè)務(wù)發(fā)展。
?
來源自:http://blog.csdn.net/a819825294/article/details/71080472
wide && deep 模型
?
wide & deeplearning是什么鬼?
- wide是指高維特征+特征組合的LR。LR高效、容易規(guī)模化(scalable)、可解釋性強(qiáng)。但是泛化性需要在特征工程上下功夫
- deep就是deep learning了。特征工程省力,但是容易過度泛化over-generalize。
顧名思義,Google提出的這篇文章將Wide Model和Deep Model結(jié)合起來進(jìn)行,思路非常值得學(xué)習(xí)。
?
?
1.Wide Model
首先說一下Wide Model,就是上圖中左邊的那一部分,是一個(gè)簡單的邏輯回歸模型。這一部分比較簡單,不多有一個(gè)新的思路就是交叉特征:
?
?
論文中一個(gè)比較形象的例子
For binary features, a cross-product transformation (e.g.,AND(gender=female, language=en)”) is 1 if and only if the constituent features (\gender=female” and \language=en”) are all 1, and 0 otherwise.
對應(yīng)的開源代碼如下:
wide_columns = [gender, native_country, education, occupation, workclass, relationship, age_buckets,tf.contrib.layers.crossed_column([education, occupation], hash_bucket_size=int(1e4)),tf.contrib.layers.crossed_column([native_country, occupation], hash_bucket_size=int(1e4)),tf.contrib.layers.crossed_column([age_buckets, education, occupation], hash_bucket_size=int(1e6))]2.Deep Model
Deep Model是最上圖中右邊的部分,首先是一個(gè)embedding層,然后是兩層的神經(jīng)網(wǎng)絡(luò),最后是一個(gè)softmax。整體上看上去清晰明了,開源的代碼中實(shí)現(xiàn)的也比較簡單,有時(shí)間的話還是要研究研究源碼。
公式表示如下,其中l(wèi)是層數(shù),W是系數(shù),b是偏置,f是激活函數(shù)
?
?
對應(yīng)的開源代碼如下:
deep_columns = [tf.contrib.layers.embedding_column(workclass, dimension=8),tf.contrib.layers.embedding_column(education, dimension=8),tf.contrib.layers.embedding_column(gender, dimension=8),tf.contrib.layers.embedding_column(relationship, dimension=8),tf.contrib.layers.embedding_column(native_country, dimension=8),tf.contrib.layers.embedding_column(occupation, dimension=8),age, education_num, capital_gain, capital_loss, hours_per_week]3.Wide & Deep Model
將上面兩個(gè)基本Model進(jìn)行結(jié)合,得到最終的模型(二分類問題)
?
?
對應(yīng)的開源代碼如下:
import tempfile model_dir = tempfile.mkdtemp() m = tf.contrib.learn.DNNLinearCombinedClassifier(model_dir=model_dir,linear_feature_columns=wide_columns,dnn_feature_columns=deep_columns,dnn_hidden_units=[100, 50])4.完整實(shí)現(xiàn)代碼
# -*- coding: utf-8 -*-import tensorflow as tf import tempfile import pandas as pd import urllib import numpy as np import warningsfrom __future__ import print_functionwarnings.filterwarnings("ignore")# Categorical base columns. gender = tf.contrib.layers.sparse_column_with_keys(column_name="gender", keys=["Female", "Male"]) race = tf.contrib.layers.sparse_column_with_keys(column_name="race", keys=["Amer-Indian-Eskimo", "Asian-Pac-Islander", "Black", "Other", "White"]) education = tf.contrib.layers.sparse_column_with_hash_bucket("education", hash_bucket_size=1000) relationship = tf.contrib.layers.sparse_column_with_hash_bucket("relationship", hash_bucket_size=100) workclass = tf.contrib.layers.sparse_column_with_hash_bucket("workclass", hash_bucket_size=100) occupation = tf.contrib.layers.sparse_column_with_hash_bucket("occupation", hash_bucket_size=1000) native_country = tf.contrib.layers.sparse_column_with_hash_bucket("native_country", hash_bucket_size=1000)# Continuous base columns. age = tf.contrib.layers.real_valued_column("age") age_buckets = tf.contrib.layers.bucketized_column(age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65]) education_num = tf.contrib.layers.real_valued_column("education_num") capital_gain = tf.contrib.layers.real_valued_column("capital_gain") capital_loss = tf.contrib.layers.real_valued_column("capital_loss") hours_per_week = tf.contrib.layers.real_valued_column("hours_per_week")wide_columns = [gender, native_country, education, occupation, workclass, relationship, age_buckets,tf.contrib.layers.crossed_column([education, occupation], hash_bucket_size=int(1e4)),tf.contrib.layers.crossed_column([native_country, occupation], hash_bucket_size=int(1e4)),tf.contrib.layers.crossed_column([age_buckets, education, occupation], hash_bucket_size=int(1e6))]deep_columns = [tf.contrib.layers.embedding_column(workclass, dimension=8),tf.contrib.layers.embedding_column(education, dimension=8),tf.contrib.layers.embedding_column(gender, dimension=8),tf.contrib.layers.embedding_column(relationship, dimension=8),tf.contrib.layers.embedding_column(native_country, dimension=8),tf.contrib.layers.embedding_column(occupation, dimension=8),age, education_num, capital_gain, capital_loss, hours_per_week]model_dir = tempfile.mkdtemp() m = tf.contrib.learn.DNNLinearCombinedClassifier(model_dir=model_dir,linear_feature_columns=wide_columns,dnn_feature_columns=deep_columns,dnn_hidden_units=[100, 50])# Define the column names for the data sets. COLUMNS = ["age", "workclass", "fnlwgt", "education", "education_num","marital_status", "occupation", "relationship", "race", "gender","capital_gain", "capital_loss", "hours_per_week", "native_country", "income_bracket"] LABEL_COLUMN = 'label' CATEGORICAL_COLUMNS = ["workclass", "education", "marital_status", "occupation","relationship", "race", "gender", "native_country"] CONTINUOUS_COLUMNS = ["age", "education_num", "capital_gain", "capital_loss","hours_per_week"]# Download the training and test data to temporary files. # Alternatively, you can download them yourself and change train_file and # test_file to your own paths. train_file = tempfile.NamedTemporaryFile() test_file = tempfile.NamedTemporaryFile() urllib.urlretrieve("http://mlr.cs.umass.edu/ml/machine-learning-databases/adult/adult.data", train_file.name) urllib.urlretrieve("http://mlr.cs.umass.edu/ml/machine-learning-databases/adult/adult.test", test_file.name)# Read the training and test data sets into Pandas dataframe. df_train = pd.read_csv(train_file, names=COLUMNS, skipinitialspace=True) df_test = pd.read_csv(test_file, names=COLUMNS, skipinitialspace=True, skiprows=1) df_train[LABEL_COLUMN] = (df_train['income_bracket'].apply(lambda x: '>50K' in x)).astype(int) df_test[LABEL_COLUMN] = (df_test['income_bracket'].apply(lambda x: '>50K' in x)).astype(int)def input_fn(df):# Creates a dictionary mapping from each continuous feature column name (k) to# the values of that column stored in a constant Tensor.continuous_cols = {k: tf.constant(df[k].values)for k in CONTINUOUS_COLUMNS}# Creates a dictionary mapping from each categorical feature column name (k)# to the values of that column stored in a tf.SparseTensor.categorical_cols = {k: tf.SparseTensor(indices=[[i, 0] for i in range(df[k].size)],values=df[k].values,dense_shape=[df[k].size, 1])for k in CATEGORICAL_COLUMNS}# Merges the two dictionaries into one.feature_cols = dict(continuous_cols.items() + categorical_cols.items())# Converts the label column into a constant Tensor.label = tf.constant(df[LABEL_COLUMN].values)# Returns the feature columns and the label.return feature_cols, labeldef train_input_fn():return input_fn(df_train)def eval_input_fn():return input_fn(df_test)print('df_train shape:',np.array(df_train).shape) print('df_test shape:',np.array(df_test).shape)m.fit(input_fn=train_input_fn, steps=200) results = m.evaluate(input_fn=eval_input_fn, steps=1) for key in sorted(results):print("%s: %s" % (key, results[key]))?
總結(jié)
以上是生活随笔為你收集整理的深度学习在美团点评推荐平台排序中的应用 widedeep推荐系统模型--学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GBDT和随机森林的区别
- 下一篇: java信息管理系统总结_java实现科