前言:
最近在参加比赛,选了推荐系统的赛题。接触到了各种推荐系统的算法,学习了许多大神的论文。非常感谢他们的科研,让我们能更注重于应用。这篇文章权当做个引子,后续会补充我比赛的具体。
知识储备:
Apriori算法可以说是经典的亲和性分析算法。它只从数据集中频繁出现的商品中选取共同出
现的商品组成频繁项集(frequent itemset),避免了上述复杂度呈指数级增长的问题。一旦找到
频繁项集,生成关联规则就很容易了。
Apriori算法背后的原理简洁却不失巧妙。首先,确保了规则在数据集中有足够的支持度。
Apriori算法的一个重要参数就是最小支持度。比如,要生成包含商品A、 B的频繁项集(A, B),
要求支持度至少为30,那么A和B都必须至少在数据集中出现30次。更大的频繁项集也要遵守该
项约定,比如要生成频繁项集(A, B, C, D),那么子集(A, B, C)必须是频繁项集(当然D自己也
要满足最小支持度标准)。
生成频繁项集后,将不再考虑其他可能的却不够频繁的项集(这样的集合有很多),从而大
大减少测试新规则所需的时间。
——引用自《python数据挖掘入门与实践》
本文所用数据集为MovieLen的,上传至文底网盘
全部代码:
import os
import pandas as pd
import sys
data_folder = 'D:\\Python\\PythonProject\\movie_recommend_test\\data'
ratings_filename = os.path.join(data_folder,'u.data')
all_ratings = pd.read_csv(ratings_filename,delimiter='\t',
header=None,names=['UserID','MovieID','Rating','Datetime'])
all_ratings['Datetime'] = pd.to_datetime(all_ratings['Datetime'],unit='s')
#确定用户是不是喜欢某一部电影
all_ratings['Favorable'] = all_ratings['Rating'] > 3
#取前200名用户的打分数据作训练集
ratings = all_ratings[all_ratings['UserID'].isin(range(200))]
favorable_ratings = ratings[ratings['Favorable']]#只包括用户喜欢某部电影所在的行
#用户为键,喜欢的电影集合为值(掌握groupby()方法)
favorable_review_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()
#开始应用Aprion算法
frequent_itemsets = {}#以项集长度为键,频繁项集为值的字典
min_support = 50
frequent_itemsets[1] = dict((frozenset((movie_id,)),
row['Favorable']) for movie_id,row in num_favorable_by_movie.iterrows()
if row['Favorable']>min_support)
from collections import defaultdict
def find_frequent_itemsets(favorable_review_by_users,k_1_itemsets,min_support):
counts = defaultdict(int)
for user,reviews in favorable_review_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])
#创建循环,运行Apriori算法,存储算法运行过程中发现的新项集
for k in range(2,20):
cur_frequent_itemsets = find_frequent_itemsets(favorable_review_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 {} frequency 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():