• 数据挖掘-MovieLens数据集_电影推荐_亲和性分析_Aprioro算法


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