37,720
社区成员
发帖
与我相关
我的任务
分享
#coding=utf-8
'''
本文,用皮尔逊相关系数(pearon correlation coefficient)计算用户之间的相似性。
'''
from operator import itemgetter, attrgetter
from math import sqrt
# user_movie, movies都是字典
def load_data():
filename_user_movie = 'ratings_test.txt'
user_movie = {}
for line in open(filename_user_movie):
(userId, itemId, rating) = line.strip().split()
user_movie.setdefault(userId,{})
user_movie[userId][itemId] = float(rating)
return user_movie
#计算用户的平均值
def average_rating(user):
average = 0
for u in user_movie[user].keys():
'''针对user遍历user_movie中item列,对于由[userId][itemId]所组成的rating进行累加。
这样得到针对一个user的所有item的总评分。
再用总评分除以用户user的评分过的电影的总个数,就得到用户的平均评分。
'''
average += user_movie[user][u]
average = average * 1.0 / len(user_movie[user].keys())
return average
def calUserSim(user_movie):
''' build inverse table for movie_user 构建倒排文本,movie_user这个字典中相当于itemId是关键字
movie_user只包含两列的内容。
'''
movie_user = {}
for ukey in user_movie.keys():#遍历第一列
for mkey in user_movie[ukey].keys(): #遍历第二列
if mkey not in movie_user:
movie_user[mkey] = []#将user_movie第二列放到movie_user中
movie_user[mkey].append(ukey)# 将user_movie第一列放到movie_user中。那这个没有将rating放进去。
# calculated co-rated movies between users,在用户之间计算共同评分过的电影。
C = {}
'''
下面的操作是针对movie对用户进行遍历,将用户和电影都放到字典C中 。在用户之间计算共同评分过的电影。
movie_user中将第一个遍历到的用户放到第一列,将与第一个用户不同的用户(如果相同就不进行循环块后面的语句)
放到第二列第一个,字典C中的键是由(第一列,第二列)共同组成的,最后在他们的基础上添加电影。
这样就形成了(用户,用户,电影)的 字典。
'''
for movie, users in movie_user.items():#返回一个包含字典中(键, 值)对元组的列表。
#在所有内容中进行遍历 ,movie, users分别对应一列
for u in users:
C.setdefault(u,{}) #将movie_user中users转到C字典中来,并确定C中u是键。
for n in users:
if u == n:
continue #continue语句被用来告诉Python跳过当前循环块中的剩余语句,然后 继续 进行下一轮循环。
C[u].setdefault(n,[])
C[u][n].append(movie)
# calculate user similarity (perason correlation) 计算基于用户之间的相似性
userSim = {}
for u in C.keys():
for n in C[u].keys():
userSim.setdefault(u,{})
userSim[u].setdefault(n,0)
average_u_rate = average_rating(u)
average_n_rate = average_rating(n)
part1 = 0
part2 = 0
part3 = 0
for m in C[u][n]:
part1 += (user_movie[u][m]-average_u_rate)*(user_movie[n][m]-average_n_rate)*1.0
part2 += pow(user_movie[u][m]-average_u_rate, 2)*1.0
part3 += pow(user_movie[n][m]-average_n_rate, 2)*1.0
part2 = sqrt(part2)
part3 = sqrt(part3)
if part2 == 0:
part2 = 0.001
if part3 == 0:
part3 = 0.001
userSim[u][n] = part1 / (part2 * part3)
return userSim
'''
Items 方法 描述返回一个包含 Dictionary 对象中所有条目的数组。下面是首先对userSim[user].items()遍历和排序,
将用户先前交互过的电影过滤掉,将其他项目都放在项目预测pred字典中 ,并且以项目i为键。
i表示的是项目,nrating表示的是用户n的评分。nuw表示的是用户n和u的用户相似度userSim值。
itemgetter函数用于获取对象的哪些维的数据。key=itemgetter(1)意即按照userSim第二列的数据来排序,降序,N个项目。
可是num的值是由谁传递的呢?
'''
def getRecommendations(user, user_movie, userSim, N):
pred = {}
interacted_items = user_movie[user].keys()
average_u_rate = average_rating(user) #沿袭了average_rating(user)函数一样的参数user
sumUserSim = 0
for n, nuw in sorted(userSim[user].items(),key=itemgetter(1),reverse=True)[0:N]:
average_n_rate = average_rating(n) #用户n的平均评分
for i, nrating in user_movie[n].items():
if i in interacted_items:
continue
pred.setdefault(i,0)
pred[i] += nuw * (nrating - average_n_rate)
sumUserSim += nuw
for i, rating in pred.items():
pred[i] = average_u_rate + (pred[i]*1.0) / sumUserSim
# top-10 pred
pred = sorted(pred.items(), key=itemgetter(1), reverse=True)[0:10]
return pred
if __name__ == "__main__": # load data
user_movie= load_data() # Calculate user similarity
userSim = calUserSim(user_movie) # Recommend
pred = getRecommendations('780', user_movie, userSim, 20) # display recommend result (top-10 results)
for i, rating in pred:
print 'film: %s, rating: %s' % (i, rating)
def load_data():
filename_user_movie = 'ratings_test.txt'
user_movie = {}
for line in open(filename_user_movie):
try:
(userId, itemId, rating) = line.strip().split()
user_movie.setdefault(userId,{})
user_movie[userId][itemId] = float(rating)
except:
print line
return user_movie