如何從零構(gòu)建實時的個性化推薦系統(tǒng)?
這些知名公司使用推薦提供情境化的、有相關(guān)性的用戶體驗,以提高轉(zhuǎn)化率和用戶滿意度。這些建議原來一般由每天晚上、每周或每月生成新推薦的批處理作業(yè)計算提供。
然而對于某些類型的推薦,響應(yīng)時間有必要比批量處理作業(yè)所需的時間更短,比如為消費者提供基于地理位置的推薦。比如電影推薦系統(tǒng),若用戶先前看過動 作片,但現(xiàn)在要找一部喜劇片,批量推薦很可能會給出更多動作片,而不是最相關(guān)的喜劇片。本文將會介紹如何使用Kiji框架,它是一個用來構(gòu)建大數(shù)據(jù)應(yīng)用和 實時推薦系統(tǒng)的開源框架。
Kiji,以實體為中心數(shù)據(jù)和360度視角
要構(gòu)建實時推薦系統(tǒng),首先需要一個能存儲360視角客戶的系統(tǒng)。此外,我們需要具備迅速獲取與指定用戶相關(guān)數(shù)據(jù)的能力,以便在用戶與網(wǎng)站和移動應(yīng)用交互時做出推薦。 Kiji是一個構(gòu)建實時應(yīng)用的模塊化開源框架,它收集,存儲和分析這類數(shù)據(jù)。
一般情況下,一個360度視圖所需的數(shù)據(jù)可以被稱為以實體為中心的數(shù)據(jù)。一個實體可以是任意數(shù)量的東西,比如客戶、用戶、帳戶,或者POS系統(tǒng)或移動設(shè)備之類更抽象的東西。
一個以實體為中心的存儲系統(tǒng)要能在一行數(shù)據(jù)中存儲與某個特定實體有關(guān)的一切信息。這對傳統(tǒng)的關(guān)系型數(shù)據(jù)庫來說是個挑戰(zhàn),因為這些信息可能既有狀態(tài)型 數(shù)據(jù)(如姓名,電子郵件地址等)又有事件流(如點擊)。傳統(tǒng)的系統(tǒng)需要把這些數(shù)據(jù)存放在多張表中,處理時再把這些表聯(lián)接起來,這使得它很難做到實時處理。 為了解決這個問題,Kiji用了Apache HBase,它在四個維度 – 行、列族、列標識和時間戳-存儲數(shù)據(jù)。借助時間戳維度和HBase存儲多個版本Cell的能力,Kiji能夠存儲有更多狀態(tài)的緩慢變化的事件流數(shù)據(jù)。

開發(fā)用在實時中的模型
Kiji為開發(fā)模型提供了兩套API,Java和Scala,兩套API都支持批量和實時組件。如此劃分的目的是將模型執(zhí)行劃分為不同階段。批量階 段是訓(xùn)練階段,是一個典型的學(xué)習(xí)過程,在該過程中,將使用完整的數(shù)據(jù)集來訓(xùn)練模型。該階段的輸出可能是線性分類器的參數(shù),或者聚類算法的群集位置,或在協(xié) 同過濾系統(tǒng)中相互關(guān)聯(lián)條目的相似性矩陣。實時階段被稱為評分階段,取得經(jīng)過訓(xùn)練的模型,并將它與實體數(shù)據(jù)相結(jié)合產(chǎn)生衍生信息。關(guān)鍵是這些衍生數(shù)據(jù)被當(dāng)作一 等公民,也就是說它可以存回到實體所在的行中,用于推薦,或作為后續(xù)計算的輸入。
Java API被稱為KijiMR, 而Scala API構(gòu)成了KijiExpress工具的核心。 KijiExpress利用Scalding庫提供API來構(gòu)建復(fù)雜的MapReduce工作流,同時避免了大量Java冗余代碼,以及串聯(lián) MapReduce作業(yè)所必需的任務(wù)調(diào)度和協(xié)作。
個體與總體
之所以要劃分出批量訓(xùn)練和實時評分兩個階段,是因為Kiji觀察到總體趨勢變化緩慢,而個體趨勢的變化迅速。
比如一個包含上千萬次購買記錄的用戶總體數(shù)據(jù)集。多一次購買不太可能對總體趨勢的好惡造成重大影響。但對于一個只有10次購買記錄的特定用戶而言, 第11次購買將對系統(tǒng)判斷用戶興趣產(chǎn)生巨大影響。鑒于這種主張,應(yīng)用程序只需在收集到足以影響總體趨勢的數(shù)據(jù)時再重新訓(xùn)練它的模型。但對于特定用戶而言, 我們可以通過實時響應(yīng)用戶的行為來改善推薦的相關(guān)性。
實時給模型評分
為了做到實時評分,KijiScoring模塊提供了一個惰性計算系統(tǒng),應(yīng)用程序可以只為經(jīng)常與其交互的活躍用戶生成***推薦。通過惰性計 算,Kiji應(yīng)用程序不必為那些不經(jīng)常光顧或再沒回來過的用戶生成推薦。這還有些額外的好處,Kiji可以在推薦時考慮像移動設(shè)備的位置之類的情境信息。
KijiScoring的主要組件叫Freshener。Freshener實際上是另外兩個Kiji組件的組 合:ScoringFunctions和FreshnessPolicies。正如前面提到的,一個模型包括訓(xùn)練和評分兩個階段。 ScoringFunction是一段代碼,描述了如何把經(jīng)過訓(xùn)練的模型和單一實體的數(shù)據(jù)組合起來產(chǎn)生一個分數(shù)或建議。FreshnessPolicy定 義數(shù)據(jù)變得陳舊或過時的時間。比如說,普通的FreshnessPolicy會指出超過一個小時后數(shù)據(jù)就過期了。更復(fù)雜的策略可能會在實體經(jīng)歷過一定次數(shù) 的事件后將其標記為過期,比如點擊或產(chǎn)品訪問等事件。***,ScoringFunction和FreshnessPolicy被附著在Kiji表中特定的 列上,在必要時被觸發(fā)來刷新數(shù)據(jù)。

一個典型的Kiji應(yīng)用程序?qū)ㄒ欢〝?shù)量的KijiScoring服務(wù)器,它們是可以向外擴展的無狀態(tài)Java進程,并能夠運行使用單一實體的數(shù) 據(jù)作為輸入的ScoringFunction。Kiji應(yīng)用程序通過KijiScoring服務(wù)器過濾客戶端請求,由它決定數(shù)據(jù)是否是***的。若有必要, 它會在把所有推薦傳回客戶端之前運行ScoringFunction進行刷新,并將重算后的數(shù)據(jù)寫到HBase中,以備后用。
將模型部署到生產(chǎn)系統(tǒng)中
能夠輕松迭代其底層的預(yù)測模型是實時推薦系統(tǒng)的一個重要目標,避免因為要將新的或改進過的模型部署到生產(chǎn)環(huán)境而停掉應(yīng)用程序。Kiji為此提供了 Kiji模型庫,它結(jié)合了描述模型以及用來訓(xùn)練模型和給模型評分的代碼如何執(zhí)行的元數(shù)據(jù)。KijiScoring服務(wù)器需要知道什么樣的列訪問會觸發(fā)刷 新,要用的FreshnessPolicy,以及將在用戶數(shù)據(jù)上執(zhí)行的ScoringFunction,以及所有經(jīng)過訓(xùn)練的模型的位置,或給模型評分所必 需的外部數(shù)據(jù)。元數(shù)據(jù)也存在一個Kiji系統(tǒng)表中,只是另一種***層的HBase表。此外,模型庫在受管的Maven庫中為已注冊的模型存儲代碼工件。 KijiScoring服務(wù)器為新登記或未登記模型定期輪詢模型庫,按需加載或卸載代碼。
整合到一起
使用協(xié)同過濾是一種非常常用的推薦提供方式。協(xié)同過濾算法通常會建立一個大型的相似矩陣,用來存放一個產(chǎn)品跟產(chǎn)品目錄中其它產(chǎn)品的關(guān)聯(lián)信息。矩陣中的每一行代表一個產(chǎn)品Pi,每一列代表另一種產(chǎn)品Pj。(Pi,Pj)中的值就是兩個產(chǎn)品之間的相似度。


既然我們在評分階段之前已經(jīng)做了很多繁重的工作,那么評分自然成了一種相當(dāng)簡單的操作。如果我們想基于被查看的條目展示推薦信息,一個通用的評分函數(shù)只是從產(chǎn)品表中查找相關(guān)產(chǎn)品,并顯示它們。
將該過程再推進一點并對結(jié)果做個性化處理是一個相對簡單的任務(wù)。在個性化系統(tǒng)中,評分函數(shù)將會取得用戶最近對產(chǎn)品的評級,并使用 KeyValueStore API查找與用戶評價過的產(chǎn)品相似的產(chǎn)品。結(jié)合評級和存儲在產(chǎn)品表中的產(chǎn)品相似度,應(yīng)用程序可以預(yù)測用戶給相關(guān)條目下的評級,并將預(yù)測評級***的產(chǎn)品推薦 給用戶。通過限制所用評級和所有已評級的相似產(chǎn)品的數(shù)量,系統(tǒng)在用戶與應(yīng)用程序進行交互時可以很輕松地處理上述操作。

結(jié)論
在本文中,我們可以了解到如何用Kiji開發(fā)一個可以實時刷新推薦的推薦系統(tǒng)。利用HBase進行低延遲處理,用Avro存儲復(fù)雜的數(shù)據(jù)類型,使用MapReduce和Scalding處理數(shù)據(jù),應(yīng)用程序能夠在實時情境中給用戶提供相關(guān)推薦。