1 相关说明
- TopN推荐问题
- 在基于图模型的推荐算法中,二分图(u,i)表示用户u对电影i评分过,即用户u观看了电影i。那么给用户u推荐电影的任务可以转化为度量用户顶点Vu和Vu没有边直接相连的电影节点在图上的相关性。
- 相关性高的顶点一般有如下特性:两个顶点有很多路径相连;连接两个顶点之间的路径长度比较短;连接两个顶点之间的路径不会经过出度较大的顶点。
2 PersonalRank算法原理
从用户u节点开始随机游走,游走到一个节点时,首先按照概率α决定是否继续游走,还是停止这次游走并从Vu节点开始重新游走。如果决定继续游走,那么就从当前节点指向的节点中按照均匀分布随机选择一个节点作为下次经过的节点,每个电影节点被访问的概率收敛到一个数,这个数越大,这个电影就越被推荐。
可以理解成用户u节点的重要性是1,通过随机游走将u节点的重要性分给了其他节点。
在执行算法之前,我们需要初始化每个节点的初始概率值。如果我们对用户u进行推荐,则令u对应的节点的初始访问概率为1,其他节点的初始访问概率为0,然后再使用迭代公式计算。迭代公式如下,其中i代表某个节点,α代表每次游走的概率。
以上随机游走的算法难点是时间复杂度高,可以通过矩阵论重新设计算法,对稀疏矩阵快速求逆。
rij代表节点i对于节点j的PR值;r0是对角线为1,其他元素为0的矩阵;M是概率转移矩阵,Mij代表节点j分得节点i的访问概率,如果i指向j的话,取值为i出度的倒数,否则取值为0。
其中(E-αM^T )^(-1) (1-α)可以看做所有顶点的推荐结果,删除所有用户节点行和电影节点列,就可以得到以用户为列、电影为行的访问概率矩阵r。对于每位用户,取对应列的所有行,按照PR值排序即可为其推荐。
3 代码
3.1 随机游走多次实现
import pandas as pd
import numpy as np
import math
import pickle
import random
import time
#写数据
def writeFile(data,path):
with open(path, "wb") as f:
pickle.dump(data, f)
#读数据
def readFile(path):
with open(path, "rb") as f:
return pickle.load(f)
#获得用户电影 的两个字典
def getDict(train_data):
user2mv={
}
mv2user={
}
for index,item in train_data.iterrows():
uid,mid=item['UserID'],item['MovieID']
user2mv.setdefault(uid,[]).append(mid)
mv2user.setdefault(mid,[]).append(uid)
return user2mv,mv2user
#随机游走
def personalRank(train_data,alpha,N):
user2mv,mv2user=getDict(train_data)
users=list(user2mv.keys())
movies=list(mv2user.keys())
#一个columns代表 一个用户
PR_movie=pd.DataFrame(data=np.zeros([len(movies),len(users)]),index=movies,columns=users)#mu 代表m对于u的重要性
PR_user=pd.DataFrame(data=np.eye(len(users)),index=users,columns=users)#u1u2 代表u1对于u2的重要性
num,sum=0,len(users)
#对于每一个用户进行N次随机游走
for user in users:
start