《推荐系统实践》 程序实现 ——2.6 基于图的模型

PersonalRank算法

在这里插入图片描述
在基于图的模型中,给用户A进行个性化推荐,实际是计算用户A对所有物品的感兴趣程度。
在PersonalRank算法中,不区分用户和商品,所以计算用户A对所有物品的感兴趣程度,即计算除用户A外的所有节点B,C,a,b,c,d对用户A的重要度。

原理如下,其中PR(v)表示重要度(物品结点的访问概率)。
在这里插入图片描述
具体过程描述1:
在这里插入图片描述
具体过程描述2:
初始赋予 ,即对于A来说,他自身的重要度为满分,其他节点的重要度均为0。

然后开始在图上游走。每次都是从PR不为0的节点开始游走,往前走一步。继续游走的概率是alpha,停留在当前节点的概率是(1-alpha)。

第一次游走, 从A节点以各自50%的概率走到了a和c,这样a和c就分得了A的部分重要度α*PR(A)*0.5。第一次游走结束后PR不为0的节点有A a c。

第二次游走,分别从节点A a c开始,往前走一步。这样节点a分得A 的重要度,节点c分得A 的重要度,节点A分得a 的重要度,节点A分得c 的重要度,节点B分得a 的重要度,节点B分得c 的重要度,节点C分得c 的重要度。最后要加上(1-α)。

程序实现:

def PersonalRank(G,alpha,root,max_step):

	rank = dict()#
	rank = {x: 0 for x in G.keys()}#初始化,将二分图中所有结点(包括所有的用户结点和物品结点)的访问概率(即PR,也可称为重要度)初始化为0
	rank[root] = 1 #为用户root进行推荐(即计算用户u对所有物品感兴趣的程度)

	for k in range(max_step):
		tmp = {x: 0 for x in G.keys()}
		for i, ri in G.items():
			for j, wij in ri.items():
				if j not in tmp: #保险起见,其实上边tmp在初始化时已经将所有的结点都包含进了
					tmp.update({j: 0})
				tmp[j] += alpha * rank[i] / (1.0 * len(ri))
				if j == root:
					tmp[j] += 1 - alpha
		rank = tmp
	return rank

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}} #节点和出边的尾节点,构成了二分图G; 边E(i,j)的权重wij设置为1。

alpha = 0.85
result = PersonalRank(G,alpha,'A',100)
print(result)

执行结果

{'A': 0.5386042757187186, 'B': 0.37000524566306364, 'C': 0.17247155260659047, 'a': 0.30753291329505, 'b': 0.0786261054089978, 'c': 0.3808333138584477, 'd': 0.15192650597239551}

可以看出,用户A已经对物品a、c有过行为了,所以只对物品b、d按照重要度进行排序为{d,b}。故给A的推荐列表就是{d,b}。

参考文献

[1] 推荐算法——基于图的推荐算法PersonalRank算法
[2] PersonalRank:一种基于图的推荐算法