推荐系统(3)---寻找数据集中的相似用户

寻找数据集中的相似用户

# -*- coding:utf-8 -*-
'''
  寻找数据集中的相似用户
'''
import json
import numpy as np

# 计算user1 和 user2的相关系数
def pearson_score(dataset,user1,user2):
    if user1 not in dataset:
        raise TypeError('User'+user1+'not present in the dataset')
    if user2 not in dataset:
        raise TypeError('User'+user2+'not present in the dataset')
    # 提取两个用户都评过分的电影
    rated_by_both = {}
    for item in dataset[user1]:
       if item in dataset[user2]:
           rated_by_both[item]=1
    num_ratings=len(rated_by_both)
    # 如果两个用户都没有评分 则说明两个用户之间没有相似度 返回值为0
    if num_ratings==0:
        return  0
    # 计算相同评分电影的平方值之和
    user1_sum=np.sum([dataset[user1][item] for item in rated_by_both])
    user2_sum=np.sum([dataset[user2][item] for item in rated_by_both])

    # 计算相同电影的评分的平方和
    user1_squared_sum=np.sum([np.square(dataset[user1][item]) for item in rated_by_both])
    user2_squared_sum=np.sum([np.square(dataset[user2][item]) for item in rated_by_both])

    # 计算数据集的乘积之和
    product_sum=np.sum([dataset[user1][item]*dataset[user2][item] for item in rated_by_both])

    # 计算皮尔逊相关系数
    Sxy=product_sum-(user1_sum*user2_sum/num_ratings)
    Sxx=user1_squared_sum-np.square(user1_sum)/num_ratings
    Syy=user2_squared_sum-np.square(user2_sum)/num_ratings

    # 考虑分母为0的情况
    if Sxx*Syy==0:
        return 0
    # 如果上述正常 返回皮尔逊相关系数
    return Sxy/np.sqrt(Sxx*Syy)

# 寻找特定数量的与输入用户相似的用户
# dataset:代表数据库 user: 输入用户 num_users:相似的用户个数
def find_similar_users(dataset,user,num_users):
    if user not in dataset:
        raise TypeError('User '+user+' not present in the dataset')

    # 计算所有用户的皮尔逊相关度
    scores = np.array([[x,pearson_score(dataset,user,x)] for x in dataset if user!=x])

    # 评分按照第二列进行排列

    scores_sorted =np.argsort(scores[:,1])

    #  评分按照降序排列
    scores_sorted_dec=scores_sorted[::-1]

    #  提取多个高分并返回
    top_k=scores_sorted_dec[0:num_users]
    return scores[top_k]

if __name__ == '__main__':
    data_file='movie_ratings.json'
    with open(data_file,'r') as f:
        data=json.loads(f.read())
    user='John Carson'
    print "\n User similar to "+user+":\n"
    # 查找三个相似用户
    similar_users=find_similar_users(data,user,3)
    print "User\t\t\t Similarity score\n"
    for item in similar_users:
        print item[0],'\t\t',round(float(item[1]),2)

输出结果如下:

 User similar to John Carson:

User             Similarity score

Michael Henry       0.99
Alex Roberts        0.75
Melissa Jones       0.59

你可能感兴趣的:(-,-,Recommender,Systems)