圖推薦_Personalrank演算法原理與簡例實現
筆者的畢業設計是基於圖演算法的推薦系統實現,寫點blog作為論文筆記,不足之處望多多指正
為什麼是圖演算法?
推薦系統的目的是解決海量資料下的資訊精準推薦問題,白話說:現在我們身邊的資訊是海量的,可供人們選擇的商品、書籍、電影也是數不勝數,而人的精力是有限的,推薦系統恰好可以為個人提供較為準確的推薦,幫助人們更快更好的找到自己需要的事物。
現階段的,商業收集到使用者的大部分資料都是發生在使用者與商品之間的,如老王買了香菸、小王買了鮮花等一類人對物的行為資料,這些行為行為資料恰好可以通過一連串的二元祖來進行表示,這恰好可以利用圖演算法來幫助開發者,設計出更好的推薦演算法。
演算法思路
此處借用《推薦系統實踐》一書中的案例來闡述:比如現在有使用者:A、B、C、D和物品:a、b、c、d、e,組成的閉環生態,我們將這其中的購買行為通過二分圖進行表示(如下圖):
利用行為資料進行推薦,本質上是找使用者最有可能選擇的物品(與使用者最為相似的物品),那研究者認為二分圖裡物品最有可能被使用者接受的因素有以下幾個:
- 兩頂點間的路徑數;
點點間路徑數越多說明有越多和使用者喜歡同a的人也喜歡b,可說明a、b相似度高
- 兩頂點間的路徑長度;
- 兩頂點間的路徑經過的點
在計算相關性時,現實中相關性越高的物品的共同點往往有:
- 頂點間有多條路徑連線;
- 連線兩頂點的路徑長度比較短;
- 連線兩頂點間的路徑不會出現出度比較大的點
因為現實生活,爆款產品的出度往往很大,演算法中直接使用容易出現長尾效應
Personalrank演算法原理
基於上述思想,產生Personalrank演算法,其演算法原理如下:
PR
(
v
)
=
{
α
∑
v
′
∈
i
n
(
v
)
P
R
(
v
′
)
∣
out
(
v
′
)
∣
(
v
≠
v
u
)
(
1
−
alpha
)
+
α
∑
v
′
∈
i
n
(
v
)
PR
(
v
′
)
∣
out
(
v
′
)
∣
(
v
=
v
u
)
\operatorname{PR}(v)=\left\{\begin{array}{l}\alpha \sum_{v^{\prime} \in \mathrm{in}(v)} \frac{\mathrm{PR}\left(v^{\prime}\right)}{\left|\operatorname{out}\left(v^{\prime}\right)\right|}\left(v \neq v_{u}\right) \\ (1-\text { alpha })+\alpha \sum_{v^{\prime} \in \mathrm{in}(v)} \frac{\operatorname{PR}\left(v^{\prime}\right)}{\left|\operatorname{out}\left(v^{\prime}\right)\right|} \quad\left(v=v_{u}\right)\end{array}\right.
其中:v為頂點集,pr(i)是戶選擇i的可能性,這裡初始情況下認為pr(i)=1(原物)pr(i)=0(非原物i),out(i)為頂點的出度;a可以看成是使用者下次選擇下一種物品的可能性。從節點i出發後,開始隨機遊走,(上式迭代),經過多次遊走後(迭代)後,訪問每個節點的概率會趨於收斂,這個收斂值就被認為是物品被使用者選中的概率。
演算法實現
基於python,通過Personalrank實現演算法程式碼如下:
#personalrank演算法的簡單算例實現
import time
#設計personalrank演算法函式
def Personalrank(Graph,alpha,root,max_depth):
#推薦排序
rank=dict()
rank={x:0 for x in Graph.keys()}
rank[root]=1
#迭代
begin=time.time()
for k in range(max_depth):
tmp={x:0 for x in Graph.keys()}
#取出節點i和他的出邊節點集合
for i,ri in Graph.items():
for j,wij in ri.items():
tmp[j]+= alpha * rank[i] / (1.0 * len(ri))
tmp[root] += (1 - alpha)
rank = tmp
end=time.time()
print('使用時間:',end-begin)
#lst=sorted(rank.items(),key=lambda x:x[1],reverse=True)
#for ele in lst:
#print('%s:%.3f , \n'%(ele[0],ele[1]))
return rank
if __name__=='__main__':
alpha=0.8
Graph={
'A':{'a':1,'b':1,'d':1},
'B':{'a':1,'c':1},
'C':{'b':1,'e':1},
'D': {'c': 1, 'e': 1},
'a':{'A':1,'B':1},
'b':{'A':1,'C':1},
'c':{'D':1,'B':1},
'd':{'A':1,'D':1},
'e':{'C':1,'D':1},
}
print(Personalrank(Graph,alpha,'b',50))
以節點b為例,利用Personalrank演算法可以得到其與節點的相似性為:
‘A’: 0.16577257339161164, ‘B’: 0.043444835869696115, ‘C’: 0.16109189469317547, ‘D’: 0.07412879716688255, ‘a’: 0.06158614968457111, ‘b’: 0.308644973214133, ‘c’: 0.04703252728649955, ‘d’: 0.04420689787736918, ‘e’: 0.09409135081606143
思考
- 現演算法在現大規模行為資料的應用場景中計算量會很大,後續可以轉化成矩陣計算來改進演算法;
- 如果從人節點出發得到推薦結果後,其與基於使用者的協同過濾演算法的異同在哪裡?同樣的,如果從物節點出發那麼其與基於物品的協同過濾演算法的異同又在哪裡?