您的位置:首页 > 编程语言 > Python开发

《python数据挖掘入门与实践》“电影推荐” 笔记3

2017-03-15 20:28 781 查看
数据来源:http://download.csdn.net/detail/zhongwen7710/8510549
原网址数据下载很慢,这里感谢网友分享。

在商品推荐的章节,用的方法是把所有的规则组合的方式,这样当数据集合n比较大的时候,需要求的组合数是2的n次幂,不便于计算。 因此这里使用的是另一种算法  Apriori算法。
算法的主要思想:
(1) 把各项目放到只包含自己的项集中,生成最初的频繁项集。只使用达到最小支持度的项目。
(2) 查找现有频繁项集的超集,发现新的频繁项集,并用其生成新的备选项集。
(3) 测试新生成的备选项集的频繁程度,如果不够频繁,则舍弃。如果没有新的频繁项集,就跳到最后一步。
(4) 存储新发现的频繁项集,跳到步骤(2)。
(5) 返回发现的所有频繁项集。

当找到所有的频繁项集合时候,我们设频繁项中的某电影为x,其他的电影为Y=S-x,那么就能得到一些规则:当喜欢看Y电影的时候,一般也会喜欢看x电影。

import os
import pandas as pd
import sys
all_ratings=pd.read_csv('u.data',delimiter='\t',header=None,names=["UserID","MovieID","Rating","Datetime"])
#把分隔符作为制表符号,并且第一行不是表头,设置每列的名称,时间戳数据得转换后使用
all_ratings["Datetime"]=pd.to_datetime(all_ratings["Datetime"],unit='s')
#print(all_ratings[:5])
#实现Apriori算法,最终的目标是找到一个规则:如果用户喜欢看某些电影,那么他们也会喜欢这部电影
all_ratings["Favorable"]=(all_ratings["Rating"]>3)
#print(all_ratings[:5])

#取前200名用户的数据作为训练数据
ratings=all_ratings[all_ratings["UserID"].isin(range(200))]
#ratings["Favorable"]返回的是一个true和false的列表。再加一层ratings[],就是把所有是true的行提取
favorable_ratings=ratings[ratings["Favorable"]]
#.groupby   书中少了"."   返回的是一个列表,为每个用户及所喜欢的电影的编号
favorable_reviews_by_users = dict((k, frozenset(v.values)) for k, v in favorable_ratings.groupby("UserID")["MovieID"])
#返回的是每部电影的影迷数
num_favorable_by_movie=ratings[["MovieID","Favorable"]].groupby("MovieID").sum()

#上面的所有步骤为算法的实现做好了数据处理的步骤,接下来就是算法的部分了

frequent_itemsets={}
min_support=50
#1个频繁项的集合
frequent_itemsets[1]=dict((frozenset((movie_id,)),row["Favorable"])for movie_id ,row in num_favorable_by_movie.iterrows() if row["Favorable"]>min_support)
#print(frequent_itemsets[1])
from collections import defaultdict
def find_frequent_itemsets(favorable_reviews_by_users,k_1_itemsets,min_support):
counts=defaultdict(int)
#遍历所有用户和打分
for user,reviews in favorable_reviews_by_users.items():
#遍历找到的频繁项集合,判断他们时候是当前评分集合的自己,如果是则表明用户已经为这个电影打分过
for itemset in k_1_itemsets:
if itemset.issubset(reviews):
for other_reviewed_movie in reviews-itemset:
current_superset=itemset|frozenset((other_reviewed_movie,))
counts[current_superset]+=1
return dict([(itemset,frequency) for itemset, frequency in counts.items() if frequency>=min_support])
#循环运行函数,频繁项集最大设到19
for k in range(2,20):
cur_frequent_itemsets=find_frequent_itemsets(favorable_reviews_by_users,frequent_itemsets[k-1],min_support)
frequent_itemsets[k]=cur_frequent_itemsets
#当频繁项集合不再增大时候就终止循环
if len(cur_frequent_itemsets)==0:
print("Did not find any frequent itemsets of length {}".format(k))
sys.stdout.flush()
break
else:
print("I found {} frequent itemsets of length{}".format(len(cur_frequent_itemsets), k))
sys.stdout.flush()
del frequent_itemsets[1]

#把所有的频繁项集合生成规则
candidate_rules=[]
for itemset_length, itemset_counts in frequent_itemsets.items():
for itemset in itemset_counts.keys():
for conclusion in itemset:
premise = itemset - set((conclusion,))
candidate_rules.append((premise, conclusion))
#print(candidate_rules[:20])
#计算规则符合和不符合的次数
correct_counts = defaultdict(int)
incorrect_counts = defaultdict(int)
for user,reviews in favorable_reviews_by_users.items():
for candidate_rule in candidate_rules:
premise,conclusion=candidate_rule
if premise.issubset(reviews):
if conclusion in reviews:
correct_counts[candidate_rule]+=1
else:
incorrect_counts[candidate_rule]+=1
#求置信度
rule_confidence = {candidate_rule: correct_counts[candidate_rule]/ float(correct_counts[candidate_rule] +incorrect_counts[candidate_rule])for candidate_rule in candidate_rules}
#排序输出置信度高的5条
from operator import itemgetter
sorted_confidence = sorted(rule_confidence.items(),key=itemgetter(1), reverse=True)
for index in range(5):
print("Rule #{0}".format(index + 1))
(premise, conclusion) = sorted_confidence[index][0]
print("Rule: If a person recommends {0} they will alsorecommend {1}".format(premise, conclusion))
print(" - Confidence:{0:.3f}".format(rule_confidence[(premise, conclusion)]))
print("")
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 数据挖掘 算法