1. #!/usr/bin/env python2
  2. # -*- coding: utf-8 -*-
  3. """
  4. Created on Tue Feb  7 14:38:33 2017
  5. 电影推荐分析:
  6. 使用 亲和性分析方法 基于 Apriori算法 推荐电影
  7. @author: yingzhang
  8. """
  9. #读取数据集: http://grouplens.org/datasets/movielens/
  10. import os
  11. #使用pandas加载数据
  12. import pandas as pd
  13. '''''
  14. 1m数据集读取方法
  15. '''
  16. #data_folder=os.path.join( os.path.expanduser("~"),"ml-1m")
  17. #ratings_filename=os.path.join( data_folder,"ratings.dat")
  18. #all_ratings=pd.read_csv( ratings_filename, delimiter="::",header=None, names=["UserID","MovieID","Rating","Datetime"])
  19. '''''
  20. 100k数据集读取方法
  21. '''
  22. data_folder=os.path.join( os.path.expanduser("~"),"ml-100k")
  23. #获取用户评分数据
  24. ratings_filename=os.path.join( data_folder,"u.data")
  25. all_ratings=pd.read_csv( ratings_filename, delimiter="\t",header=None, names=["UserID","MovieID","Rating","Datetime"])
  26. all_ratings[:1]
  27. #输出的数据格式如下
  28. '''''
  29. UserID  MovieID  Rating   Datetime
  30. 0       1     1193       5  978300760
  31. '''
  32. #时间格式要转换一下
  33. all_ratings["Datetime"]=pd.to_datetime(all_ratings["Datetime"],unit='s')
  34. all_ratings[:1]
  35. #新增一列,用来存用户对某个电影是否喜欢 ( 如果评分大于3)
  36. all_ratings["Favorable"]=all_ratings["Rating"]>3
  37. all_ratings[:10]
  38. #输出的数据格式如下: Favorable这一列的数据表明用户是否喜欢这部电影
  39. '''''
  40. UserID  MovieID  Rating            Datetime Favorable
  41. 0       1     1193       5 2000-12-31 22:12:40      True
  42. 1       1      661       3 2000-12-31 22:35:09     False
  43. '''
  44. #从数据集中取前200名用户的打分数据作训练集
  45. ratings=all_ratings[  all_ratings['UserID'].isin(range(200))]
  46. #过滤一次数据,只保留用户喜欢的电影(即 Favorable为True值的)
  47. favorable_ratings=ratings[ratings["Favorable"]]
  48. favorable_ratings[:5]
  49. #因为要生成频繁项集,所以我们只对打分超过一次的用户感兴趣,所以按照UserID分组,并遍历每个用户看过的每一部电影,存到一个字典中
  50. from collections import defaultdict
  51. favorable_reviews_by_users=dict((k,frozenset(v.values))
  52. for k,v in favorable_ratings.groupby("UserID")["MovieID"])
  53. print("length: {0}".format( len(favorable_reviews_by_users) ) )
  54. #再创建一个数据框,存入每部电影评价分为3分以上的人数( 即 Favorable为True)的数量
  55. num_favorable_by_movie=ratings[["MovieID","Favorable"]].groupby("MovieID").sum()
  56. #查看结果
  57. num_favorable_by_movie
  58. #排序输出前五名
  59. num_favorable_by_movie.sort( "Favorable",ascending=False)[:5]
  60. #创建一个函数,它接收新发现的频繁项集,创建超集,检测频繁程度
  61. '''''
  62. favorable_reviews_by_users: 用户打分情况的集合
  63. k_1_itemsets: 上一个频繁项集
  64. min_support:最小支持度
  65. 返回值格式:
  66. dict( 频繁项集    支持度 )
  67. '''
  68. def find_frequent_itemsets( favorable_reviews_by_users, k_1_itemsets, min_support):
  69. counts=defaultdict( int )
  70. #循环用户和他们的打分数据
  71. for user,reviews in favorable_reviews_by_users.items():
  72. #再循环前一次找出的频繁项集,判断它们是否为 reviews的子集,
  73. for itemset in k_1_itemsets:
  74. if itemset.issubset( reviews):  #如果是,表明用户已经为子集中的电影打过分了
  75. #那么接下来,就要遍历用户打过分却没有出现在项集reviews中的电影了,因为这样可以用它来生成超集,更新该项集的计数
  76. for other_reviewed_movie in reviews-itemset: #other_reviewed_movie 用户打过分,但还不在频繁项集中
  77. current_superset=itemset|frozenset( (other_reviewed_movie,))
  78. counts[current_superset]+=1    #这个频繁项集的数量支持度+1
  79. #函数最后检测达到支持度要求的项集,只返回频繁度够的频繁项集
  80. return dict(  [(itemset,frequency) for itemset,frequency in counts.items()  if frequency>=min_support   ]           )
  81. import sys
  82. #创建一个字典,存不同长度的频繁项集
  83. #数据格式:
  84. #频繁项集长度   对应的频繁项集
  85. frequent_itemsets={}
  86. min_support=50   #要求的最小支持度
  87. #从频繁项集长度为1的开始,并且支持度要大于50
  88. frequent_itemsets[1]= dict((frozenset((movie_id,)),row["Favorable"]) for movie_id,row in num_favorable_by_movie.iterrows() if row["Favorable"]>min_support)
  89. #输出频繁集长度为1,支持度大于50的所有的电影信息
  90. frequent_itemsets[1]
  91. print("there are {0} movie with more than {1} favorable reviews".format( len(frequent_itemsets[1]), min_support))
  92. sys.stdout.flush()   #将缓冲区的内容输出到终端
  93. #定义要找的频繁集的最大长度
  94. max_length=20
  95. #循环频繁集长度从2到 max_length
  96. for k in range(2, max_length):
  97. cur_frequent_itemsets=find_frequent_itemsets(  favorable_reviews_by_users,  frequent_itemsets[k-1], min_support   )
  98. if len(cur_frequent_itemsets)==0:
  99. print("can not find any frequent itemsets of length {0}".format( k ))
  100. sys.stdout.flush()
  101. break
  102. else:
  103. print(" find {0} frequent itemsets of length {1}".format(len(cur_frequent_itemsets), k))
  104. print("\t data as following:")
  105. #print( cur_frequent_itemsets )
  106. sys.stdout.flush()
  107. frequent_itemsets[k]=cur_frequent_itemsets
  108. # del itemsets of length 1
  109. #del frequent_itemsets[1]
  110. #######################################################################
  111. #以上Apriori算法结束后,得到了一系列的频繁项集,但它还不是关联规则。频繁项集是一组达到最小支持度的项目,而关联规则是由前提和结论组成
  112. #从频繁项集中抽取关联规则,把其中几部电影作为前提,另一部电影作为结论组成规则: 如果用户喜欢xx,yy,zz,那么他们也会喜欢ttt
  113. #遍历频繁项集,为每个项集生成规则
  114. candidate_rules=[]
  115. #itemset_length 频繁项集长度
  116. # itemset_counts :  (itemset,frequency)
  117. for itemset_length,itemset_counts in frequent_itemsets.items():
  118. #取出itemset_counts中的每个键,{电影1,电影2,...}
  119. for itemset in itemset_counts.keys():
  120. #循环频繁项集中的每部电影,生成条件和结论
  121. for conclusion in itemset:
  122. premise=itemset-set((conclusion,))
  123. candidate_rules.append((premise,conclusion))
  124. print("there are {0} candidate rules".format( len(candidate_rules)))
  125. #print("the rules as following:")
  126. #print( candidate_rules)
  127. #######################################################################
  128. #计算每条规则的置信度:
  129. #先用两个字典存规则应验, 规则不适用数量
  130. correct_counts=defaultdict(int)   #规则应验
  131. incorrect_counts=defaultdict(int)    #规则不适用
  132. #循环所有的用户及他们喜欢的电影
  133. for user, reviews in favorable_reviews_by_users.items():
  134. #循环所有的规则
  135. for candidate_rule in candidate_rules:
  136. premise,conclusion=candidate_rule
  137. #判断前提是否是 reviews中的一个子集, 并且结论也在 reviews中,说明这条规则应验,否则不适用
  138. if premise.issubset(reviews):
  139. if conclusion in reviews:
  140. correct_counts[candidate_rule]+=1
  141. else:
  142. incorrect_counts[candidate_rule]+=1
  143. #计算置信度
  144. rule_confidence={candidate_rule: correct_counts[candidate_rule]/ float(correct_counts[candidate_rule]+incorrect_counts[candidate_rule]) for candidate_rule in candidate_rules}
  145. #设定最低置信度
  146. min_confidence=0.9
  147. #过滤掉小于最低置信度的规则
  148. rule_confidence={candidate_rule:  confidence for    candidate_rule,confidence in rule_confidence.items() if confidence>min_confidence}
  149. print( "the total of rules which bigger than min_confidence is {}".format( len(rule_confidence )) )
  150. #排序输出前五条置信度最高的规则
  151. from operator import itemgetter
  152. sorted_confidence=sorted( rule_confidence.items(),key=itemgetter(1),reverse=True)
  153. for index in range(5):
  154. print("Rule #{0}".format(index+1))
  155. (premise,conclusion)=sorted_confidence[index][0]
  156. print("Rule: if a person recommends {0} they will also recommend {1}".format( premise, conclusion))
  157. print( " - Confidence: {0:.3f}".format( rule_confidence[(premise,conclusion)]))
  158. print("")
  159. #######################################################################
  160. #加载电影的名字
  161. #100k数据集取法
  162. movie_name_filename=os.path.join( data_folder,"u.item")
  163. movie_name_data=pd.read_csv(movie_name_filename,delimiter="|",header=None,encoding="mac-roman")
  164. movie_name_data.columns=["MovieID", "Title", "Release Date", "Video Release", "IMDB", "<UNK>", "Action", "Adventure",
  165. "Animation", "Children's", "Comedy", "Crime", "Documentary", "Drama", "Fantasy", "Film-Noir",
  166. "Horror", "Musical", "Mystery", "Romance", "Sci-Fi", "Thriller", "War", "Western"]
  167. #定义一个查找电影名的函数
  168. def get_movie_name(movie_id):
  169. title_object=movie_name_data[movie_name_data["MovieID"]==movie_id]["Title"]
  170. title=title_object.values[0]
  171. return title
  172. #测试这个函数
  173. get_movie_name(4)
  174. #重新排序输出前五条置信度最高的规则
  175. for index in range(5):
  176. print("Rule #{0}".format(index+1))
  177. (premise,conclusion)=sorted_confidence[index][0]
  178. premise_names=",".join( get_movie_name(idx) for idx in premise  )
  179. conclusion_name=get_movie_name( conclusion)
  180. print("Rule: if a person recommends {0} they will also recommend {1}".format( premise_names, conclusion_name))
  181. print( " - Confidence: {0:.3f}".format( rule_confidence[(premise,conclusion)]))
  182. print("")
  183. #######################################################################
  184. #评估: 寻找最好的规则.
  185. #抽取所有没有用于训练的数据作为测试集, 训练集数据用了前200名用户的打分数据,测试集用其它的数据即可
  186. test_dataset=  all_ratings[~all_ratings['UserID'].isin(range(200))]
  187. test_favorable_ratings=test_dataset[test_dataset["Favorable"]]
  188. test_favorable_reviews_by_users=dict((k,frozenset(v.values))
  189. for k,v in test_favorable_ratings.groupby("UserID")["MovieID"])
  190. #计算规则应验的数量
  191. test_correct_counts=defaultdict(int)   #规则应验
  192. test_incorrect_counts=defaultdict(int)    #规则不适用
  193. #循环所有的用户及他们喜欢的电影
  194. for user, reviews in test_favorable_reviews_by_users.items():
  195. #循环所有的规则
  196. for candidate_rule in candidate_rules:
  197. premise,conclusion=candidate_rule
  198. #判断前提是否是 reviews中的一个子集, 并且结论也在 reviews中,说明这条规则应验,否则不适用
  199. if premise.issubset(reviews):
  200. if conclusion in reviews:
  201. test_correct_counts[candidate_rule]+=1
  202. else:
  203. test_incorrect_counts[candidate_rule]+=1
  204. #计算置信度
  205. test_rule_confidence={candidate_rule: test_correct_counts[candidate_rule]/ float(test_correct_counts[candidate_rule]+test_incorrect_counts[candidate_rule]) for candidate_rule in candidate_rules}
  206. print( len(test_rule_confidence))
  207. #最后排序输出前五名
  208. sorted_test_confidence=sorted(  test_rule_confidence.items(),key=itemgetter(1),reverse=True )
  209. print( sorted_test_confidence[:5])
  210. #输出规则信息
  211. for index in range(10):
  212. print("Rule #{0}".format(index+1))
  213. (premise,conclusion)=sorted_confidence[index][0]
  214. premise_names=",".join( get_movie_name(idx) for idx in premise  )
  215. conclusion_name=get_movie_name( conclusion)
  216. print("Rule: if a person recommends {0} they will also recommend {1}".format( premise_names, conclusion_name))
  217. print( " - Train Confidence: {0:.3f}".format( rule_confidence[(premise,conclusion)]))
  218. print( " - Test Confidence: {0:.3f}".format( test_rule_confidence[(premise,conclusion)]))
  219. print("")

数据挖掘-MovieLens数据集_电影推荐_亲和性分析_Aprioro算法的更多相关文章

  1. 数据挖掘-diabetes数据集分析-糖尿病病情预测_线性回归_最小平方回归

    # coding: utf-8 # 利用 diabetes数据集来学习线性回归 # diabetes 是一个关于糖尿病的数据集, 该数据集包括442个病人的生理数据及一年以后的病情发展情况. # 数据 ...

  2. Flutter实战视频-移动电商-15.首页_商品推荐模块编写

    15.首页_商品推荐模块编写 商品推荐,我们做成可以横向滚动的 分析: 上面是标题,下面是ListView,里面是一个Column, column分三层,第一是图片,第二是价格,第三是市场价格 小细节 ...

  3. SparkML之推荐引擎(一)---电影推荐

    本文将使用 SparkML 来构建推荐引擎. 推荐引擎算法大致分为 基于内容的过滤.协同过滤.矩阵分解,本文将使用基于属于矩阵分解的 最小二乘法 算法来构建推荐引擎. 对于推荐引擎模块这里将分为两篇文 ...

  4. 基于mllib的协同过滤实战(电影推荐)

    //加载需要的包 import org.apache.spark.rdd._ import org.apache.spark.mllib.recommendation.{ALS, Rating, Ma ...

  5. 利用Surprise包进行电影推荐

    Surprise(Simple Python Recommendation System Engine)是一款推荐系统库,是scikit系列中的一个.简单易用,同时支持多种推荐算法(基础算法.协同过滤 ...

  6. 【大数据 Spark】利用电影观看记录数据,进行电影推荐

    利用电影观看记录数据,进行电影推荐. 目录 利用电影观看记录数据,进行电影推荐. 准备 1.任务描述: 2.数据下载 3.部分数据展示 实操 1.设置输入输出路径 2.配置spark 3.读取Rati ...

  7. 人工智能大数据,公开的海量数据集下载,ImageNet数据集下载,数据挖掘机器学习数据集下载

    人工智能大数据,公开的海量数据集下载,ImageNet数据集下载,数据挖掘机器学习数据集下载 ImageNet挑战赛中超越人类的计算机视觉系统微软亚洲研究院视觉计算组基于深度卷积神经网络(CNN)的计 ...

  8. 利用python实现电影推荐

    "协同过滤"是推荐系统中的常用技术,按照分析维度的不同可实现"基于用户"和"基于产品"的推荐. 以下是利用python实现电影推荐的具体方法 ...

  9. 转利用python实现电影推荐

    “协同过滤”是推荐系统中的常用技术,按照分析维度的不同可实现“基于用户”和“基于产品”的推荐. 以下是利用python实现电影推荐的具体方法,其中数据集源于<集体编程智慧>一书,后续的编程 ...

随机推荐

  1. python 抽象类和接口类

    一.接口类 继承的两种用途: 1.继承基类的方法,并且做出自己的改变或者扩展(代码重用) 2.声明某个子类兼容于某个基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数 名)  ...

  2. redis3.0.6版本的info信息解读

    127.0.0.1:6379> info# Serverredis_version:3.0.6redis_git_sha1:00000000redis_git_dirty:0redis_buil ...

  3. stdlib.h中自带的两个算法qsort,bsearch

    http://zh.cppreference.com/w/c/algorithm ========== void qsort( void *ptr, size_t count, size_t size ...

  4. maven学习(十)——maven生命周期以及插件

    一.生命周期 1.何为生命周期? Maven生命周期就是为了对所有的构建过程进行抽象和统一,包括项目清理,初始化,编译,打包,测试,部署等几乎所有构建步骤 2.Maven三大生命周期 Maven有三套 ...

  5. linux常用命令(复制)

    显示目录和文件的命令    Ls:用于查看所有文件夹的命令. Dir:用于显示指定文件夹和目录的命令   Tree: 以树状图列出目录内容 Du:显示目录或文件大小 修改目录,文件权限和属主及数组命令 ...

  6. [转]完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法

    HTML5的语义化标签以及属性,可以让开发者非常方便地实现清晰的web页面布局,加上CSS3的效果渲染,快速建立丰富灵活的web页面显得非常简单. HTML5的新标签元素有: <header&g ...

  7. 使用BootStrap网格布局进行一次演示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. [luogu1357] 花园 [dp+矩阵快速幂]

    题面: 传送门 思路: 把P形花圃记录为0,C形记录为1,那么一段花圃就可以状态压缩成一个整数 那么,我们可以有这样的状压dp: dp[i][S]表示前i个花圃,最后m个的状态为S的情况 如果这是一条 ...

  9. 在npm当中发布自己的包的方法

    首先需要一个注册一个npm账号,注意,必须验证邮箱,不然是无法发布包的!下面是当时的报错 接着在你需要发布的包的文件夹下面打开你的cmd或者其他的命令行输入工具  输入  npm init 初始化你的 ...

  10. 远程连接linux和linux的网络配置

    linux一般是作为服务器的,并不直接对其进行操作,并且由于地理位置的原因,我们需要对linux服务器进行远程连接. 首先我们要确定linux服务器是否安装了ssh服务,在linux服务器上安装ope ...