我理解的推薦系統本質是一種排序方式。排序的規則是按照我們預測的用戶喜好程度的一個排序的列表,而如何定義用戶的喜好程度是推薦系統要解決的核心問題。機器學習的算法只是推薦系統的一部分。構建一個完整的推薦系統將會使用到多個大數據的組件,從而在實際的項目中實現數據的存儲,計算,模型更新。
一、什么是推薦系統
舉個例子,我使用讀書,如果是去傳統的圖書館,面對一個個的書架我會迷茫拿出哪一本來閱讀。但是現在登錄個閱讀軟件或者使用kindle,他們會給出一些閱讀建議。
這些建議的基礎就是推薦系統,底層通常是使用一些機器學習的方法提供推薦結果。推薦系統通過記錄我們不斷的閱讀,收藏等操作,預測我們的需求或者喜好給予合適的建議。
二、推薦系統總覽
推薦系統是一整個技術架構,並非僅僅是花哨的機器學習算法。推薦系統根據不同的業務會有不同的技術架構,但大多數的推薦系統一般遵循以下的技術架構。后邊將會從宏觀上介紹着各個組成部分的作用。

當下深度學習的流行,使得計算機視覺和自然語言處理技術更加成熟,因此在推薦系統中使用深度學習技術會有較好的效果。本文也將介紹除了使用協同過濾構建傳統的推薦系統,也會介紹如何整合目前比較流行的深度學習技術來獲得更好的推薦效果。
三、機器學習
機器學習的組件需要完成推薦模型的訓練。選擇適用的算法從歷史數據學習並生成可以部署的推薦模型,調用推薦模型從而向用戶提供個性化建議。值得注意的是,推薦算法的輸出類型將會影響后續對它的調用和存儲,因為用戶通過不斷的使用我們的產品會不斷產生新的行為數據。
理想情況下,我們希望每產生新數據后可以重新優化我們的已有模型,但實際上難以實現,因為訓練模型需要一定的時長。目前在實踐中比較通用的解決方案是使用Lambda體系結構。
Lambda體系結構適用於在線學習也適用於離線學習。在線學習使用的數據是新產生的數據,數據量較小訓練更快可以提供接近實時推薦結果。離線學習使用所有的歷史數據,訓練的頻次較低。
離線訓練
離線訓練是機器學習推薦算法的主要學習機制。此過程通常涉及傳統的機器學習算法,即在訓練集上訓練模型,進行交叉驗證以選擇最佳超參數,並將該模型導出為可供服務層使用的模型。
系統應該實現自動訓練模型和選擇最佳模型。並且能夠按照合適的頻率定時進行訓練。因為離線模型訓練使用所有的歷史數據通常訓練過程需要較長的時間,所以可以使用作業調度來完成,如使用oozie或者自己寫定時啟動訓練程序的腳本。目前常用的方法有使用Spark DStream操作,使用用戶近期產生的新數據與Hadoop文件系統(HDFS)的歷史數據相結合。使用Spark MLlib中交替最小二乘(ALS)算法訓練數據。 
ALS是一種矩陣分解算法,它可以用數字表示每個用戶和每個物品。將用戶和物品在k維空間中表示,在此空間中的距離用來表示用戶的偏好。因此靠近某個用戶的物品可能是該用戶可能感興趣的物品。ALS模型的輸出是每個用戶和每個物品的k維向量,通常存儲為兩個矩陣,一個用於用戶向量一個用於物品向量。
選擇MLlib中的ALS算法只是舉個例子,也可以選擇其他的推薦算法或者自己設計算法,使用ALS的優點是相對比較簡單,易於實現,通用性也較好。
在線訓練

在線訓練的過程是將根據最近產生的數據訓練出來的模型作為數據流更新到系統中,這隱含着兩個需求,一是我們需要在內存中快速更新模型,當新數據到達時可以從中學習新的模型參數。二是我們需要一個支持增量更新的算法。
使用ALS算法利用最小二乘對用戶和物品參數進行近似的在線更新,這種方式可以用來實時合並新數據,具體做法就是我們將當前的用戶和物品矩陣放在內存中,通過SparkStreaming進行實時更新,訓練后對模型進行更新。
在線更新模型可以在一定程度上解決冷啟動問題,當用戶第一次登陸時,我們沒有用戶行為數據,可能會使用一些普適性較好的推薦,然而使用在線更新意味着用戶只要與第一個商品有了行為,就可以立即改善預測模型提供個性化推薦。
四、Web服務
Web服務用於建立用戶和應用程序的交互關系,Web服務常用的可以選擇使用JavaEE,需要滿足能夠向多個用戶提供建議,並應該設有埋點,將新的用戶行為數據采集下來推送到kafka用於在線訓練更新模型。
五、部署
部署推薦模型需要考慮應用程序的時效性要求和數據規模,通常的做法是將ALS矩陣存儲在內存中,使用LSH(局部敏感散列)+KNN(近鄰搜索,可用於快速預測)。通過讀取離線訓練模型並整合在線訓練的模型。

如上圖是整個推薦系統的基本架構。
六、集成深度學習
我們構建一個推薦應用程序,可能會需要使用不同的機器學習算法去試驗,從中選擇最佳的推薦模型,深度學習技術雖然先進,但是使用傳統的算法模型如ALS迭代會更簡單。
更換模型時,如果模型的輸入輸出一致,可以直接替換,在架構中可以直接使用心得深度學習模型替換ALS,對於離線部分,我們可以在集群中配置一個或者多個GPU,使用TensorFlow或者Keras進行離線批量訓練,或者使用基於Spark的深度學習框架如deeplearning4j。並將離線訓練的程序在Spark集群上提交運行,神經網絡默認是使用梯度下降逐步進行訓練,因此在線模型訓練也可以替換,在每個時間間隔內新產生的數據作為小批量的訓練數據,並且可以通過向前和向后傳遞模型來更新模型。這部分不需要GPU加速。

在生產環境構建推薦系統時,最好是通過使用矩陣分解這種簡單模型入手,如果簡單模型達不到好的推薦效果,再考慮轉向使用更復雜的技術,在大多數情況下,不會使用深度學習取代矩陣分解,而是使用深度學習模型與協同過濾方法結合使用構建混合模型。
一個好的推薦系統不僅僅是只需要一個好的推薦算法,而且還需要一個能根據用戶需求隨時調整適應的基礎架構,如果說不能有效的結合生產環境,再復雜再高端的算法也是無用的。我認為建模技術固然重要,但我們首先應該關注的整個系統的基礎架構,隨着業務發展,系統的需求發生變化難以避免。所以推薦系統架構應該支持擴展和修改現有的算法模型,如果說需要更多的個性化推薦,我們可以在不影響基礎架構設計的前提下,增加深度學習模型用於提升推薦效果。
