《推薦系統實踐》算法純享(附代碼鏈接)(二)—— 協同過濾篇

上一部分介紹了《推薦系統實踐》中關於推薦系統常用的一些評測指標,那麼從這一部分開始,將真正進入到推薦算法部分。

這個系列分爲如下幾個部分:

《推薦系統實踐》算法純享(附代碼鏈接)(一)—— 評價指標篇
《推薦系統實踐》算法純享(附代碼鏈接)(二)—— 協同過濾篇
《推薦系統實踐》算法純享(附代碼鏈接)(三)—— 冷啓動篇
《推薦系統實踐》算法純享(附代碼鏈接)(四)—— UGC推薦篇
《推薦系統實踐》算法純享(附代碼鏈接)(五)—— 藉助上下文信息推薦篇
《推薦系統實踐》算法純享(附代碼鏈接)(六)—— 藉助社交網絡推薦篇
《推薦系統實踐》算法純享(附代碼鏈接)(七)—— 評分預測篇

完整代碼鏈接:https://github.com/Magic-Bubble/RecommendSystemPractice

下面將開始本系列的第二部分——協同過濾篇

2 協同過濾

這裏要先聲明一點,僅僅基於用戶行爲數據設計的推薦算法一般稱爲協同過濾算法。

2.1 基於用戶的協同過濾算法

代碼鏈接:https://github.com/Magic-Bubble/RecommendSystemPractice/blob/master/Chapter2/基於用戶的協同過濾算法.ipynb

主要包含兩個步驟:
a. 計算用戶之間的相似度:找到和目標用戶興趣相似的用戶集合。
b. 根據用戶相似度及用戶對物品的評價爲物品打分:找到這個集合中的用戶喜歡的,且目標用戶沒有聽說過的物品推薦給目標用戶。

Step1: 計算用戶相似度

根據協同過濾算法的定義,這裏主要是利用用戶行爲的相似度來計算興趣的相似度。給定用戶u和用戶v,令N(u)N(u)N(v)N(v)分別表示用戶u和用戶v曾經有過正反饋的物品集合,則有如下三種方式計算相似度:

  1. Jaccard公式

wuv=N(u)N(v)N(u)N(v)w_{uv}=\frac{N(u) \bigcap N(v)}{N(u) \bigcup N(v)}

  1. 餘弦相似度(UserCF算法)

wuv=N(u)N(v)N(u)N(v)w_{uv}=\frac{N(u) \bigcap N(v)}{\sqrt{|N(u)||N(v)|}}

  1. 改進的餘弦相似度(UserIIF算法)

wuv=iN(u)N(v)1log1+N(i)N(u)N(v)w_{uv}=\frac{\sum_{i\in{N(u) \bigcap N(v)}} \frac{1}{log1+|N(i)|}}{\sqrt{|N(u)||N(v)|}}

在UserIIF算法中,N(i)N(i)是物品i的熱度,可見其對熱門物品進行了懲罰,因爲兩個用戶對冷門物品採取過同樣的行爲更能說明他們興趣的相似度。

這裏要強調一個工程實現上的Trick。在計算用戶行爲之間的相似度時,如果按照定義實現的話,需要對兩兩用戶的行爲集合進行統計,這樣的時間複雜度爲O(UU)O(|U|*|U|),但用戶行爲往往是十分稀疏的,很多用戶之間的行爲並沒有交集,導致時間浪費在這些不必要的計算上。這時就可以建立Item-User的倒排表,這樣在同一個Item下面的User兩兩之間一定是在這個Item上有交集的,所以只需要遍歷所有的Item,對其下所有的User兩兩進行統計即可,這樣可以極大降低時間複雜度。

Step2: 爲物品打分

在統計完用戶之間的相似度之後,就可以利用這種用戶相似度以及用戶對物品的評價爲物品打分。其公式如下:

p(u,i)=vS(u,K)N(i)wuvrvip(u, i) = \sum_{v \in S(u, K) \bigcap N(i)}w_{uv}r_{vi}

wuiw_{ui}表示用戶u對物品i的感興趣程度,S(u,K)S(u, K)表示和用戶u興趣最接近的K個用戶,N(i)N(i)是對物品i有過行爲的用戶集合,wuvw_{uv}是用戶u和用戶v的興趣相似度,rvir_{vi}是用戶v對物品i的興趣。

在實現的時候,往往會取一個較小的K值,先召回一批物品,然後爲這些物品中沒出現在目標用戶中的物品利用上述公式進行打分。

2.2 基於物品的協同過濾算法

代碼鏈接:https://github.com/Magic-Bubble/RecommendSystemPractice/blob/master/Chapter2/基於物品的協同過濾算法.ipynb

與基於用戶的協同過濾算法一樣,基於物品的協同過濾算法也是基於鄰域的一種做法。它也可以分爲兩步:

a. 計算物品之間的相似度。
b. 根據物品的相似度和用戶的歷史行爲爲用戶生成推薦列表。

Step1: 計算物品相似度

計算物品相似度主要還是利用用戶的行爲數據,即比較對兩個物品有過正反饋的用戶集合的相似性。令N(i)N(i)爲喜歡物品i的用戶集合,則有如下幾種相似度計算方法:

  1. 購買了該商品的用戶也經常購買的其他商品

wij=N(i)N(j)N(i)w_{ij}=\frac{|N(i) \bigcap N(j)|}{|N(i)|}

  1. 餘弦相似度(ItemCF算法)

上面的公式在計算的時候會導致物品與熱門物品的相似度都很高,因此可以加上物品j的熱度懲罰項,變成了如下的餘弦相似度的形式:

wij=N(i)N(j)N(i)N(j)w_{ij}=\frac{N(i) \bigcap N(j)}{\sqrt{|N(i)||N(j)|}}

  1. 改進的餘弦相似度(ItemIUF算法)

wij=uN(i)N(j)1log1+N(u)N(i)N(j)w_{ij}=\frac{\sum_{u\in{N(i) \bigcap N(j)}} \frac{1}{log1+|N(u)|}}{\sqrt{|N(i)||N(j)|}}

與UserIIF算法類似,這裏也對熱門用戶進行了懲罰,即活躍用戶對物品相似度的貢獻應該小於不活躍的用戶。

Step2: 爲物品打分

在統計完物品之間的相似度之後,就可以利用這種物品相似度以及用戶對歷史物品的評價爲物品打分。其公式如下:

p(u,j)=iN(u)S(j,K)wjiruip(u, j) = \sum_{i \in N(u) \bigcap S(j, K)}w_{ji}r_{ui}

這裏N(u)N(u)是用戶喜歡的物品的集合,S(j,K)S(j,K)是和物品j最相似的K個物品的集合,wjiw_{ji}是物品j和i的相似度,ruir_{ui}是用戶u對物品i的興趣。

這裏還有一個Trick,可以對wijw_{ij}進行歸一化,使得物品之間計算相似度的時候保持同樣的量級,如下所示:

wij=wijmaxjwijw_{ij}^{'}=\frac{w_{ij}}{max_{j}w_{ij}}

2.3 隱語義模型

代碼鏈接:https://github.com/Magic-Bubble/RecommendSystemPractice/blob/master/Chapter2/隱語義模型.ipynb

隱語義模型LFM其實就是機器學習的模型了,它其實是一種對矩陣分解的模擬,用兩個低階向量相乘來模擬實際的User-Item矩陣,如用如下公式計算用戶u對物品i的興趣:

Preference(u,i)=rui=puTqi=k=1Kpu,kqi,kPreference(u, i)=r_{ui}=p_{u}^{T}q_{i}=\sum_{k=1}^{K}p_{u,k}q_{i,k}

這裏的pu,kp_{u,k}qi,kq_{i,k}是模型的參數,其中pu,kp_{u,k}度量了用戶u的興趣和第k個隱類的關係,而qi,kq_{i,k}度量了第k個隱類和物品i之間的關係。

那麼,label要怎麼標註?一般數據集裏面的都是隻有正向反饋,即只有標籤1,這時就需要進行負採樣,即採出標籤0來。採樣是針對每個用戶來進行的,對於每個用戶,負採樣的Item要遵循如下原則:

  1. 對每個用戶,要保證正負樣本的平衡(數目相似)。
  2. 對每個用戶採樣負樣本時,要選取那些很熱門,而用戶卻沒有行爲的物品。

在定義完打分公式和label標註之後,就可以利用機器學習中常用的梯度下降法進行模型的學習了。最後的模型還要加上一些正則化項,其loss爲:

C=(u,i)K(ruir^ui)2=(u,i)K(ruik=1Kpu,kqi,k)2+λpu2+λqi2C=\sum_{(u,i)\in K}(r_{ui}-\hat{r}_{ui})^2 = \sum_{(u,i)\in K}(r_{ui}-\sum_{k=1}^{K}p_{u,k}q_{i,k})^2 + \lambda||p_u||^2 + \lambda||q_i||^2

主要是求pu,kp_{u,k}qi,kq_{i,k}兩組參數,其梯度爲:

Cpuk=2qik+2λpuk\frac{\partial C}{\partial p_{uk}}=-2q_{ik}+2\lambda p_{uk}
Cqik=2puk+2λpik\frac{\partial C}{\partial q_{ik}}=-2p_{uk}+2\lambda p_{ik}

根據隨機梯度下降法,每次的更新爲(α\alpha爲學習率):

puk=puk+α(qikλpuk)p_{uk} = p_{uk} + \alpha (q_{ik} - \lambda p{uk})
qik=qik+α(pukλpik)q_{ik} = q_{ik} + \alpha (p_{uk} - \lambda p{ik})

2.4 基於圖的模型

代碼鏈接:https://github.com/Magic-Bubble/RecommendSystemPractice/blob/master/Chapter2/基於圖的模型.ipynb

用戶的行爲(User, Item)是可以表示爲二分圖的,比如下圖:

那麼任務就變成了在二分圖上爲用戶進行個性化推薦,即給用戶u推薦物品的任務可以轉化爲度量用戶頂點vuv_u和與vuv_u沒有邊直接相連的物品節點在圖上的相關性,相關性越高的物品在推薦列表中的權重就越高。

正常來說,相關性高的一對節點之間一般具有如下特徵:

  1. 兩個頂點之間有很多路徑相連;
  2. 連接兩個頂點之間的路徑長度都比較短;
  3. 連接兩個頂點之間的路徑不會經過出度比較大的頂點。

基於上面這三個主要因素,可以用PersonalRank算法進行圖上的隨機遊走推薦,其原理爲:要給用戶u進行個性化推薦,可以從用戶u對應的節點vuv_u開始在用戶物品二分圖上進行隨機遊走。遊走到任何一個節點時,首先按照概率α\alpha決定是繼續遊走,還是停止這次遊走並從vuv_u節點開始重新遊走。如果決定繼續遊走,那麼就從當前節點指向的節點中按照均勻分佈隨機選擇一個節點作爲遊走下次經過的節點。這樣,經過很多次隨機遊走後,每個物品節點被訪問到的概率會收斂到一個數。最終的推薦列表中物品的權重就是物品節點的訪問概率。

表述爲遞推公式如下:

PR(v)={αvin(v)PR(v)out(v)vvu(1α)+αvin(v)PR(v)out(v)v=vuPR(v)=\left\{ \begin{array}{rcl} \alpha \sum_{v' \in in(v)} \frac{PR(v^{'} )}{|out(v')|} & & {v \neq v_u}\\ (1-\alpha)+\alpha \sum_{v' \in in(v)} \frac{PR(v' )}{|out(v')|} & & {v = v_u}\\ \end{array} \right.

在工程實現上,可以真的用循環來模擬遊走,但還是推薦用矩陣的形式,令M(v,v)=1out(v)M(v, v') = \frac{1}{|out(v)|}爲用戶物品二分圖的轉移概率矩陣,則迭代公式轉化爲:

r=(1α)r0+αMTrr = (1 - \alpha) r_0 + \alpha M^Tr

這個公式是有解析解的,比模擬遊走要方便很多。

r=(1α)(1αMT)1r0r = (1 - \alpha) (1 - \alpha M^T)^{-1}r_0

2.5 各算法比較

2.5.1 UserCF和ItemCF的綜合比較

  1. UserCF比較古老,而ItemCF則相對較新。
  2. UserCF給用戶推薦那些和他有共同興趣愛好的用戶喜歡的物品,而ItemCF給用戶推薦那些和他之前喜歡的物品類似的物品。從這個算法的原理可以看到,UserCF的推薦結果着重於反映和用戶興趣相似的小羣體的熱點,而ItemCF的推薦結果着重於維繫用戶的歷史興趣。換句話說,UserCF的推薦更社會化,反映了用戶所在的小型興趣羣體中物品的熱門程度,而ItemCF的推薦更加個性化,反映了用戶自己的興趣傳承。
  3. UserCF比較適合用於新聞推薦等熱門程度和實時性較強的場景。比如一個人看新聞不可能每天只看和之前看的相關的那些,更多的是看今天有哪些新的熱門的。從原理上講,UserCF可以給用戶推薦和他有相似愛好的一羣其他用戶今天都在看的新聞,這樣在抓住熱點和時效性的同時,保證了一定程度的個性化。從技術角度講,UserCF主要是維護用戶相似度表,在這種場景下,物品的更新速度遠超用戶,所以維護物品相似度表難度和成本都較高。
  4. ItemCF則適用於圖書、電商、電影等場景。首先這些場景中用戶的興趣是比較固定和長久的,而且一般物品更新的速度不會特別快。

總結如下:

2.5.2 LFM與基於鄰域的方法的比較

  1. 理論基礎:LFM是一種機器學習模型,有最優化等理論支撐。而基於鄰域的方法更多的是基於統計,沒有學習。
  2. 離線計算的空間複雜度:基於鄰域的方法需要維護一張離線的相關表。假設有MM個用戶和NN個物品,UserCF需要O(MM)O(M*M)的空間,ItemCF需要O(NN)O(N*N)的空間,而對於LFM,有FF個隱類的話,需要O(F(M+N))O(F*(M+N))的空間。
  3. 離線計算的時間複雜度:假設有MM個用戶、NN個物品、KK條用戶對物品的行爲記錄。那麼,UserCF計算用戶相關表的時間複雜度是O(N(K/N)2)O(N * (K/N)^2),而ItemCF計算物品相關表的時間複雜度是O(M(K/M)2)O(M*(K/M)^2)。而對於LFM,如果用FF個隱類,迭代SS次,那麼它的計算複雜度是O(KFS)O(K * F * S)。那麼,如果K/N>FSK/N > F*S,則代表UserCF的時間複雜度低於LFM,如果K/M>FSK/M>F*S,則說明ItemCF的時間複雜度低於LFM。在一般情況下,LFM的時間複雜度要稍微高於UserCF和ItemCF,這主要是因爲該算法需要多次迭代。但總體上,這兩種算法在時間複雜度上沒有質的差別。
  4. 在線實時推薦:UserCF和ItemCF在線服務算法需要將相關表緩存在內存中,然後可以在線進行實時的預測。而從LFM的預測公式可以看到,LFM在給用戶生成推薦列表時,需要計算用戶對所有物品的興趣權重,然後排名,返回權重最大的N個物品。那麼,在物品數很多時,這一過程的時間複雜度非常高,可達O(MNF)O(M*N*F)。因此,LFM不太適合用於物品數非常龐大的系統,如果要用,我們也需要一個比較快的算法給用戶先計算一個比較小的候選列表,然後再用LFM重新排名。另一方面,LFM在生成一個用戶推薦列表時速度太慢,因此不能在線實時計算,而需要離線將所有用戶的推薦結果事先計算好存儲在數據庫中。因此,LFM不能進行在線實時推薦,也就是說,當用戶有了新的行爲後,他的推薦列表不會發生變化。
  5. 推薦解釋:ItemCF算法支持很好的推薦解釋,它可以利用用戶的歷史行爲解釋推薦結果。但LFM無法提供這樣的解釋,它計算出的隱類雖然在語義上確實代表了一類興趣和物品,卻很難用自然語言描述並生成解釋展現給用戶。

協同過濾篇到這裏就分享完了,後面將繼續分享第三部分——冷啓動篇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章