引言
我們正處在一個知識爆炸的時代,伴隨著信息量的劇增和人工智能的蓬勃發(fā)展,互聯(lián)網(wǎng)公司越發(fā)具有強烈的個性化、智能化信息展示的需求。而信息展示個性化的典型應(yīng)用主要包括搜索列表、推薦列表、廣告展示等等。
很多人不知道的是,看似簡單的個性化信息展示背后,涉及大量的數(shù)據(jù)、算法以及工程架構(gòu)技術(shù),這些足以讓大部分互聯(lián)網(wǎng)公司望而卻步。究其根本原因,個性化信息展示背后的技術(shù)是排序?qū)W習(xí)問題(Learning to Rank)。顯然,市面上大部分關(guān)于排序?qū)W習(xí)的文章,要么偏算法、要么偏工程。雖然算法方面有一些系統(tǒng)性的介紹文章,但往往對讀者的數(shù)學(xué)能力要求比較高,也偏學(xué)術(shù)論文,對于非算法同學(xué)來說門檻非常高。而大部分工程方面的文章也比較粗糙,基本上停留在Google的Two-Phase Scheme階段,從工程實施的角度來說,遠(yuǎn)遠(yuǎn)還不夠具體。
對于那些由系統(tǒng)開發(fā)工程師負(fù)責(zé)在線排序架構(gòu)的團(tuán)隊來說,本文會采用通俗的例子和類比方式來闡述算法部分,希望能夠幫助大家更好地理解和掌握排序?qū)W習(xí)的核心概念。如果是算法工程師團(tuán)隊的同學(xué),可以忽略算法部分的內(nèi)容。本文的架構(gòu)部分闡述了美團(tuán)點評到店餐飲業(yè)務(wù)線上運行的系統(tǒng),可以作為在線排序系統(tǒng)架構(gòu)設(shè)計的參考原型直接使用。該架構(gòu)在服務(wù)治理、分層設(shè)計的理念,對于保障在線排序架構(gòu)的高性能、高可用性、易維護(hù)性也具有一定的參考價值。包括很多具體環(huán)節(jié)的實施方案也可以直接進(jìn)行借鑒,例如流量分桶、流量分級、特征模型、級聯(lián)模型等等。
總之,讓開發(fā)工程師能夠理解排序?qū)W習(xí)算法方面的核心概念,并為在線架構(gòu)實施提供細(xì)顆粒度的參考架構(gòu),是本文的重要目標(biāo)。
算法部分機器學(xué)習(xí)涉及優(yōu)化理論、統(tǒng)計學(xué)、數(shù)值計算等多個領(lǐng)域。這給那些希望學(xué)習(xí)機器學(xué)習(xí)核心概念的系統(tǒng)開發(fā)工程師帶來了很大的障礙。不過,復(fù)雜的概念背后往往蘊藏著樸素的道理。本節(jié)將嘗試采用通俗的例子和類比方式,來對機器學(xué)習(xí)和排序?qū)W習(xí)的一些核心概念進(jìn)行揭秘。
機器學(xué)習(xí) 什么是機器學(xué)習(xí)?典型的機器學(xué)習(xí)問題,如下圖所示:
機器學(xué)習(xí)模型或算法(Model/Algorithm)會根據(jù)觀察到的特征值(Feature)進(jìn)行預(yù)測,給出預(yù)測結(jié)果或者目標(biāo)(Prediction/Target)。這就像是一個函數(shù)計算過程,對于特定X值(Feature),算法模型就像是函數(shù),最終的預(yù)測結(jié)果是Y值。不難理解,機器學(xué)習(xí)的核心問題就是如何得到預(yù)測函數(shù)。
Wikipedia的對機器學(xué)習(xí)定義如下:
“Machine learning is a subset of artificial intelligence in the field of computer science that often uses statistical techniques to give computers the ability to learn with data, without being explicitly programmed.”
機器學(xué)習(xí)的最重要本質(zhì)是從數(shù)據(jù)中學(xué)習(xí),得到預(yù)測函數(shù)。人類的思考過程以及判斷能力本質(zhì)上也是一種函數(shù)處理。從數(shù)據(jù)或者經(jīng)驗中學(xué)習(xí),對于人類來說是一件再平常不過的事情了。例如人們通過觀察太陽照射物體影子的長短而發(fā)明了日晷,從而具備了計時和制定節(jié)氣的能力。古埃及人通過尼羅河水的漲落發(fā)明了古埃及歷法。
又比如人們通過觀察月亮形狀的變化而發(fā)明了陰歷。
如果機器能夠像人一樣具備從數(shù)據(jù)中學(xué)習(xí)的能力,從某種意義上講,就具備了一定的“智能”。現(xiàn)在需要回答的兩個問題就是:
到底什么是“智能”?
如何讓機器具備智能?
什么是智能?在回答這個問題之前,我們先看看傳統(tǒng)的編程模式為什么不能稱之為“智能”。傳統(tǒng)的編程模式如下圖所示,它一般要經(jīng)歷如下幾個階段:
人類通過觀察數(shù)據(jù)(Data)總結(jié)經(jīng)驗,轉(zhuǎn)化成知識(Knowledge)。
人類將知識轉(zhuǎn)化成規(guī)則(Rule)。
工程師將規(guī)則轉(zhuǎn)化成計算機程序(Program)。
在這種編程模式下,如果一個問題被規(guī)則覆蓋,那么計算機程序就能處理。對于規(guī)則不能覆蓋的問題,只能由人類來重新思考,制定新規(guī)則來解決。所以在這里“智能”角色主要由人類來承擔(dān)。人類負(fù)責(zé)解決新問題,所以傳統(tǒng)的程序本身不能稱之為“智能”。
所以,“智能”的一個核心要素就是“舉一反三”。
如何讓機器具備智能?在討論這個問題之前,可以先回顧一下人類是怎么掌握“舉一反三”的能力的?基本流程如下:
老師給學(xué)生一些題目,指導(dǎo)學(xué)生如何解題。學(xué)生努力掌握解題思路,盡可能讓自己的答案和老師給出的答案一致。
學(xué)生需要通過一些考試來證明自己具備“舉一反三”的能力。如果通過了這些考試,學(xué)生將獲得畢業(yè)證書或者資格從業(yè)證書。
學(xué)生變成一個從業(yè)者之后將會面臨并且處理很多之前沒有碰到過的新問題。
機器學(xué)習(xí)專家從人類的學(xué)習(xí)過程中獲得靈感,通過三個階段讓機器具備“舉一反三”的能力。這三個階段是:訓(xùn)練階段(Training)、測試階段(Testing)、推導(dǎo)階段(Inference)。下面逐一進(jìn)行介紹:
訓(xùn)練階段訓(xùn)練階段如下圖所示:
人類給機器學(xué)習(xí)模型一些訓(xùn)練樣本(X,Y),X代表特征,Y代表目標(biāo)值。這就好比老師教學(xué)生解題,X代表題目,Y代表標(biāo)準(zhǔn)答案。
機器學(xué)習(xí)模型嘗試想出一種方法解題。
在訓(xùn)練階段,機器學(xué)習(xí)的目標(biāo)就是讓損失函數(shù)值最小。類比學(xué)生嘗試讓自己解題的答案和老師給的標(biāo)準(zhǔn)答案差別最小,思路如出一轍。
測試階段測試階段如下圖所示:
人類給訓(xùn)練好的模型一批完全不同的測試樣本(X,Y)。這就好比學(xué)生拿到考試試卷。
模型進(jìn)行推導(dǎo)。這個過程就像學(xué)生正在考試答題。
人類要求測試樣本的總損失函數(shù)值低于設(shè)定的最低目標(biāo)值。這就像學(xué)校要求學(xué)生的考試成績必須及格一樣。
推導(dǎo)階段推導(dǎo)階段如下圖所示:
在這個階段機器學(xué)習(xí)模型只能拿到特征值X,而沒有目標(biāo)值。這就像工作中,人們只是在解決一個個的問題,但不知道正確的結(jié)果到底是什么。
在推導(dǎo)階段,機器學(xué)習(xí)的目標(biāo)就是預(yù)測,給出目標(biāo)值。
排序?qū)W習(xí) 什么是排序?qū)W習(xí)?Wikipedia的對排序?qū)W習(xí)的定義如下:
“Learning to rank is the application of machine learning, typically supervised, semi-supervised or reinforcement learning, in the construction of ranking models for information retrieval systems. Training data consists of lists of items with some partial order specified between items in each list. This order is typically induced by giving a numerical or ordinal score or a binary judgment (e.g. "relevant" or "not relevant") for each item. The ranking model"s purpose is to rank, i.e. produce a permutation of items in new, unseen lists in a way which is "similar" to rankings in the training data in some sense.”
排序?qū)W習(xí)是機器學(xué)習(xí)在信息檢索系統(tǒng)里的應(yīng)用,其目標(biāo)是構(gòu)建一個排序模型用于對列表進(jìn)行排序。排序?qū)W習(xí)的典型應(yīng)用包括搜索列表、推薦列表和廣告列表等等。
列表排序的目標(biāo)是對多個條目進(jìn)行排序,這就意味著它的目標(biāo)值是有結(jié)構(gòu)的。與單值回歸和單值分類相比,結(jié)構(gòu)化目標(biāo)要求解決兩個被廣泛提起的概念:
列表評價指標(biāo)
列表訓(xùn)練算法
列表評價指標(biāo)以關(guān)鍵詞搜索返回文章列表為例,這里先分析一下列表評價指標(biāo)要解決什么挑戰(zhàn)。
第一個挑戰(zhàn)就是定義文章與關(guān)鍵詞之間的相關(guān)度,這決定了一篇文章在列表中的位置,相關(guān)度越高排序就應(yīng)該越靠前。
第二個挑戰(zhàn)是當(dāng)列表中某些文章沒有排在正確的位置時候,如何給整個列表打分。舉個例子來說,假如對于某個關(guān)鍵詞,按照相關(guān)性的高低正確排序,文檔1、2、3、4、5應(yīng)該依次排在前5位。現(xiàn)在的挑戰(zhàn)就是,如何評估“2,1,3,4,5”和“1,2,5,4,3”這兩個列表的優(yōu)劣呢?
列表排序的評價指標(biāo)體系總來的來說經(jīng)歷了三個階段,分別是Precision and Recall、Discounted Cumulative Gain(DCG)和Expected Reciprocal Rank(ERR)。我們逐一進(jìn)行講解。
Precision and Recall(P-R)本評價體系通過準(zhǔn)確率(Precision)和召回率(Recall)兩個指標(biāo)來共同衡量列表的排序質(zhì)量。對于一個請求關(guān)鍵詞,所有的文檔被標(biāo)記為相關(guān)和不相關(guān)兩種。
Precision的定義如下:
Recall的定義如下:
舉個列子來說,對于某個請求關(guān)鍵詞,有200篇文章實際相關(guān)。某個排序算法只認(rèn)為100篇文章是相關(guān)的,而這100篇文章里面,真正相關(guān)的文章只有80篇。按照以上定義:
準(zhǔn)確率=80/100=0.8
召回率=80/200=0.4。
Discounted Cumulative Gain(DCG)P-R的有兩個明顯缺點:
所有文章只被分為相關(guān)和不相關(guān)兩檔,分類顯然太粗糙。
沒有考慮位置因素。
DCG解決了這兩個問題。對于一個關(guān)鍵詞,所有的文檔可以分為多個相關(guān)性級別,這里以rel1,rel2...來表示。文章相關(guān)性對整個列表評價指標(biāo)的貢獻(xiàn)隨著位置的增加而對數(shù)衰減,位置越靠后,衰減越嚴(yán)重。基于DCG評價指標(biāo),列表前p個文檔的評價指標(biāo)定義如下:
對于排序引擎而言,不同請求的結(jié)果列表長度往往不相同。當(dāng)比較不同排序引擎的綜合排序性能時,不同長度請求之間的DCG指標(biāo)的可比性不高。目前在工業(yè)界常用的是Normalized DCG(nDCG),它假定能夠獲取到某個請求的前p個位置的完美排序列表,這個完美列表的分值稱為Ideal DCG(IDCG),nDCG等于DCG與IDCG比值。所以nDCG是一個在0到1之間的值。
nDCG的定義如下:
IDCG的定義如下:
|REL|代表按照相關(guān)性排序好的最多到位置p的結(jié)果列表。
Expected Reciprocal Rank(ERR)與DCG相比,除了考慮位置衰減和允許多種相關(guān)級別(以R1,R2,R3...來表示)以外,ERR更進(jìn)了一步,還考慮了排在文檔之前所有文檔的相關(guān)性。舉個例子來說,文檔A非常相關(guān),排在第5位。如果排在前面的4個文檔相關(guān)度都不高,那么文檔A對列表的貢獻(xiàn)就很大。反過來,如果前面4個文檔相關(guān)度很大,已經(jīng)完全解決了用戶的搜索需求,用戶根本就不會點擊第5個位置的文檔,那么文檔A對列表的貢獻(xiàn)就不大。
ERR的定義如下:
列表訓(xùn)練算法做列表排序的工程師們經(jīng)常聽到諸如Pointwise、Pairwise和Listwise的概念。這些是什么東西呢,背后的原理又是什么呢?這里將逐一解密。
仍然以關(guān)鍵詞搜索文章為例,排序?qū)W習(xí)算法的目標(biāo)是為給定的關(guān)鍵詞對文章列表進(jìn)行排序。做為類比,假定有一個學(xué)者想要對各科學(xué)生排名進(jìn)行預(yù)測。各種角色的對應(yīng)關(guān)系如下:
首先我們要告訴學(xué)者每個學(xué)生的各種屬性,這就像我們要告訴排序算法文檔特征。對于目標(biāo)值,我們卻有三種方式來告訴學(xué)者:
對于每個學(xué)科,我們可以告訴學(xué)者每個學(xué)生的成績。比較每個學(xué)生的成績,學(xué)者當(dāng)然可以算出每個學(xué)生的最終排名。這種訓(xùn)練方法被稱為Pointwise。對于Pointwise算法,如果最終預(yù)測目標(biāo)是一個實數(shù)值,就是一個回歸問題。如果目標(biāo)是概率預(yù)測,這就是一個分類問題,例如CTR預(yù)估。
對于每個學(xué)科,我們可以告訴學(xué)者任意兩個學(xué)生的相互排名。根據(jù)學(xué)生之間排名的情況,學(xué)者也可以算出每個學(xué)生的最終排名。這種訓(xùn)練方法被稱為Pairwise。Pairwise算法的目標(biāo)是減少逆序的數(shù)量,所以是個二分類問題。
對于每個學(xué)科,我們可以直接告訴學(xué)者所有學(xué)生的整體排名。這種訓(xùn)練方法被稱為Listwise。Listwise算法的目標(biāo)往往是直接優(yōu)化nDCG、ERR等評價指標(biāo)。
這三種方法表面看上去有點像玩文字游戲,但是背后卻是工程師和科學(xué)家們不斷探索的結(jié)果。最直觀的方案是Pointwise算法,例如對于廣告CTR預(yù)估,在訓(xùn)練階段需要標(biāo)注某個文檔的點擊概率,這相對來說容易。Pairwise算法一個重要分支是Lambda系列,包括LambdaRank、LambdaMart等,它的核心思想是:很多時候我們很難直接計算損失函數(shù)的值,但卻很容易計算損失函數(shù)梯度(Gradient)。這意味著我們很難計算整個列表的nDCG和ERR等指標(biāo),但卻很容易知道某個文檔應(yīng)該排的更靠前還是靠后。Listwise算法往往效果最好,但是如何為每個請求對所有文檔進(jìn)行標(biāo)注是一個巨大的挑戰(zhàn)。
在線排序架構(gòu)典型的信息檢索包含兩個階段:索引階段和查詢階段。這兩個階段的流程以及相互關(guān)系可以用下圖來表示:
索引階段的工作是由索引器(Indexer)讀取文檔(Documents)構(gòu)建索引(Index)。
查詢階段讀取索引做為召回,然后交給Topn Retriever進(jìn)行粗排,在粗排后的結(jié)果里面將前n個文檔傳給Reranker進(jìn)行精排。這樣一個召回、粗排、精排的架構(gòu)最初是由Google提出來的,也被稱為“Two-Phase Scheme”。
索引部分屬于離線階段,這里重點講述在線排序階段,即查詢階段。
三大挑戰(zhàn)在線排序架構(gòu)主要面臨三方面的挑戰(zhàn):特征、模型和召回。
特征挑戰(zhàn)包括特征添加、特征算子、特征歸一化、特征離散化、特征獲取、特征服務(wù)治理等。
模型挑戰(zhàn)包括基礎(chǔ)模型完備性、級聯(lián)模型、復(fù)合目標(biāo)、A/B實驗支持、模型熱加載等。
召回挑戰(zhàn)包括關(guān)鍵詞召回、LBS召回、推薦召回、粗排召回等。
三大挑戰(zhàn)內(nèi)部包含了非常多更細(xì)粒度的挑戰(zhàn),孤立地解決每個挑戰(zhàn)顯然不是好思路。在線排序作為一個被廣泛使用的架構(gòu)值得采用領(lǐng)域模型進(jìn)行統(tǒng)一解決。Domain-driven design(DDD)的三個原則分別是:領(lǐng)域聚焦、邊界清晰、持續(xù)集成。
基于以上分析,我們構(gòu)建了三個在線排序領(lǐng)域模型:召回治理、特征服務(wù)治理和在線排序分層模型。
召回治理經(jīng)典的Two-Phase Scheme架構(gòu)如下圖所示,查詢階段應(yīng)該包含:召回、粗排和精排。但從領(lǐng)域架構(gòu)設(shè)計的角度來講,粗排對于精排而言也是一種召回。和基于傳統(tǒng)的文本搜索不同,美團(tuán)點評這樣的O2O公司需要考慮地理位置和距離等因素,所以基于LBS的召回也是一種召回。與搜索不同,推薦召回往往基于協(xié)同過濾來完成的,例如User-Based CF和Item-Based CF。
綜上所述,召回總體而言分成四大類:
關(guān)鍵詞召回,我們采用Elasticsearch解決方案。
距離召回,我們采用K-D tree的解決方案。
粗排召回。
推薦類召回。
特征服務(wù)治理傳統(tǒng)的視角認(rèn)為特征服務(wù)應(yīng)該分為用戶特征(User)、查詢特征(Query)和文檔特征(Doc),如下圖:
這是比較純粹的業(yè)務(wù)視角,并不滿足DDD的領(lǐng)域架構(gòu)設(shè)計思路。由于特征數(shù)量巨大,我們沒有辦法為每個特征設(shè)計一套方案,但是我們可以把特征進(jìn)行歸類,為幾類特征分別設(shè)計解決方案。每類技術(shù)方案需要統(tǒng)一考慮性能、可用性、存儲等因素。從領(lǐng)域視角,特征服務(wù)包含四大類:
列表類特征。一次請求要求返回實體列表特征,即多個實體,每個實體多個特征。這種特征建議采用內(nèi)存列表服務(wù),一次性返回所有請求實體的所有特征。避免多次請求,從而導(dǎo)致數(shù)量暴增,造成系統(tǒng)雪崩。
實體特征。一次請求返回單實體的多個特征。建議采用Redis、Tair等支持多級的Key-Value服務(wù)中間鍵提供服務(wù)。
上下文特征。包括召回靜態(tài)分、城市、Query特征等。這些特征直接放在請求內(nèi)存里面。
相似性特征。有些特征是通過計算個體和列表、列表和列表的相似度而得到的。建議提供多帶帶的內(nèi)存計算服務(wù),避免這類特征的計算影響在線排序性能。本質(zhì)上這是一種計算轉(zhuǎn)移的設(shè)計。
在線排序分層模型如下圖所示,典型的排序流程包含六個步驟:場景分發(fā)(Scene Dispatch)、流量分配(Traffic Distribution)、召回(Recall)、特征抽取(Feature Retrieval)、預(yù)測(Prediction)、排序(Ranking)等等。
按照DDD的設(shè)計原則,我們設(shè)計了如下在線排序分層模型,包括:場景分發(fā)(Scene Dispatch)、模型分發(fā)(Model Distribution)、排序(Ranking)、特征管道(Feature Pipeline)、預(yù)測管道(Prediction Pipeline)。我們將逐一進(jìn)行介紹。
場景分發(fā)(Scene Dispatch)場景分發(fā)一般是指業(yè)務(wù)類型的分發(fā)。對于美團(tuán)點評而言包括:分平臺、分列表、分使用場景等。如下圖所示:
模型分發(fā)(Model Distribution)模型分發(fā)的目標(biāo)是把在線流量分配給不同的實驗?zāi)P停唧w而言要實現(xiàn)三個功能:
為模型迭代提供在線流量,負(fù)責(zé)線上效果收集、驗證等。
A/B測試,確保不同模型之間流量的穩(wěn)定、獨立和互斥、確保效果歸屬唯一。
確保與其他層的實驗流量的正交性。
流量的定義是模型分發(fā)的一個基礎(chǔ)問題。典型的流量包括:訪問、用戶和設(shè)備。
如何讓一個流量穩(wěn)定地映射到特定模型上面,流量之間是否有級別?這些是模型分發(fā)需要重點解決的問題。
流量分桶原理采用如下步驟將流量分配到具體模型上面去:
把所有流量分成N個桶。
每個具體的流量Hash到某個桶里面去。
給每個模型一定的配額,也就是每個策略模型占據(jù)對應(yīng)比例的流量桶。
所有策略模型流量配額總和為100%。
當(dāng)流量和模型落到同一個桶的時候,該模型擁有該流量。
舉個例子來說,如上圖所示,所有流量分為32個桶,A、B、C三個模型分別擁有37.5%、25%和37.5%的配額。對應(yīng)的,A、B、C應(yīng)該占據(jù)12、8和12個桶。
為了確保模型和流量的正交性,模型和流量的Hash Key采用不同的前綴。
流量分級每個團(tuán)隊的模型分級策略并不相同,這里只給出一個建議模型流量分級:
基線流量。本流量用于與其他流量進(jìn)行對比,以確定新模型的效果是否高于基準(zhǔn)線,低于基準(zhǔn)線的模型要快速下線。另外,主力流量相對基線流量的效果提升也是衡量算法團(tuán)隊貢獻(xiàn)的重要指標(biāo)。
實驗流量。該流量主要用于新實驗?zāi)P汀T摿髁看笮≡O(shè)計要注意兩點:第一不能太大而傷害線上效果;第二不能太小,流量太小會導(dǎo)致方差太大,不利于做正確的效果判斷。
潛力流量。如果實驗流量在一定周期內(nèi)效果比較好,可以升級到潛力流量。潛力流量主要是要解決實驗流量方差大帶來的問題。
主力流量。主力流量只有一個,即穩(wěn)定運行效果最好的流量。如果某個潛力流量長期好于其他潛力流量和主力流量,就可以考慮把這個潛力流量升級為主力流量。
做實驗的過程中,需要避免新實驗流量對老模型流量的沖擊。流量群體對于新模型會有一定的適應(yīng)期,而適應(yīng)期相對于穩(wěn)定期的效果一般會差一點。如果因為新實驗的上線而導(dǎo)致整個流量群體的模型都更改了,從統(tǒng)計學(xué)的角度講,模型之間的對比關(guān)系沒有變化。但這可能會影響整個大盤的效果,成本很高。
為了解決這個問題,我們的流量分桶模型優(yōu)先為模型列表前面的模型分配流量,實驗?zāi)P捅M量放在列表尾端。這樣實驗?zāi)P偷念l繁上下線不影響主力和潛力流量的用戶群體。當(dāng)然當(dāng)發(fā)生模型流量升級的時候,很多流量用戶的服務(wù)模型都會更改。這種情況并不是問題,因為一方面我們在嘗試讓更多用戶使用更好的模型,另一方面固定讓一部分用戶長期使用實驗流量也是不公平的事情。
排序(Ranking)排序模塊是特征模塊和預(yù)測模塊的容器,它的主要職責(zé)如下:
獲取所有列表實體進(jìn)行預(yù)測所需特征。
將特征交給預(yù)測模塊進(jìn)行預(yù)測。
對所有列表實體按照預(yù)測值進(jìn)行排序。
特征管道(Feature Pipeline)特征管道包含特征模型(Feature Model)、表達(dá)式(Expression)、原子特征(Atomic Feature)、 特征服務(wù)代理(Feature Proxy)、特征服務(wù)(Feature Service)。如下圖所示:
特征管道要解決兩個核心問題:
給定特征名獲取對應(yīng)特征值。這個過程很復(fù)雜,要完成特征名->特征服務(wù)->特征類->特征值的轉(zhuǎn)化過程。
特征算子問題。模型使用的特征往往是對多個原子特征進(jìn)行復(fù)合運算后的結(jié)果。另外,特征離散化、歸一化也是特征算子需要解決的問題。
完整的特征獲取流程如下圖所示,具體的流程如下:
Ranking模塊從FeatureModel里面讀取所有的原始特征名。
Ranking將所有的原始特征名交給Feature Proxy。
Feature Proxy根據(jù)特征名的標(biāo)識去調(diào)用對應(yīng)的Feature Service,并將原始特征值返回給Ranking模塊。
Ranking模塊通過Expression將原始特征轉(zhuǎn)化成復(fù)合特征。
Ranking模塊將所有特征交給級聯(lián)模型做進(jìn)一步的轉(zhuǎn)換。
特征模型(Feature Model)我們把所有與特征獲取和特征算子的相關(guān)信息都放在一個類里面,這個類就是FeatureModel,定義如下:
//包含特征獲取和特征算子計算所需的meta信息 public class FeatureModel { //這是真正用在Prediction里面的特征名 private String featureName; //通過表達(dá)式將多種原子特征組合成復(fù)合特征。 private IExpression expression; //這些特征名是真正交給特征服務(wù)代理(Feature Proxy)去從服務(wù)端獲取特征值的特征名集合。 private Set表達(dá)式(Expression)originalFeatureNames; //用于指示特征是否需要被級聯(lián)模型轉(zhuǎn)換 private boolean isTransformedFeature; //是否為one-hot特征 private boolean isOneHotIdFeature; //不同one-hot特征之間往往共享相同的原始特征,這個變量>用于標(biāo)識原始特征名。 private String oneHotIdKey; //表明本特征是否需要歸一化 private boolean isNormalized; }
表達(dá)式的目的是為了將多種原始特征轉(zhuǎn)換成一個新特征,或者對單個原始特征進(jìn)行運算符轉(zhuǎn)換。我們采用前綴法表達(dá)式(Polish Notation)來表示特征算子運算。例如表達(dá)式(5-6)*7的前綴表達(dá)式為* - 5 6 7。
復(fù)合特征需要指定如下分隔符:
復(fù)合特征前綴。區(qū)別于其他類型特征,我們以“$”表示該特征為復(fù)合特征。
表達(dá)式各元素之間的分隔符,采用“_”來標(biāo)識。
用“O”表示運算符前綴。
用“C”表示常數(shù)前綴。
用“V”表示變量前綴。
例如:表達(dá)式v1 + 14.2 + (2*(v2+v3)) 將被表示為 $O+_O+_Vv1_C14.2_O*_C2_O+_Vv2_Vv3
原子特征(Atomic Feature)原子特征(或者說原始特征)包含特征名和特征值兩個部分。原子特征的讀取需要由4種實體類共同完成:
POJO用于存儲特征原始值。例如DealInfo保存了所有與Deal實體相關(guān)的特征值,包括Price、maxMealPerson、minMealPerson等等。
ScoringValue用于存儲從POJO中返回的特征值。特征值包含三種基本類型,即數(shù)量型(Quantity)、序數(shù)型(Ordinal)、類別型(Categorical)。
ScoreEnum實現(xiàn)特征名到特征值的映射。每類原子特征對應(yīng)于一個ScoreEnum類,特征名通過反射(Reflection)的方式來構(gòu)建對應(yīng)的ScoreEnum類。ScoreEnum類和POJO一起共同實現(xiàn)特征值的讀取。
FeatureScoreEnumContainer用于保存一個算法模型所需所有特征的ScoreEnum。
一個典型的例子如下圖所示:
DealInfo是POJO類。
DealInfoScoreEnum是一個ScoreEnum基類。對應(yīng)于平均用餐人數(shù)特征、價格等特征,我們定義了DIAveMealPerson和DIPrice的具體ScoreEnum類。
FeatureScoreEnumContainer用于存儲某個模型的所有特征的ScoreEnum。
復(fù)雜系統(tǒng)設(shè)計需要充分的利用語言特性和設(shè)計模式。建議的優(yōu)化點有三個:
為每個原子特征定義一個ScoreEnum類會導(dǎo)致類數(shù)量暴增。優(yōu)化方式是ScoreEnum基類定義為Enum類型,每個具體特征類為一個枚舉值,枚舉值繼承并實現(xiàn)枚舉類的方法。
FeatureScoreEnumContainer采用Build設(shè)計模式將一個算法模型的所需特征轉(zhuǎn)換成ScoreEnum集合。
ScoreEnum從POJO類中讀取具體特征值采用的是Command模式。
這里稍微介紹一下Command設(shè)計模式。Command模式的核心思想是需求方只要求拿到相關(guān)信息,不關(guān)心誰提供以及怎么提供。具體的提供方接受需求方的需求,負(fù)責(zé)將結(jié)果交給需求方。
在特征讀取里面,需求方是模型,模型僅僅提供一個特征名(FeatureName),不關(guān)心怎么讀取對應(yīng)的特征值。具體的ScoreEnum類是具體的提供方,具體的ScoreEnum從POJO里面讀取特定的特征值,并轉(zhuǎn)換成ScoringValue交給模型。
特征服務(wù)代理(Feature Proxy)特征服務(wù)代理負(fù)責(zé)遠(yuǎn)程特征獲取實施,具體的過程包括:
每一大類特征或者一種特征服務(wù)有一個FeatureProxy,具體的FeatureProxy負(fù)責(zé)向特征服務(wù)發(fā)起請求并獲取POJO類。
所有的FeatureProxy注冊到FeatureServiceContainer類。
在具體的一次特征獲取中,F(xiàn)eatureServiceContainer根據(jù)FeatureName的前綴負(fù)責(zé)將特征獲取分配到不同的FeatureProxy類里面。
FeatureProxy根據(jù)指定的實體ID列表和特征名從特征服務(wù)中讀取POJO列表。只有對應(yīng)ID的指定特征名(keys)的特征值才會被賦值給POJO。這就最大限度地降低了網(wǎng)絡(luò)讀取的成本。
預(yù)測管道(Prediction Pipeline)預(yù)測管道包含:預(yù)測(Prediction)、級聯(lián)模型(Cascade Model)、表達(dá)式(Expression)、特征轉(zhuǎn)換(Transform)、計分(Scoring)和原子模型(Atomic Model)。
預(yù)測(Prediction)預(yù)測本質(zhì)上是對模型的封裝。它負(fù)責(zé)將每個列表實體的特征轉(zhuǎn)化成模型需要的輸入格式,讓模型進(jìn)行預(yù)測。
級聯(lián)模型(Cascade Model)我們構(gòu)建級聯(lián)模型主要是基于兩方面的觀察:
基于Facebook的《Practical Lessons from Predicting Clicks on Ads at Facebook》的Xgboost+LR以及最近很熱門的Wide&Deep表明,對一些特征,特別是ID類特征通過樹模型或者NN模型進(jìn)行轉(zhuǎn)化,把轉(zhuǎn)化后的值做為特征值交給預(yù)測模型進(jìn)行預(yù)測,往往會能實現(xiàn)更好的效果。
有些訓(xùn)練目標(biāo)是復(fù)合目標(biāo),每個子目標(biāo)需要通過不同的模型進(jìn)行預(yù)測。這些子目標(biāo)之間通過一個簡單的表達(dá)式計算出最終的預(yù)測結(jié)果。
舉例如下圖所示,我們自上而下進(jìn)行講解:
該模型有UserId、CityId、UserFeature、POI等特征。
UserId和CityId特征分別通過GBDT和NN模型進(jìn)行轉(zhuǎn)換(Transform)。
轉(zhuǎn)換后的特征和UserFeature、POI等原始特征一起交給NN和LR模型進(jìn)行算分(Scoring)。
最終的預(yù)測分值通過表達(dá)式Prediction Score = αNNScore + βLRScore/(1+γ)來完成。表達(dá)式中的 α 、β和γ是事先設(shè)置好的值。
原子模型(Atomic Model)在這里原子模型指的是一種原子計算拓?fù)浣Y(jié)構(gòu),比如線性模型、樹模型和網(wǎng)絡(luò)模型。
常用的模型像Logistic Regression和Linear Regression都是線性模型。GBDT、Random Forest都是樹模型。MLP、CNN、RNN都是網(wǎng)絡(luò)模型。
這里定義的原子模型主要的目的是為了工程實施的便利。一個模型被認(rèn)定為原子模型有如下兩個原因:
該模型經(jīng)常做為獨立預(yù)測模型被使用。
該模型有比較完整的實現(xiàn)代碼。
總結(jié)本文總結(jié)了作者在美團(tuán)點評解決到店餐飲個性化信息展示的相關(guān)經(jīng)驗,從算法和架構(gòu)兩方面進(jìn)行闡述。在算法部分,文章采用通俗的例子和類比方式進(jìn)行講解,希望非算法工程師能夠理解關(guān)鍵的算法概念。架構(gòu)部分比較詳細(xì)地闡述了到店餐飲的排序架構(gòu)。
根據(jù)我們所掌握的知識,特征治理和召回治理的思路是一種全新的視角,這對于架構(gòu)排序系統(tǒng)設(shè)計有很大的幫助。這種思考方式同樣也適用于其他領(lǐng)域模型的構(gòu)建。與Google提供的經(jīng)典Two-Phase Scheme架構(gòu)相比,在線排序分層模型提供了更細(xì)顆粒度的抽象原型。該原型細(xì)致的闡述了包括分流、A/B測試、特征獲取、特征算子、級聯(lián)模型等一系列經(jīng)典排序架構(gòu)問題。同時該原型模型由于采用了分層和層內(nèi)功能聚焦的思路,所以它比較完美地體現(xiàn)了DDD的三大設(shè)計原則,即領(lǐng)域聚焦、邊界清晰、持續(xù)集成。
作者簡介劉丁,曾就職于Amazon、TripAdvisor。2014年加入美團(tuán),先后負(fù)責(zé)美團(tuán)推薦系統(tǒng)、智能篩選系統(tǒng)架構(gòu)、美團(tuán)廣告系統(tǒng)的架構(gòu)和上線、完成美團(tuán)廣告運營平臺的搭建。目前負(fù)責(zé)到店餐飲算法策略方向,推進(jìn)AI在到店餐飲各領(lǐng)域的應(yīng)用。
參考文章:[1]Gamma E, Helm R, Johnson R, et al. Design Patterns-Elements of Reusable Object-Oriented Software. Machinery Industry, 2003.
[2]Wikipedia,Learning to rank.
[3]Wikipedia,Machine learning.
[4]Wikipedia,Precision and recall.
[5]Wikipedia,Discounted cumulative gain.
[6]Wikipedia,Domain-driven design.
[7]Wikipedia,Elasticsearch.
[8]Wikipedia,k-d tree.
[9]百度百科,太陽歷.
[10]百度百科,陰歷.
[11]Xinran H, Junfeng P, Ou J, et al. Practical Lessons from Predicting Clicks on Ads at Facebook
[12]Olivier C, Donald M, Ya Z, Pierre G. Expected Reciprocal Rank for Graded Relevance
[13]Heng-Tze C, Levent K, et al. Wide & Deep Learning for Recommender Systems
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/19880.html
摘要:一些知識點有哪些方法方法前端從入門菜鳥到實踐老司機所需要的資料與指南合集前端掘金前端從入門菜鳥到實踐老司機所需要的資料與指南合集歸屬于筆者的前端入門與最佳實踐。 工欲善其事必先利其器-前端實習(xí)簡歷篇 - 掘金 有幸認(rèn)識很多在大廠工作的學(xué)長,在春招正式開始前為我提供很多內(nèi)部推薦的機會,非常感謝他們對我的幫助。現(xiàn)在就要去北京了,對第一份正式的實習(xí)工作也充滿期待,也希望把自己遇到的一些問題和...
摘要:更多資源請文章轉(zhuǎn)自月份前端資源分享的作用數(shù)組元素隨機化排序算法實現(xiàn)學(xué)習(xí)筆記數(shù)組隨機排序個變態(tài)題解析上個變態(tài)題解析下中的數(shù)字前端開發(fā)筆記本過目不忘正則表達(dá)式聊一聊前端存儲那些事兒一鍵分享到各種寫給剛?cè)腴T的前端工程師的前后端交互指南物聯(lián)網(wǎng)世界的 更多資源請Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://github.com/jsfr...
摘要:技術(shù)之類加載機制掘金類加載機制是語言的一大亮點,使得類可以被動態(tài)加載到虛擬機中。玩轉(zhuǎn)仿探探卡片式滑動效果掘金講起本篇博客的歷史起源,估計有一段歷史了。 Java 技術(shù)之類加載機制 - Android - 掘金類加載機制是 Java 語言的一大亮點,使得 Java 類可以被動態(tài)加載到 Java 虛擬機中。 這次我們拋開術(shù)語和概念,從例子入手,由淺入深地講解 Java 的類加載機制。 本文...
閱讀 3098·2021-11-22 09:34
閱讀 601·2021-11-22 09:34
閱讀 2446·2021-10-08 10:18
閱讀 3383·2021-09-22 15:57
閱讀 2595·2021-09-22 15:25
閱讀 2411·2019-08-30 15:54
閱讀 2118·2019-08-30 15:44
閱讀 1805·2019-08-29 11:18