基於圖的推薦演算法之Personal PageRank程式碼實戰

weixin_33890526發表於2017-04-12

背景:Personal Rank 屬於協同的一種,也是為了精準的match使用者感興趣的物品,是一種基於圖的推薦演算法。最近在具體落地這個演算法方面遇到了一些時間效能方面的問題,所以整理一下,文中不僅會涉及演算法介紹,同樣會涉及具體程式碼,以及為了優化時間所做的工作。

personal rank演算法介紹:普適推薦問題中的(user,item)對,可以表示為二分圖G(V,E),兩類頂點分別表示使用者Vu,以及物品Vi,如下圖1所示 使用者A點選了物品abd,使用者B點選了ac,C點選了be,D點選了cd。那麼可以轉化為右圖,右圖只標示了使用者A和他點選物品的連擊,其餘類似。該演算法的核心目的是衡量出對某一固定結點,其餘結點的重要程度。從而得出推薦順序。

5616808-59b7644cab3716a7.png
圖1

關於如何衡量某一個結點對於另一個結點的重要程度,物理解釋如下:(1)兩個頂點之間的路徑數是否比較多(2)兩個頂點之間路徑的長度是否比較短。(3)連線兩個頂點的路徑是否較少經過出度較大的結點。那麼基於隨機遊走的personal rank演算法是如何闡述的呢? 假設我們要給使用者A推薦物品。從頂點VA開始出發,以alpha的概率從A的出邊中等概率的選擇一條隨機遊走過去,到達下一個頂點,比方說頂點a,從下一個頂點a有(1-alpha)的概率回到起點A,或者alpha的概率繼續等概率遊走到到頂點a的出邊中。多次迴圈後發現,各頂點的重要度收斂。遞推公式如下圖2所示:


5616808-a32f6fbd675de886.jpg
圖2

這個遞推公式是不是非常眼熟,將公式中(1-alpha)換成(1-alpha)/n ,那麼就變成了page rank,當然page rank不會固定某一頂點。根據personal rank的遞推公式很容易給出demo 程式碼如下。但是這個demo的時間效能非常差(n萬級別使用者物品點選對資料需要在spark下並行需要1個小時不能接受)

5616808-b739fa79a93e0b8d.png
圖3

根據如上程式碼分分析耗時主要發生在每個使用者結點需要迴圈跌代,上述圖2所示推導公式可以轉化為矩陣形式這樣的話運算的耗時將會降低非常多。矩陣形式推導見圖4.下圖中,最後結果行由於推薦是求的結點的相對重要性,所以在實際計算中1-alpha可以省略,(E-alpha*M.tranpose()) 的逆矩陣即為所有結點推薦結果的。每一列表示一個結點的結果(如果該矩陣為n*n)。r0 即為n*1矩陣,且只有一行為1,其餘為0,想取出第幾個結點的結果就將第幾行賦值為1.

5616808-2ecab9b2c33d2de5.jpg
圖4

由圖3中G轉化為M矩陣也就是轉移矩陣的過程中,可以想象轉移矩陣必然及其稀疏,為了節約時間以及控制以免記憶體error,採取稀疏矩陣的儲存方式。python中關於稀疏矩陣的庫是scipy.sparse. 有很多形式的稀疏矩陣類可以採用,封裝的非常好,根據需要可以自行選擇。api document:https://docs.scipy.org/doc/scipy/reference/sparse.html我們這裡選用了coo的方式見圖5(數十萬點展對僅從G轉化為M矩陣僅耗時0.47s左右),儲存靈活,可以迅速轉化成csr快速計算,也便於後續求逆。稀疏矩陣的求逆,轉化為解線代方程。Ax=E,而且由於矩陣A明顯是稀疏矩陣,所以解稀疏矩陣的線性方程,用到python的scipy 下面的gmres庫,解釋文件裡說可以解(Ax=b型的線性方程,b可以是n*1或者n*多,但是一經試驗發現只能用解  n*1,那麼也就說每次只能解出一個使用者的推薦結果單個使用者解出方程,並給出topk推薦用時大約0.72s但是試想如果是數十萬量級的使用者序列解決肯定是行不通的,所以再求出A之後,需要進行spark並行,十萬使用者,數十萬使用者物品點選對,1主13work164vcore的叢集配置下,經過repartition以及num-executor*executor-cores合理配置,佔滿資源20min,佔一半多core可以在30min左右),圖6是給出矩陣A產出的程式碼實現。注:單位矩陣np.eye(num) num一大就會報mem error,採用稀疏矩陣過渡。圖7給出了vertex矩陣的第一個頂點的推薦順序。關於spark程式這裡就不給出了。其實就是臨門一腳了。感興趣的小夥伴可以自己嘗試一下,如有問題請留言。當然大家如果想應用這個演算法,需要離線評估推薦準確率,關於本文所敘述離線評估演算法推薦的準確度,以及實際應用到線上的點展比,由於牽扯實際專案不方便透漏。

5616808-a17402dd943ec846.png
圖5
5616808-c9f27dcdac89cd24.png
圖6
5616808-dc5352fb5787de88.png
圖7

我們每一步的前進都是站在巨人肩上,特別鳴謝參考文獻。如需全文轉載請註明出處,謝謝

參考文獻:http://www.cnblogs.com/zhangchaoyang/articles/5470763.html,http://it.sohu.com/20170220/n481178384.shtml,http://blog.jobbole.com/71431/

相關文章