當前位置:
首頁 > 科技 > 推薦系統的工程實現

推薦系統的工程實現

作者 | gongyouliu

來源 | 大數據工程師

01 寫在前面

本篇文章作者會結合多年推薦系統開發的實踐經驗粗略介紹推薦系統的工程實現,簡要說明要將推薦系統很好地落地到產品中需要考慮哪些問題及相應的思路、策略和建議,其中有大量關於設計哲學的思考,希望對從事推薦演算法工作或準備入行推薦系統的讀者有所幫助。

本篇文章主要從整體上來介紹推薦系統工程實現,以後發布的系列文章會逐步介紹工程實現的各個細節實現原理與策略。為了描述方便,本文主要基於視頻推薦來講解,作者這幾年也一直在從事視頻推薦系統開發的工作,其他行業的推薦系統工程實現思路類似。

02 推薦系統與大數據

推薦系統是幫助人們解決信息獲取問題的有效工具,對互聯網產品而也用戶數和信息總量通常都是巨大的,每天收集到的用戶在產品上的交互行為也是海量的,這些大量的數據收集處理就涉及到大數據相關技術,所以推薦系統與大數據有天然的聯繫,要落地推薦系統往往需要企業具備一套完善的大數據分析平台。

推薦系統與大數據平台的依賴關係如下圖。大數據平台包含數據中心和計算中心兩大抽象,數據中心為推薦系統提供數據存儲,包括訓練推薦模型需要的數據,依賴的其他數據,以及推薦結果,而計算中心提供算力支持,支撐數據預處理、模型訓練、模型推斷(即基於學習到的模型,為每個用戶推薦)等。

推薦系統在整個大數據平台的定位

大數據與人工智慧具有千絲萬縷的關係,互聯網公司一般會構建自己的大數據與人工智慧團隊,構建大數據基礎平台,基於大數據平台構建上層業務,包括商業智能(BI),推薦系統及其他人工智慧業務,下圖是典型的基於開源技術的視頻互聯網公司大數據與人工智慧業務及相關的底層大數據支撐技術。

大數據支撐下的人工智慧技術體系(DS:數據源,DC:大數據中心,BIZ:上層業務)

在產品中整合推薦系統是一個系統工程,怎麼讓推薦系統在產品中產生價值,真正幫助到用戶,提升用戶體驗的同時為平台方提供更大的收益是一件有挑戰的事情,整個推薦系統的業務流可以用下圖來說明,它是一個不斷迭代優化的過程,是一個閉環系統。

有了上面這些介紹,相信讀者對大數據與推薦系統的關係有了一個比較清楚的了解,下面會著重講解推薦系統工程實現相關的知識。

03 推薦系統業務流及核心模塊

先介紹一下構建一套完善的推薦系統涉及到的主要業務流程及核心模塊,具體流程如下圖,下面分別介紹各個模塊:

數據收集模塊

構建推薦模型需要收集很多數據,包括用戶行為數據,用戶相關數據及推薦「標的物」相關數據。如果將推薦系統比喻為廚師做菜,那麼這些數據是構建推薦演算法模型的原材料。巧婦難為無米之炊,要構建好的推薦演算法收集到足夠多的有價值的數據是非常關鍵和重要的。

ETL模塊

收集到的原始數據一般是非結構化的,ETL模塊的主要目的是從收集到的原始數據中提取關鍵欄位(拿視頻行業來說,用戶id,時間,播放的節目,播放時長,播放路徑等都是關鍵欄位),將數據轉化為結構化的數據存儲到數據倉庫中。同時根據一定的規則或策略過濾掉臟數據,保證數據質量的高標準。在互聯網公司中,用戶行為數據跟用戶規模呈正比,所以當用戶規模很大時數據量非常大,一般採用HDFS、Hive、HBase等大數據分散式存儲系統來存儲數據。

用戶相關數據及推薦「標的物」相關數據一般是結構化的數據,一般是通過後台管理模塊將數據存儲到MySQL、ProgreSQL等關係型資料庫中。

特徵工程模塊

推薦系統採用各種機器學習演算法來學慣用戶偏好,並基於用戶偏好來為用戶推薦「標的物」,而這些推薦演算法用於訓練的數據是可以「被數學所描述」的,一般是向量的形式,其中向量的每一個分量/維度就是一個特徵,所以特徵工程的目的就是將推薦演算法需要的,以及上述ETL後的數據轉換為推薦演算法可以學習的特徵。

當然,不是所有推薦演算法都需要特徵工程,比如,如果要做排行榜相關的熱門推薦,只需要對數據做統計排序處理就可以了。最常用的基於物品的推薦和基於用戶的推薦也只用到用戶id,標的物id,用戶對標的物的評分三個維度,也談不上特徵工程。像logistic回歸等複雜一些的機器學習演算法需要做特徵工程,一般基於模型的推薦演算法都需要特徵工程。

特徵工程是一個比較複雜的過程,要做好需要很多技巧、智慧、行業知識、經驗等,在這篇文章中作者不作詳細介紹。

推薦演算法模塊

推薦演算法模塊是整個推薦系統的核心之一,該模塊的核心是根據具體業務及可利用的所有數據設計一套精準、易於工程實現、可以處理大規模數據的(分散式)機器學習演算法,進而可以預測用戶的興趣偏好。這裡一般涉及到模型訓練、預測兩個核心操作。下面用一個圖簡單描述這兩個過程,這也是機器學習的通用流程。

好的推薦工程實現,希望盡量將這兩個過程解耦合,做到通用,方便用到各種推薦業務中,後面在推薦系統架構設計一節中會詳細講解具體的設計思路和哲學。

推薦結果存儲模塊

作者在最開始做推薦系統時由於沒有經驗,開始將推薦結果存儲在Mysql中,當時遇到最大的問題是每天更新用戶的推薦時,需要先找到用戶存儲的位置,再做替換,操作複雜,並且當用戶規模大時,高並發讀寫,大數據量存儲,Mysql也扛不住,現在最好的方式是採用CouchBase,Redis等可以橫向擴容的資料庫,可以完全避開MySQL的缺點。

在計算機工程中有「空間換時間」的說法,對於推薦系統來說,就是先計算好每個用戶的推薦,將推薦結果存儲下來,通過預先將推薦結果存下來,可以更快的為用戶提供推薦服務,提升用戶體驗。由於推薦系統會為每個用戶生成推薦結果,並且每天都會(基本全量)更新用戶的推薦結果,一般採用NoSql資料庫來存儲,並且要求資料庫可拓展,高可用,支持大規模並發讀寫。

推薦結果一般不是直接在模型推斷階段直接寫入推薦存儲資料庫,較好的方式是通過一個數據管道(如kafka)來解耦,讓整個系統更加模塊化,易於維護拓展。

Web服務模塊

該模塊是推薦系統直接服務用戶的模塊,該模塊的主要作用是當用戶在UI上觸達推薦系統時,觸發推薦介面,為用戶提供個性化推薦,該模塊的穩定性、響應時長直接影響到用戶體驗。跟上面的推薦存儲模塊類似,Web服務模塊也需要支持高並發訪問、水平可拓展、亞秒級(一般200ms之內)響應延遲。

下圖是作者公司相似影片推薦演算法的一個簡化版業務流向圖,供大家與上面的模塊對照參考:

相似影片業務流

04 推薦系統支撐模塊

推薦系統想要很好的穩定的發揮價值,需要一些支撐業務來輔助,這些支撐業務雖然不是推薦系統的核心模塊,但卻是推薦業務穩定運行必不可少的部分,主要包括如下4大支撐模塊,下面分別簡述各個模塊的作用和價值。

推薦系統核心支撐模塊

評估模塊

推薦評估模塊的主要作用是評估整個推薦系統的質量及價值產出。一般來說可以從兩個維度來評估。

離線評估:主要是評估訓練好的推薦模型的「質量」,模型在上線服務之前需要評估該模型的準確度,一般是將訓練數據分為訓練集和測試集,訓練集用於訓練模型,而測試集用來評估模型的預測誤差。

在線評估:模型上線提供推薦服務過程中來評估一些真實的轉化指標,比如轉化率、購買率、點擊率、播放時長等。線上評估一般會結合AB測試,先放一部分量,如果效果達到期望再逐步拓展到所有用戶,避免模型線上效果不好嚴重影響用戶體驗和收益指標等。

調度模塊

一個推薦業務要產生價值,所有依賴的任務都要正常運行。推薦業務可以抽象為有向無環圖(第六節推薦系統架構設計會講到將推薦業務抽象為有向無環圖),因此需要按照該有向圖的依賴關係依次執行每個任務,這些任務的依賴關係就需要藉助合適的調度系統(比如Azkaban)來實現,早期我們採用Crontab來調度,當任務量多的時候就不那麼方便了,Crontab也無法很好解決任務依賴關係。

監控模塊

監控模塊解決的是當推薦業務(依賴的)任務由於各種原因調度失敗時可以及時告警,通過郵件或者簡訊通知運維或者業務的維護者,及時發現問題,或者可以在後台自動拉起服務。同時可以對服務的各種其他狀態做監控,比如文件大小、狀態變數的值、日期時間等與業務正常執行相關的狀態變數,不正常時及時發現問題。

審查模塊

審查模塊是對推薦系統結果數據格式的正確性、有效性進行檢查,避免錯誤產生,一般的處理策略是根據業務定義一些審查用例(類似測試用例),在推薦任務執行前或者執行階段對運算過程做check,發現問題及時告警。舉兩個例子,如果你的DAU是100w,每天大約要為這麼多用戶生成個性化推薦結果,但是由於一些開發錯誤,只計算了20w用戶的個性化推薦,從監控是無法發現問題的,如果增加推薦的用戶數量跟DAU的比例控制在1附近這個審查項,就可以避免出現問題;在推薦結果插入資料庫過程中,開發人員升級了新的演算法,不小心將數據格式寫錯(如Json格式不合法),如果不加審查,會導致最終插入的數據格式錯誤,導致介面返回錯誤或者掛掉,對用戶體驗有極大負面影響。

05 推薦系統範式

推薦系統的目的是為用戶推薦可能喜歡的標的物,這個過程涉及到用戶、標的物兩個重要要素,我們可以根據這兩個要素的不同組合產生不同的推薦形態,即所謂的不同「範式(paradigm)」(數學專業的同學不難理解範式,如果不好理解可以將範式看成具備某種相似性質的對象的集合),根據我自己構建推薦系統的經驗可以將推薦系統總結為如下5種範式,這5中範式可以應用到產品的各種推薦場景中,後面會拿視頻APP舉例說明具體的應用場景。

範式1:完全個性化範式:為每個用戶提供個性化的內容,每個用戶推薦結果都不同;

常見的猜你喜歡就是這類推薦,可以用於進入首頁的綜合類猜你喜歡推薦,進入各個頻道(如電影)頁的猜你喜歡推薦。下圖是電視貓首頁興趣推薦,就是為每個用戶提供不一樣的個性化推薦;

範式2:群組個性化範式:首先將用戶分組(根據用戶的興趣,將興趣相似的歸為一組),每組用戶提供一個個性化的推薦列表,同一組的用戶推薦列表一樣,不同組的用戶推薦列表不一樣;

這裡舉一個在作者公司利用範式2做推薦的例子,我們在頻道頁三級列表中,會根據用戶的興趣對列表做個性化重排序,讓與用戶更匹配的節目放到前面,提升節目轉化,但是在實現時,為了節省存儲空間,先對用戶聚類,同一類用戶興趣相似,對這一類用戶,列表的排序是一樣的,但是不同類的用戶的列表是完全不一樣的。見下圖的戰爭風雲tab,右邊展示的節目集合總量不變,只是在不同組的用戶看到的排序不一樣,排序是根據與用戶的興趣匹配度高低來降序排列的。

範式3:非個性化範式:為所有用戶提供完全一樣的推薦;

比如各類排行榜業務,既可以作為首頁上的一個獨立的推薦模塊,方便用戶發現新熱內容,也可以作為猜你喜歡推薦新用戶冷啟動的默認推薦,下圖是搜索模塊當用戶未輸入搜索關鍵詞時給出的熱門內容,也是採用該範式的例子;

範式4:標的物關聯標的物範式:為每個標的物關聯一組標的物,作為用戶在訪問標的物詳情頁時的推薦,每個用戶都是相同的標的物;

當用戶瀏覽一個電影時,可以通過關聯相似的電影,為用戶提供更多的選擇空間(下圖就是電視貓電影詳情頁關聯的相似影片);還可以當用戶播放一個節目退出時,推薦用戶可能還喜歡的其他節目;針對短視頻,可以將相似節目做成連播推薦列表,用戶播放當前節目直接連播相似節目,提升節目分發和用戶體驗;

範式5:笛卡爾積範式:每個用戶跟每個標的物的組合產生的推薦都不相同,不同用戶在同一個視頻的詳情頁看到的推薦結果都不一樣;

該範式跟4類似,只不過不同用戶在同一個節目得到的關聯節目不一樣,會結合用戶的興趣,給出更匹配用戶興趣的關聯節目;

由於每個用戶跟每個標的物的組合推薦結果都不一樣,往往用戶數和標的物的數量都是巨大的,沒有足夠的資源事先將所有的組合的推薦結果先計算存儲下來,一般是在用戶觸發推薦時實時計算推薦結果呈現給用戶,計算過程也要盡量簡單,在亞秒級就可以算完,比如利用用戶的播放歷史,過濾掉用戶已經看過的關聯節目;

下面給一個簡單的圖示來說明這5種範式,讓讀者有一個直觀形象的理解。

推薦演算法的5種範式

總之,推薦系統不是孤立存在的對象,它一定是要整合到具體的業務中,在合適的產品交互流程中觸達用戶,通過用戶觸發推薦行為。所以,推薦系統要應用到產品中需要嵌入到用戶使用產品的各個流程(頁面)中。當用戶訪問首頁時,可以通過綜合推薦(範式1)來給用戶提供個性化推薦內容,當用戶訪問詳情頁,可以通過相似影片(範式4)提供相似標的物推薦,當用戶進入搜索頁尚未輸入搜索內容時,可以通過熱門推薦給用戶推送新熱節目(範式3)。這樣處處都有推薦,才會使產品顯得更加智能。所有這些產品形態基本都可以用上面介紹的5種範式來概括。

06 推薦系統架構設計

作者在早期構建推薦系統時由於經驗不足,而業務又比較多,當時的策略是每個演算法工程師負責幾個推薦業務(一個推薦業務對應一個推薦產品形態),由於每個人只對自己的業務負責,所以開發基本是獨立的,每個人只關注自己的演算法實現,雖然用到的演算法是一樣的,但前期在開發過程中沒有將通用的模塊抽象出來,每個開發人員從ETL、演算法訓練、預測到插入資料庫都是獨立的,並且每個人在實現過程中整合了自己的一些優化邏輯,一竿子插到底,導致資源(計算資源,存儲資源,人力資源)利用率不高,開發效率低下。經過幾年的摸索,作者在團隊內部構建了一套通用的演算法組件Doraemon框架(就像機器貓的小口袋,有很多工具供大家方便構建推薦業務),盡量做到資源的節省,大大提升了開發效率。開發過程的蛻變,可以用下面的圖示簡單說明,從中讀者也可以對Doraemon架構落地前後的推薦業務開發變化有個大致的了解。

Doraemon框架前後開發方式對比

作者構建Doraemon框架的初衷是希望構建推薦業務就像搭積木一樣(見下圖),可以快速構建一套演算法體系,快速上線業務。演算法或者處理邏輯就像一塊一塊的積木,而演算法依賴的數據(及數據結構)就是不同積木之間是否可以銜接的「介面」。

構建推薦業務就像搭積木一樣簡單(圖片來源於網路)

本著上面樸素的思想,下面作者詳細說說構建這套體系的思路和策略。

為了支撐更多類型的推薦業務,減少系統的耦合,便於發現和追蹤問題,節省人力成本,方便演算法快速上線和迭代,需要設計比較好的推薦系統架構,而好的推薦系統架構應該具備6大原則:通用性,模塊化,組件化,一致性,可拓展性,抽象性。下面分別對上述6大原則做簡要說明,闡述清楚它們的目標和意義。

通用性:所謂通用,就是該架構具備包容的能力,業務上的任何推薦產品都可以用這一套架構來涵蓋和實現。

模塊化:模塊化的目的在於將一個業務按照其功能做拆分,分成相互獨立的模塊,以便於每個模塊只包含與其功能相關的內容,模塊之間通過一致性的協議調用。將一個大的系統模塊化之後,每個模塊都可以被高度復用。模塊化的目的是為了重用,模塊化後可以方便重複使用和插撥到不同平台,不同推薦業務邏輯中。

組件化:組件化就是基於可重用的目的,將一個大的軟體系統拆分成多個獨立的組件,主要目的就是減少耦合。一個獨立的組件可以是一個軟體包、web服務、web資源或者是封裝了一些函數的模塊。這樣,獨立出來的組件可以單獨維護和升級而不會影響到其他的組件。組件化的目的是為了解耦,把系統拆分成多個組件,分離組件邊界和責任,便於獨立升級和維護,組件可插拔,通過組件的拼接和增減提供更豐富的能力。

組件化和模塊化比較類似,目標分別是為了更好的解耦和重用,就像搭積木一樣構建複雜系統。

一致性:指模塊的數據輸入輸出採用統一的數據交互協議,做到整個系統一致。

可拓展性:系統具備支撐大數據量,大並發的能力,並且容易在該系統中增添新的模塊,提供更豐富的能力,讓業務更加完備自治。

抽象性:將相似的操作和流程抽象為統一的操作,主要目的是簡化系統設計,讓系統更加簡潔通用。針對推薦系統採用數學上的概念抽象如下:

操作/演算法抽象:我們先對數據處理或者演算法做一個抽象,將利用輸入數據通過「操作」得到輸出的的過程抽象為「運算元」,按照這個抽象,ETL、機器學習訓練模型、機器學習推斷都是運算元。其中輸入輸出可以是數據或者模型。

演算法或者操作的運算元抽象

業務抽象:任何一個推薦業務可以抽象為由數據/模型為節點,運算元為邊的「有向無環圖」。下圖是深度學習的演算法處理流程,整個演算法實現就是一個有向無環圖。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI科技大本營 的精彩文章:

新鮮開源:基於TF2.0的深度強化學習平台
拯救老電影——詳解愛奇藝ZoomAI視頻增強技術的應用

TAG:AI科技大本營 |