上图是一个二元图,表示了A,B,C用户对abcd物品的感兴趣程度,有连线即为感兴趣。
图游走算法是根据图各节点关系来进行计算的,并且图游走算法不区分用户与作品。
比如我们对用户A进行推荐,那么先初始化对A的感兴趣程度为1,用一个字典rank来存储感兴趣程度
那么rank[‘A’]=1,其余节点均为0
假设游走的概率为alpha,那么停留的概率为(1-alpha)。
那么第一次游走,rank[‘a’] = rank['c] = rank[‘A’]* 1/2* alpha, rank[‘A’] = 1-alpha
可以列出这个公式
网上的实现代码如下:
import time
def personalRank(G, alpha, root, max_step):
rank = dict()
rank = {x:0 for x in G.keys()}
rank[root] = 1
start = time.time()
for k in range(max_step):
temp = {x:0 for x in G.keys()}
for i, ri in G.items():
#每个点都要游走
for j, rj in ri.items():
#对相连的其他点进行值的更新
temp[j] += alpha * rank[i]/(1.0*len(ri))
#此处更新初始点的值
temp[root] += (1-alpha);
#每游走一次更新一下rank
rank = temp;
end = time.time()
print("time:{}".format(end-start))
li = sorted(rank.items(), key = lambda x:x[1], reverse=True)
for ele in li:
print("%s:%.3f, \t"%(ele[0], ele[1]))
return rank
if __name__ == '__main__' :
alpha = 0.8
G = {'A' : {'a' : 1, 'c' : 1},
'B' : {'a' : 1, 'b' : 1, 'c':1, 'd':1},
'C' : {'c' : 1, 'd' : 1},
'a' : {'A' : 1, 'B' : 1},
'b' : {'B' : 1},
'c' : {'A' : 1, 'B' : 1, 'C':1},
'd' : {'B' : 1, 'C' : 1}}
personalRank(G, alpha, 'A', 50) #从'A'节点开始游走
根据我的理解实现代码如下:
def personalRank(G, alpha, root, max_step):
rank = dict()
rank = {x:0 for x in G.keys()}
rank[root] = 1
start = time.time()
for k in range(max_step):
for i, ri in G.items():
#每个点都要游走
for j, rj in ri.items():
#对相连的其他点进行值的更新
rank[j] += alpha * rank[i]/(1.0*len(ri))
rank[i] *= (1-alpha);
end = time.time()
print("time:{}".format(end-start))
li = sorted(rank.items(), key = lambda x:x[1], reverse=True)
for ele in li:
print("%s:%.3f, \t"%(ele[0], ele[1]))
return rank
代码不同的原因:用户既然是alpha的概率去游走,那么剩下的值就应该变成rank[users]*(1-alpha)
,而不是直接相加。而网上所找的都是直接相加的,这样的总概率和加起来也不是1,感觉有点问题。
仅供参考,欢迎讨论