用户行为很容易表示为以用户和物品为顶点的二部图。
假设我们根据用户评分文件得到了一个字典形式表示的二部图graph。graph的具体结构如下:
{ userA:{itema:1, itemc:1 },userB:{itema:1,itemd:1},itema:{userA:1,userB:1},itemb:{},itemc:{userA:1},itemd:{userB:1} }
可见,字典graph的key为所有的用户和物品。
下面,定义一个函数,该函数针对我们输入的某个user,返回所有顶点(包括用户和物品)的取值,其中k为我们设定的迭代次数。
def personal_rank(graph,user,alpha,k):
rank = {}
rank = { i:0 for i in graph}
rank[user] = 1
for k_index in range(k):
temp_rank = {}
temp_rank = { i:0 for i in graph}
for out_vertex, out_vertex_dict in graph.items():
for j, j_value in graph[out_vertex].items():
temp_rank[j] += alpha * rank[out_vertex] / len(out_vertex_dict)
if j == user:
temp_rank[j] += (1- alpha) # 相当于 (1- alpha) * 1
if temp_rank == rank:
break:
rank = temp_rank
return rank
然后,我们根据得到的rank,将其中代表用户顶点的键值对过滤,对剩下的代表物品顶点的键值对进行降序排列,并过滤掉该用户已经操作过的物品,就得到我们需要向该用户推荐的物品序列了。
通过公式推导,我们也可得到矩阵运算形式的personal_rank,矩阵运算形式的计算速度要比此处的for循环计算速度快多了。此处就不再阐述矩阵形式的personal_rank算法的具体过程了。