基于用户的协同过滤推荐算法的实现--以电影推荐为例

  • 数据集描述
  • 余弦相似度
  • 实现过程描述
  • 完整代码

数据集描述

数据包括:movies.csv和ratings.csv。movies.csv文档中包含三列属性,分别是movieId电影序号、title电影名称和genres电影类型。movies.csv文档中包含四列属性,分别是userId用户序号、movieId电影序号,rating用户评分(0.5-5,分值越高代表越好)第四列属性不用考虑。在该电影系统中使用了610个用户为9742部电影打分,生成了100836行的数据集。

余弦相似度

公式引用了博客园蝈蝈俊的文章《余弦相似度Cosine Similarity相关计算公式 》中写的文章,文末附链接。
假定A和B是两个n维向量,A是 [A1, A2, …, An] ,B是 [B1, B2, …, Bn] ,则A与B的夹角θ的余弦等于:


根据公式,我写了计算两用户之间的余弦相似度,代码如下:

def CosFunction(test, user):        # 计算两用户之间余弦相似度sum1 = 0sum2 = 0sum3 = 0for i in range(len(test)):sum1 = sum1 + test[i] * user[i]sum2 = sum2 + math.pow(test[i],2)sum3 = sum3 + math.pow(user[i],2)CosTotal = sum1/ (math.sqrt(sum2) * math.sqrt(sum3))# print(CosTotal)return CosTotal

实现过程描述

首先我们对读取文件,用list二维列表保存电影和用户对电影的评分结果
行表示电影和用户对电影的评分,列为电影的属性和评分结果
用movies,ratings分别存储两个函数返回的结果。

def read_movie(filename):with open (filename, encoding='utf-8') as f:reader = csv.reader(f)movies = [[row[0],row[1],row[2]] for row in reader]return moviesdef read_userRating(filename):# userId, movieId, rating, timestampwith open(filename, encoding='utf-8')as f:reader = csv.reader(f)ratings = [[row[0], row[1], row[2]] for row in reader]return ratings

之后我们根据电影和评分列表数据生成每个用户对看过的电影的评分列表

def ratingsArray(movies, ratings):      # 生成评分矩阵user_rating_array = []number = 0user_rating_list = []for userRating in ratings:          # 建立用户的评分列表集合if str(number) == userRating[0]:user_rating_list.append([userRating[1], userRating[2]])# print(number,userRating[0],userRating[1], userRating[2])else:user_rating_array.append([number, user_rating_list])# print(number, user_rating_list)user_rating_list = []number = number + 1user_rating_list.append([userRating[1], userRating[2]])user_rating_array.append([number, user_rating_list]) # 添加最后一个# print(user_rating_array)return user_rating_array

评分列表显示如下

在为目标用户选出推荐的电影之前,我们先生成单个用户对所有电影的评分矩阵.
用户传入单个用户对看过电影评分的列表,根据所有电影生成用户对所有电影的评分矩阵。

def GetAllMovieRating(user_rating, movies):     # 单个用户对九千多部电影的评分矩阵userAllMovieRating = []# print(user_rating)for movie in movies:movieId = movie[0]userRating = 0for userMovieId, userMovieRating in user_rating:if movieId == userMovieId:userRating = float(userMovieRating)breakuserAllMovieRating.append(userRating)userAllMovieRating[0] = 0       # 把下标为0项置为0 下标为0不代表是电影return userAllMovieRating

评分结果显示如下,对于没看过的电影,评分为0。一行为一个用户对所有电影的评分。

我们选取用户id为10的用户作为目标用户,根据所有用户的评分数据集,找到与目标用户相似的前20个用户,为目标用户选出推荐的电影。代码思想如下:
首先遍历610个用户,为每个用户生成评分矩阵,并根据每个用户的评分向量求该用户与目标用户的余弦相似度 。用列表保存每个用户的id和该用户与目标用户余弦相似度结果,根据余弦相似度结果排序,选取前20个用户。并用这20个用户的id再一次生成他们对所有电影的评分矩阵,用它们的余弦相似度求和并开平方,方便后面计算推荐电影评分。

def CosSimilarity(UserId, user_rating_list, movies):testAllMovieRating = GetAllMovieRating(user_rating_list[UserId][1], movies)print(UserId, testAllMovieRating)resCos = []for id in range(len(user_rating_list)):if id == UserId or id == 0:continueuserAllMovieRating = GetAllMovieRating(user_rating_list[id][1], movies)print(id, userAllMovieRating)# 计算余弦相似度Cos = CosFunction(testAllMovieRating, userAllMovieRating)resCos.append([id, Cos])print(resCos)# key=(lambda x:x[1]),reverse=Trueres1 = sorted(resCos, key = (lambda x:x[1]), reverse = True)    # 取前20个与目标用户相似的用户res1 = res1[:20]print(res1)# 求前20个用户的所有电影评分矩阵res1AllMovieRating = []for item in res1:userAllMovieRating = GetAllMovieRating(user_rating_list[item[0]][1], movies)print(item[0], userAllMovieRating)res1AllMovieRating.append([item[0], userAllMovieRating])# 前20个用户的Cos余弦相似度求和sum2 = 0for i in range(len(res1)):sum2 = sum2 + math.sqrt(res1[i][1])# sum2 = math.sqrt(sum2)print(sum2)# 求所有电影对目标用户的推荐评分,目标用户看过的电影推荐评分设置为0MovieRecommend = []for i in range(len(testAllMovieRating)):recommend = 0sum1 = 0for j in range(len(res1)):sum1 = sum1 + res1[j][1] * float(res1AllMovieRating[j][1][i])recommend = sum1 / sum2if testAllMovieRating[i] != 0:recommend = 0MovieRecommend.append([i,recommend])print(MovieRecommend)MovieTop = sorted(MovieRecommend, key = (lambda x:x[1]), reverse=True)     # 根据推荐评分对电影排序print(MovieTop)Recommend = MovieTop[:20]print(Recommend)return Recommend

余弦相似度结果如图所示,我们发现,用户id为159,143的用户和id为10的目标用户比较相似。

推荐评分结果如下图所示,第7373个电影的推荐评分为1.4.

最后返回推荐电影的结果,根据推荐电影的下标号输出推荐电影的名称
对目标用户10推荐结果如下,我们从推荐结果可以看到,该用户比较喜欢看动作类和冒险类的电影。

完整代码

import math
import csv
def read_movie(filename):with open (filename, encoding='utf-8') as f:reader = csv.reader(f)movies = [[row[0],row[1],row[2]] for row in reader]return moviesdef read_userRating(filename):# userId, movieId, rating, timestampwith open(filename, encoding='utf-8')as f:reader = csv.reader(f)ratings = [[row[0], row[1], row[2]] for row in reader]return ratingsdef ratingsArray(movies, ratings):      # 生成评分矩阵user_rating_array = []number = 0user_rating_list = []for userRating in ratings:          # 建立用户的评分列表集合if str(number) == userRating[0]:user_rating_list.append([userRating[1], userRating[2]])# print(number,userRating[0],userRating[1], userRating[2])else:user_rating_array.append([number, user_rating_list])# print(number, user_rating_list)user_rating_list = []number = number + 1user_rating_list.append([userRating[1], userRating[2]])user_rating_array.append([number, user_rating_list]) # 添加最后一个# print(user_rating_array)return user_rating_arraydef CosSimilarity(UserId, user_rating_list, movies):# test_rating_list = user_rating_list[UserId][1]testAllMovieRating = GetAllMovieRating(user_rating_list[UserId][1], movies)print(UserId, testAllMovieRating)# print(test_rating_list)# print(len(user_rating_list))  # 611个,包含下标0resCos = []for id in range(len(user_rating_list)):if id == UserId or id == 0:continueuserAllMovieRating = GetAllMovieRating(user_rating_list[id][1], movies)# print(id, userAllMovieRating)# 计算余弦相似度Cos = CosFunction(testAllMovieRating, userAllMovieRating)resCos.append([id, Cos])print(resCos)# key=(lambda x:x[1]),reverse=Trueres1 = sorted(resCos, key = (lambda x:x[1]), reverse = True)    # 取前20个与目标用户相似的用户res1 = res1[:20]print(res1)# 求前20个用户的所有电影评分矩阵res1AllMovieRating = []for item in res1:userAllMovieRating = GetAllMovieRating(user_rating_list[item[0]][1], movies)print(item[0], userAllMovieRating)res1AllMovieRating.append([item[0], userAllMovieRating])# 前20个用户的Cos余弦相似度求和sum2 = 0for i in range(len(res1)):sum2 = sum2 + math.sqrt(res1[i][1])# sum2 = math.sqrt(sum2)print(sum2)# 求所有电影对目标用户的推荐评分,目标用户看过的电影推荐评分设置为0MovieRecommend = []for i in range(len(testAllMovieRating)):recommend = 0sum1 = 0for j in range(len(res1)):sum1 = sum1 + res1[j][1] * float(res1AllMovieRating[j][1][i])recommend = sum1 / sum2if testAllMovieRating[i] != 0:recommend = 0MovieRecommend.append([i,recommend])print(MovieRecommend)MovieTop = sorted(MovieRecommend, key = (lambda x:x[1]), reverse=True)     # 根据推荐评分对电影排序print(MovieTop)Recommend = MovieTop[:20]print(Recommend)return Recommenddef CosFunction(test, user):        # 计算两用户之间余弦相似度sum1 = 0sum2 = 0sum3 = 0for i in range(len(test)):sum1 = sum1 + test[i] * user[i]sum2 = sum2 + math.pow(test[i],2)sum3 = sum3 + math.pow(user[i],2)CosTotal = sum1/ (math.sqrt(sum2) * math.sqrt(sum3))# print(CosTotal)return CosTotaldef GetAllMovieRating(user_rating, movies):     # 单个用户对九千多部电影的评分矩阵userAllMovieRating = []# print(user_rating)for movie in movies:movieId = movie[0]userRating = 0for userMovieId, userMovieRating in user_rating:if movieId == userMovieId:userRating = float(userMovieRating)breakuserAllMovieRating.append(userRating)userAllMovieRating[0] = 0       # 把下标为0项置为0 下标为0不代表是电影return userAllMovieRatingdef RecommendMovies(movies, recommend):for item, item2 in recommend:print(movies[item][1], '\t' , movies[item][2])if __name__=='__main__':movies = read_movie('movies.csv')ratings = read_userRating('ratings.csv')user_rating_list = ratingsArray(movies, ratings)recommend =  CosSimilarity(10, user_rating_list,movies)RecommendMovies(movies, recommend)

相关链接
https://www.cnblogs.com/ghj1976/p/yu-xian-xiang-shi-ducosine-similarity-xiang-guan-j.html

基于用户的协同过滤推荐算法的实现--以电影推荐为例相关推荐

  1. [推荐算法]UserCF,基于用户的协同过滤算法

    UserCF:UserCollaborationFilter,基于用户的协同过滤 算法核心思想:在一个在线推荐系统中,当用户A需要个性化推荐时,可以先找到和他有相似兴趣的其它用户,然后把那些用户喜欢的 ...

  2. 【知识发现】基于用户的协同过滤推荐算法python实现

    1.协同过滤推荐算法分为两类,分别是基于用户的协同过滤算法(user-based collaboratIve filtering),和基于物品的协同过滤算法(item-based collaborat ...

  3. 协同过滤算法_基于用户的协同过滤推荐算法原理和实现

    (给算法爱好者加星标,修炼编程内功) 来源:Create Chen's Blog https://www.cnblogs.com/technology/p/4467895.html 在推荐系统众多方法 ...

  4. python协同过滤可以预测吗_基于用户的协同过滤推荐算法原理-附python代码实现...

    在推荐系统众多方法中,基于用户的协同过滤推荐算法是最早诞生的,原理也较为简单.该算法1992年提出并用于邮件过滤系统,两年后1994年被 GroupLens 用于新闻过滤.一直到2000年,该算法都是 ...

  5. 基于用户的协同过滤推荐算法原理和实现

    在推荐系统众多方法中,基于用户的协同过滤推荐算法是最早诞生的,原理也较为简单.该算法1992年提出并用于邮件过滤系统,两年后1994年被 GroupLens 用于新闻过滤.一直到2000年,该算法都是 ...

  6. 基于用户的协同过滤推荐算法原理和实现分析

    本文转载自nieson  基于用户的协同过滤推荐算法原理和实现 在推荐系统众多方法中,基于用户的协同过滤推荐算法是最早诞生的,原理也较为简单.该算法1992年提出并用于邮件过滤系统,两年后1994年被 ...

  7. (一)基于用户的协同过滤推荐算法原理和实现

    在推荐系统众多方法中,基于用户的协同过滤推荐算法是最早诞生的,原理也较为简单.该算法1992年提出并用于邮件过滤系统,两年后1994年被 GroupLens 用于新闻过滤.一直到2000年,该算法都是 ...

  8. 如何使用Java+SSM(Spring+SpringMVC+Mybatis)开发个性化新闻推荐系统 在线新闻推荐系统 基于用户项目协同过滤、内容、聚类、关联规则推荐算法实现WebNewsRSMEx

    如何使用Java+SSM(Spring+SpringMVC+Mybatis)开发个性化新闻推荐系统 在线新闻推荐系统 基于用户项目协同过滤.内容.聚类.关联规则推荐算法实现WebNewsRSMEx 一 ...

  9. mysql数据推荐算法_Java+Mysql实现简单在线电影、音乐、图书推荐系统 基于用户的协同过滤推荐算法实现 源代码下载...

    # Java+Mysql实现简单在线电影.音乐.图书等推荐系统(基于用户的协同过滤推荐算法) 一.项目简介 1.开发工具和实现技术 MyEclipse10,jdk1.7,mysql5.5,tomca ...

  10. python协同过滤电影推荐_python实现基于用户的协同过滤算法(CF)——以电影评价数据(ml-100k)为例...

    程序简介 项目以ml-100k电影评分数据集为输入,实现了基于用户的协同过滤算法,最后预测的MAE为0.84,因为经过优化,10万条评分数据运行时间不超过2分钟 协同过滤算法(CF)基于对用户历史行为 ...

最新文章

  1. 基于C++实现线程池加速
  2. 用 Python 识别图片中的文字
  3. deploy mysql_Deploy Mysql
  4. anaconda + pycharm安装教程补充
  5. 别样的1024程序员节“无Bug市集”
  6. oracle如何查看剩余表空间,oracle 查看各表空间剩余量
  7. c语言实现输入电压检测,STC12C2052AD单片机AD转换C语言程序的实现
  8. 用pywinauto抓取微信公众号
  9. flask项目中出现Error: While importing ‘manager‘, an ImportError was raised.
  10. dcos - 安装docker
  11. 解决uniapp调试过程中的请求跨域和环境配置
  12. 【CS231n】斯坦福大学李飞飞视觉识别课程笔记(十九):卷积神经网络笔记(下)
  13. 五金行业:强行业性的进销存系统具体看三项
  14. 3D Game Programming Design:UI系统--Quest Log 公告牌
  15. QR码编码原理二(编码)
  16. 草根seo站长利用网站赚钱的方法 1
  17. CentOS7 使用二进制部署 Kubernetes v1.15.3集群
  18. Mysql 修改密码 (亲测)
  19. 独秀日记:刚抱了*冰冰睡觉一个星期,就开始想*子怡了
  20. unity 手机重力迷宫(三)

热门文章

  1. 杭电ACM-LCY算法进阶培训班-专题训练(Hash及其应用)
  2. 相机焦距、像元大小构造内参矩阵
  3. 老Java程序员花两天做了个消消乐(天天爱消除)
  4. oc 中正则表达式不区分中英文分号的问题
  5. AT89C51单片机制作简易密码锁
  6. java 图片 pdf_Java 添加图片到PDF
  7. Ubuntu16.04下用umake安装vscode
  8. GD32F450以太网(1):ETH 外设接口简介
  9. 华为设备配置基于MSDP的Anycast RP
  10. SELinux audit2allow命令使用