利用python构建推荐引擎小项目实战

本次写的构建推荐引擎是一个晓得project,依赖于三个源文件:

find_similar_user.py  pearson_score.py  euclidean_score.py

以及最后的实现部分。

一个json数据文件,格式如下:

    "John Carson": 
    {
        "Inception": 2.5,
        "Pulp Fiction": 3.5,
        "Anger Management": 3.0,
        "Fracture": 3.5,
        "Serendipity": 2.5,
        "Jerry Maguire": 3.0
    },
    "Michelle Peterson": 
    {
        "Inception": 3.0,
        "Pulp Fiction": 3.5,
        "Anger Management": 1.5,
        "Fracture": 5.0,
        "Jerry Maguire": 3.0,
        "Serendipity": 3.5 

1.计算欧式距离分数

为了构建一个推荐引擎,需要定义相似度指标,以便找到与数据库中特定用户相似的用户,欧式距离分数为两个数据点之间的欧几里得距离,可以作为指标。

首先定义一个用于计算两个用户之间的欧几里得分数的函数,第一步首先判断用户是否在数据库中出现,如果没有则输出无

def euclidean_score(dataset,user1,user2):
    if user1 not in dataset:
        raise TypeError('User' + user1 + 'not persent in the dataset')
    if user2 not in dataset:
        raise TypeError('User' + user2 + 'not persent in the dataset')

为了计算分数,需要提取两个用户均评分过的电影,并赋予值1:传入用户实参,遍历这两个用户看过的所有电影,然后寻找两个用户都评分过的电影

rated_by_both = {}
    for item in dataset[user1]:
        if item in dataset[user2]:
            rated_by_both[item]=1

如果没有两个用户共同评分过的电影,则说明这两个用户之间没有相似度,得分为0

    if rated_by_both ==0:
        return 0

对于每个共同评分,只计算平方和的平方根,并将该值归一化,使得评分值在0到1之间

squared_difference = []
    for item in dataset[user1]:
        if item in dataset[user2]:
            squared_difference.append(np.square(dataset[user1][item]-dataset[user2][item]))
    return 1/(1+np.sqrt(np.sum(squared_difference)))

如果评分相似,那么平方和的差别就会很小,因此评分就会变得很高

定义主函数,加载文件,传入两个随机用户计算分数

if __name__ == '__main__':
    data_file = 'movie_ratings.json'
    with open(data_file,'r') as f:
        data = json.loads(f.read())
    #嘉定两个随机用户,计算其欧式距离分数
    user1 = 'John Carson'
    user2 = 'Michelle Peterson'
    print("\nEuclidean score:")
    print(euclidean_score(data,user1,user2))

2.计算皮尔逊相关系数

我们之后的推荐引擎主要用皮尔逊系数来做

首先定义一个用于计算两个用户之间皮尔逊相关度系数的函数

第一步同样是判断是都都在数据库中出现,第二部是提取两个用户均评分过的电影,此处和1计算欧几里得分数类似:

def pearson_score(dataset,user1,user2):
    if user1 not in dataset:
        raise TypeError('User' + user1 + 'not persent in the dataset')
    if user2 not in dataset:
        raise TypeError('User' + user2 + 'not persent 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)
    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])

计算皮尔逊相关系数需要的各种元素并考虑坟墓为0的情况,如果正常就返回皮尔逊相关系数

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
    if Sxx *Syy ==0:
        return 0

定义主函数并计算两个用户之间的皮尔逊相关系数

if __name__ == '__main__':
    data_file = 'movie_ratings.json'
    with open(data_file,'r') as f:
        data = json.loads(f.read())
    user1 = 'John Carson'
    user2 = 'Michelle Peterson'
    print("\nPearson score:")
    print(pearson_score(data,user1,user1))

3.寻找相似用户

第一步导入已有的皮尔逊函数

import json
import numpy as np
from pearson_score import pearson_score

定义一个函数,用于寻找与输入用户相似的用户,该函数有三个输入参数:数据库、输入用户和寻找的相似用户个数,首先查看该用户是否包含在数据库中,如果存在需要计算与其他所有用户的皮尔逊相关系数。

def find_similar_user(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])

将计算好的皮尔逊系数的分数按照降序排列,提取出k个最高分并返回

    #将这些得分按照第二列排列
    scores_sorted = np.argsort(scores[:,1])
    #评分按照降序排列
    scores_sorted_dec = scores_sorted[::-1]
    #提取出k个最高分并返回
    top_k = scores_sorted_dec[0:num_users]
    return scores[top_k]

定义主函数,家在输入数据库,输入实参,定义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("\nUsers similar to "+user +":\n")
        similar_users = find_similar_user(data,user,3)
        print("User\t\t\tSimilarity score\n")
        for item in similar_users:
            print(item[0],'\t\t',round(float(item[1]),2))


4。生成电影推荐

首先引入依赖的三个函数

import json
import numpy as np
from euclidean_score import euclidean_score
from pearson_score import pearson_score
from find_similar_user import find_similar_user

定义一个为给定用户生成电影推荐的函数,首先检查该用户是否存在于数据库中,然后计算皮尔逊系数

def generate_recommendations(dataset,user):
    if user not in dataset:
        raise TypeError('User' + user + 'not present in the dataset')
    #计算该用户与数据库中其他用户的皮尔逊相关系数
    total_scores = {}
    similarity_sums = {}
    for u in [x for x in dataset if x !=user]:
        similarity_score = pearson_score(dataset,user,u)
        if similarity_score<=0:
            continue

找到还未被该用户评分的电影,如果该用户看过所有的电影,那就不能为用户推荐电影,对该条件进行判断输出

        for item in [x for x in dataset[u] if x not in dataset[user] or dataset[user][x]==0]:
            total_scores.update({item:dataset[u][item]*similarity_score})
            similarity_sums.update({item:similarity_score})
    if len(total_scores) ==0:
        return ['Not recommendations possible']

有了皮尔逊相关系数列表,下面生成一个电影评分标准化列表,并对其进行降序排列,然后进行提取

    movie_ranks = np.array([[total/similarity_sums[item],item] for item, total in total_scores.items()])
    #对皮尔逊相关系数进行降序排列,根据第一列
    movie_ranks = movie_ranks[np.argsort(movie_ranks[:,0])[::-1]]
    #提取出推荐的电影
    recommendations = [movie for _, movie in movie_ranks]
    return recommendations

最后定义主函数,加载数据集,给定某个用户进行推荐

if __name__ == '__main__':
    data_file = "movie_ratings.json"
    with open(data_file,'r') as f:
        data = json.loads(f.read())
        #为Michael Henry 生成推荐
        user = 'Michael Henry'
        print("\nRecommendations for "+user +":")
        movies = generate_recommendations(data,user)
        for i, movie in enumerate(movies):
            print(str(i+1)+'.'+movie)
        #为John Carson  生成推荐
        user = 'John Carson'
        print("\nRecommendations for "+user +":")
        movies = generate_recommendations(data,user)
        for i, movie in enumerate(movies):
            print(str(i+1)+'.'+movie)


最后的总结:

这个小project用到了是皮尔逊系数和欧几里得分数的计算,然后用了一些基本的数据结构的知识,没有考虑当数据量过大的时候如何释放内存,函数还需要重构。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值