推薦系統是近些年很是火的技術,不論是電商類軟件仍是新聞類app,都號稱有精準的推薦系統能給你推送你最感興趣的內容。現象級的資訊類app「今日頭條」就得益於此成爲了勢頭很是猛的一款產品。本文就針對推薦系統講述一些相關概念和實踐經驗。算法
首先須要明確的就是推薦系統的目標,通常來講不外乎如下幾個:數據庫
- 用戶滿意性:首當其衝的,推薦系統主要就是爲了知足用戶的需求,所以準確率是評判一個推薦系統好壞的最關鍵指標。
- 多樣性:雖然推薦系統最主要仍是知足用戶的興趣,可是也要兼顧內容的多樣性,對於權重不一樣的興趣都要作到兼顧。
- 新穎性:用戶看到的內容是那些他們以前沒有據說過的物品。簡單的作法就是在推薦列表去掉用戶以前有過行爲的那些內容。
- 驚喜度:和新穎性相似,但新穎性只是用戶沒看到過的可是確實是和他行爲是相關的,而驚喜度是用戶既沒有看過和他以前的行爲也不相關,但用戶看到後的確是喜歡的。
- 實時性:推薦系統要根據用戶的上下文來實時更新推薦內容,用戶的興趣也是隨着時間而改變的,須要實時更新。
- 推薦透明度:對於用戶看到的最終結果,要讓用戶知道推薦此內容的緣由。好比,「買過這本書的人同時也買過」、"你購買過的xx和此商品相似"。
- 覆蓋率:挖掘長尾內容也是推薦系統很重要的目標。所以,推薦的內容覆蓋到的內容越多越好。
基於這些目標,推薦系統包括四種推薦方式:緩存
- 熱門推薦:就是熱門排行榜的概念。這種推薦方式不只僅在IT系統,在日常的生活中也是到處存在的。這應該是效果最好的一種推薦方式,畢竟熱門推薦的物品都是位於曝光量比較高的位置的。
- 人工推薦:人工干預的推薦內容。相比於依賴熱門和算法來進行推薦。一些熱點時事如世界盃、nba總決賽等就須要人工加入推薦列表。另外一方面,熱點新聞帶來的推薦效果也是很高的。
- 相關推薦:相關推薦有點相似於關聯規則的個性化推薦,就是在你閱讀一個內容的時候,會提示你閱讀與此相關的內容。
- 個性化推薦:基於用戶的歷史行爲作出的內容推薦。也是本文主要講述的內容。
其中,前三者是和機器學習沒有任何關係的,但倒是推薦效果最好的三種方式。通常說來,這部份內容應該佔到總的推薦內容的80%左右,另外20%則是對長尾內容的個性化推薦。網絡
個性化推薦系統
個性化推薦是機器學習應用的一個典型場景。在本質上和搜索引擎是同樣的,一樣是爲了解決信息過載的問題。搜索引擎某種意義上也是一個個性化推薦系統,可是其輸入特徵是能夠從搜索關鍵字直接能夠獲得的。而通常的推薦系統,輸入特徵則是須要機器學習才能獲得。架構
個性化推薦系統通常由日誌系統、推薦算法、內容展現UI三部分組成。app
- 日誌系統:這是推薦系統的輸入源,是一個推薦系統全部信息的源頭。
- 推薦算法:這是推薦系統的核心,根據輸入數據得出最終的推薦結果的具體過程就在這裏。
- 內容展現UI:對於推薦結果如何展現,也是一個值得權衡的地方。以更好地知足推薦系統的目標,並能更好的收集用戶的行爲信息等。
其中,個性化推薦中最爲核心的推薦算法,目前比較流行的有如下幾種:框架
- 基於內容的推薦:根據內容自己的屬性(特徵向量)所做的推薦。
- 基於關聯規則的推薦:「啤酒與尿布」的方式,是一種動態的推薦,可以實時對用戶的行爲做出推薦。是基於物品之間的特徵關聯性所作的推薦,在某種狀況下會退化爲物品協同過濾推薦。
- 協同過濾推薦:與基於關聯規則的推薦相比是一種靜態方式的推薦,是根據用戶已有的歷史行爲做分析的基礎上作的推薦。可分爲物品協同過濾、用戶協同過濾、基於模型的協同過濾。其中,基於模型的協同又能夠分爲如下幾種類型:基於距離的協同過濾;基於矩陣分解的協同過濾,即Latent Factor Model(SVD);基於圖模型協同,即Graph,也叫社會網絡圖模型。
個性化推薦系統的典型架構以下圖所示:機器學習
recommend-sys
在線業務系統的日誌接入數據高速公路,再由數據高速公路迅速運轉到離線數據處理平臺和在線流計算平臺;離線數據處理平臺週期性地以批處理方式加工過去一段時間的數據,獲得人羣標籤和其餘模型參數,存放在高速緩存中,供在線業務系統使用,與此同時,在線流計算平臺實時對線上的日誌數據作處理,對離線計算出的數據進行補充、修正等;在線業務系統綜合離線特徵和在線特徵使用必定的邏輯獲得輸出供業務使用,產生的日誌流入數據高速公路。分佈式
基於此框架,個性化推薦系統的典型流程以下所示:性能
recommend
可知,一個推薦系統主要有如下模塊組成:
- 用戶行爲日誌:此部分主要是用戶行爲日誌的存儲,屬於數據統計的一部分, 存儲在hive中。在此不作贅述。
- 數據ETL-1:將用戶日誌轉換爲推薦算法所須要的數據格式。
- 推薦算法:是個性化推薦最主要的部分,包括經過用戶行爲計算相關內容以及推薦結果等。
- 數據ETL-2: 將推薦算法獲得的結果進一步加工爲存儲模塊的輸入數據。
- 用戶畫像存儲:存儲用戶的偏好以及行爲數據,如對內容關鍵字的偏好、點擊過哪些內容等。
- 推薦結果存儲:存儲各類推薦算法產生的推薦結果,能夠分爲兩部分:{用戶 : itemList}推薦結果,爲用戶推薦的內容列表;{item : itemList}推薦結果,與item相關的內容列表。
- 服務調用模塊:整合推薦結構,對外提供提供推薦的調用接口。
數據ETL-1
對原始的用戶行爲等數據進行清洗、加工,如字段、屬性、格式化等,做爲下一步推薦算法的輸入。
推薦算法
對於個性化推薦系統來講,推薦算法應該是其最核心的部分。目前有不少流行的算法,好比:
- 基於內容和用戶畫像的推薦:此種算法,可見以前的一篇文章:www.rowkey.me/blog/2016/0…。
- 基於矩陣分解的推薦: 基於SVD/ALS算法對用戶進行內容推薦。相比起SVD,ALS更加適合解決稀疏矩陣的問題。Spark mlib中已經集成了對als算法的實現,須要作的就是在etl-1中把數據轉換爲als須要的數據格式以及調整als算法的各類參數。這裏有一篇文章比較具體地描述瞭如何使用spark來作基於ALS的推薦:colobu.com/2015/11/30/…。
- 用戶&物品協同過濾推薦:包括UserBased CF和ItemBased CF。對於這二者,須要根據業務的不一樣來選擇不一樣的算法。當用戶很是多的時候,考慮到維護用戶矩陣的成本,通常是不推薦選擇用戶協同過濾的,而對於候選item不少的時候,則不推薦使用物品協同過濾。
推薦算法的輸出結果通常是一個用戶對應一個item列表或者是一個item對應一個item列表。此部分主要考慮的是算法的時間複雜度,不論是哪種算法,一旦用戶或者內容數據上了百萬級別,都須要經過分佈式計算如MapReduce、Spark等來進行解決。
推薦算法的基本流程以下圖所示:
數據ETL-2
對推薦算法產生的結果進行清洗、格式化等,做爲下一步存儲模塊的輸入。
用戶畫像存儲
存儲用戶的偏好以及行爲數據等信息。對於偏好,採用標籤量化來表示,是一種隨着時間衰減的值。對於用戶畫像,是批量寫入、實時讀取,因此存儲要着重考慮讀的性能。能夠選擇使用Redis集羣做爲技術方案,可以最大知足讀的性能,缺點是Redis的成本昂貴且不支持auto index。也可以使用Hbase做爲存儲,使用ElasricSearch構建二級索引,以應對根據多種維度彙集用戶的需求(好比過濾某一個標籤下的全部用戶)。
推薦結果存儲
對各類推薦算法計算出的推薦結果的存儲。存儲空間要求大,格式複雜。對於存儲的容量和讀寫性能要求都比較高。能夠選擇使用Redis集羣做爲此部分的存儲方案。
服務調用
整合用戶畫像和推薦結果兩部分數據,向外提供推薦調用的接口。主要是數據庫IO調用開銷。
- 根據用戶id,獲取推薦的item列表。
- 根據item,獲取相關聯的item列表。
- 根據用戶id, 獲取用戶畫像。
該模塊須要採起必定的策略聚合多種推薦算法的推薦結果,直接面向業務。策略因爲會隨着面向的業務不一樣而不一樣,須要可配置化。同時也提供對外暴露用戶畫像的接口,使得業務方可使用用戶畫像作針對性的處理。能夠採用RPC機制對外暴露服務接口。
須要考慮的問題
對於一個推薦系統,結合其實現目標,還有一些須要注重考慮的問題。
實時性問題
因爲計算用戶、item矩陣或者進行矩陣分解是須要離線進行且比較耗時,所以協同的推薦算法是很難達到實時性的。實時部分的推薦主要依靠基於用戶畫像的推薦來進行。最終的推薦列表是根據必定的策略對這兩部分進行聚合的結果。
時效性內容問題
時效性內容指的是那些與時間強相關的內容,好比新聞、時事等。若是一條10天前xx球員得到冠軍的新聞如今被推薦了出來,可想用戶確定是莫名其妙或者是很失望的。所以,對於時效性內容,須要與普通的待推薦的內容區分開,作單獨的推薦或者不走個性化推薦。
冷啓動問題
無論使用何種推薦算法,都會面臨冷啓動問題:當用戶是新用戶,如何給用戶推薦item呢?當內容是新內容,如何推薦給用戶?
- 對於新用戶,能夠採起的一種策略就是採用熱門推薦或者人工推薦,把絕大多人關心的內容推薦出來。
- 對於內容,能夠將內容分爲新內容池和待推薦內容池。新內容產生時,首先進入新內容池。每次推薦的時候,先重新內容池作候選推薦,並給此內容的傳播度+1,直到其傳播度大於一個閾值的時候,將其移至待推薦內容池。這樣既能夠解決新內容的冷啓動問題也在必定程度上能夠保證新內容的曝光量。
多樣性問題
在基於用戶畫像的推薦算法中,取出用戶的多個標籤,而後根據相關度從不一樣的標籤中取不一樣數量的內容,這樣既兼顧了用戶的多種興趣也可以在必定程度上解決多樣性的問題。
如:用戶具備tag:A B C D,相關度爲wA wB wC wD,Total推薦爲總共須要推薦的條數,那麼
RecommendList(u) = A[Total推薦 * wA] + B[Total推薦 * wB] + C[Total推薦 * wC] + D[Total推薦 * wD]複製代碼
內容質量
不論是熱門推薦、人工推薦仍是取某一標籤下的內容列表都牽扯到的一個問題就是:如何給內容排序?
當用戶對內容的喜愛不同,能夠按照興趣度來排序;但當沒法區分興趣度的時候(好比:用戶是新用戶;內容都是新內容;用戶對於某一標籤下的內容興趣度同樣),可使用內容質量來作排序。click/pv是一種評判內容質量的方式。此外,使用卷積神經網絡相關算法也能夠構建內容質量模型。
驚喜問題
推薦系統的驚喜目標一直是一個難題,被稱做EE(Exploit & Explore)問題,bandit算法是解決這個問題的一個派系,就是估計置信區間的作法,而後按照置信區間的上界來進行推薦,以UCB、LinUCB爲表明的。簡單點說就是先不考慮你喜不喜歡就把質量高的內容推薦給你,後面根據用戶的行爲反饋對推薦內容做調整。具體的能夠參見此篇文章:推薦系統的苟且和遠方。
總結
借用推薦系統的那點事一文的幾句話作爲結語:
- 實力派的【算法工程師】每每都是ABC[always be coding],這樣的算法工程師才能根據實際問題創建模型或者創建規則庫,是真正能解決問題的人。每每是一些有研究背景,經驗豐富的研究員,更加劇視工程,由於工程架構上一些恰當合理的設計,效果每每就能遠遠高過於模型算法優化。
- 學院派的【算法工程師】每每是爲了算法而算法,而不是爲了解決推薦系統的問題去找最適合算法。這也是爲何大公司常常招了一些博士畢業的算法工程師後,不是研究算法而是讓他們成天在那看數據報表?【由於發現算法沒啥好研究,只能讓他們在那看看報表找找規律了。】
- 【幾乎全部所謂的智能推薦算法都是花拳繡腿】
- 當一個作推薦系統的部門開始重視【數據清理,數據標柱,效果評測,數據統計,數據分析】這些所謂的髒活累活,這樣的推薦系統纔會有救。
以上是推薦系統實踐的一些經驗
閱讀原文