推荐系统之UserCF算法

基于用户的协同过滤算法

算法概念:
UserCF算法是推荐系统中协同过滤算法中的一种,称为基于用户的协同过滤算法。该算法通过用户A的兴趣,找到兴趣相同的其他用户,将其他用户喜欢而用户A没有的物品进行推荐。

算法步骤:

  1. 找到和目标用户兴趣相似的用户集合;
  2. 找到这个集合中用户喜欢的,且目标用户没有的物品推荐给用户。

算法缺点:
在该算法应用的场景中,用户的数目越大,计算用户相似度矩阵越难,其困难度体现在时间复杂度和空间复杂度上。

接下来,我们将通过movieslen数据集进行该算法的实现,其链接为movieslen数据集
在这里插入图片描述
在本次实验中,我们用了大小为1M的电影数据集,即链接中大小为955k的zip文件。其中的rating.csv文件字段里面的内容包含了每一个用户对于每一部电影的评分:
userId, movieId, rating, timestamp
userId: 每个用户的id
movieId: 每部电影的id
rating: 用户评分,是5星制,按半颗星的规模递增(0.5 stars - 5 stars)
timestamp: 自1970年1月1日零点后到用户提交评价的时间的秒数

代码流程如下:

  1. 找到每个用户和其所评论及未评论过的电影;
  2. 将每个用户的电影评分进行映射,每个用户电影评分形成一个onehot;
  3. 通过两两计算用户的onehot,得出每个用户最相近的用户个数;
  4. 再对每个用户没有评分的电影进行打分(通过上述与其相似的10个用户的电影评分作为分值);
  5. 按照最新的电影评分,向每个用户进行推送最相近的10个电影。
# -*- coding: utf-8 -*-
#!/usr/bin/env python
'''
author:limingqi
time:2020.01.22
titile:movieslens实现userCF算法
'''
import math
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
#加载文件路径
movies_path = '../ml-latest-small/movies.csv'
ratings_path = '../ml-latest-small/ratings.csv'
#读取文件内容
MoviesDF = pd.read_csv(movies_path,index_col=None)
RatingsDF = pd.read_csv(ratings_path,index_col=None)
#将数据按照4:1的比例进行分割
trains_ratingsDF,test_ratingsDF = train_test_split(RatingsDF,test_size=0.2)
#通过数据透视表对数据进行分析
train_ratings_provie = pd.pivot_table(trains_ratingsDF[['userId','movieId','rating']],
                                      columns=['movieId'],index=['userId'],values='rating',fill_value=0)
#获取电影id的索引
MoviesMap = dict(enumerate(list(train_ratings_provie.columns)))
#获取用户id的索引
UserMap = dict(enumerate(list(train_ratings_provie.index)))
#将每个用户对电影的打分进行抽取
RatingValues = train_ratings_provie.values.tolist()
#计算两个列表的余弦相似度
def CalconsineSimilarity(list1,list2):
    res = 0
    denominator1 = 0
    denominator2 = 0
    for (val1,val2) in zip(list1,list2):
        res += (val1 * val2)
        denominator1 += val1 ** 2
        denominator2 += val2 ** 2
    return res / (math.sqrt(denominator1 * denominator2))
#设定一个array,列行均为RatingValues的长度
UserSimMatrix = np.zeros((len(RatingValues),len(RatingValues)),dtype=np.float32)
#计算每个用户关系的余弦相似度
for i in range(len(RatingValues)-1):
    for j in range(i+1,len(RatingValues)):
        #UserSimMatrix为一个矩阵,因此只需计算一个上三角矩阵,下三角矩阵位置数值相同
        UserSimMatrix[i,j] = CalconsineSimilarity(RatingValues[i],RatingValues[j])
        UserSimMatrix[j,i] = UserSimMatrix[i,j]
#寻找每个用户最相近的k个用户
UserMostSimDict = dict()
for i in range(len(RatingValues)):
    UserMostSimDict[i] = sorted(enumerate(list(UserSimMatrix[i])),key=lambda x:x[1],reverse=True)[:10]
#计算每个用户对没有看过的电影进行打分
UserRecommendValues = np.zeros((len(RatingValues),len(RatingValues[0])),dtype=np.float32)
for i in range(len(RatingValues)):
    for j in range(len(RatingValues[i])):
        #如果RatingValues[i][j]==0,那么该用户没有对该电影进行打分,则进行计算
        if RatingValues[i][j] == 0:
            val = 0
            #通过对该用户最相似10个用户的电影评分计算该用户对此电影的评分
            for (user,sim) in UserMostSimDict[i]:
                val += (RatingValues[user][j] * sim)
            UserRecommendValues[i,j] = val
#通过最新的打分过后的电影,为每个用户推荐10部电影
UserRecommendDict = dict()
for i in range(len(RatingValues)):
    UserRecommendDict[i] = sorted(enumerate(list(UserRecommendValues[i])),key=lambda x:x[1],reverse=True)[:10]
#通过用户的索引id与用户真正id进行转化;通过电影的索引id与真正的电影id进行转化
UserRecommendList = []
for key,value in UserRecommendDict.items():
    user = UserMap[key]
    for MovieId,val in value:
        UserRecommendList.append([user,MoviesMap[MovieId]])
#通过推荐电影的id找到对应的电影名称,并将用户id、电影id、电影名称映射到一起,打印出来
RecommendDF = pd.DataFrame(UserRecommendList,columns=['userId','movieId'])
RecommendDF = pd.merge(RecommendDF,MoviesDF[['movieId','title']],on='movieId',how='inner')
print(RecommendDF.tail(10))

最终结果如下显示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_32113189/article/details/104074428