文章目录
4 用亲和性分析方法推荐电影
本章主要涉及以下几个概念。
亲和性分析
用Apriori算法挖掘关联特征
电影推荐
数据稀疏问题
4.1 亲和性分析
亲和性分析用来找出两个对象共同出现的情况。而前几章,我们关注的是同种对象之间的相
似度。亲和性分析所用的数据通常为类似于交易信息的数据。从直观上来看,这些数据就像是商
店的交易数据——从中能看出哪些商品是顾客一起购买的。
然而,亲和性分析方法的应用场景有很多,比如:
欺诈检测
顾客区分
软件优化
产品推荐
亲和性分析比分类更具探索性,因为通常我们无法拿到像在很多分类任务中所用的那样完整
的数据集。例如,在电影推荐任务中,我们拿到的是不同用户对不同电影的评价。但是,每个用
户不可能评价过所有电影,这就给亲和性分析带来一个不容忽视的大难题。如果用户没有评价过一部电影,是因为他们不喜欢这部电影(据此就不推荐给他们),还是因为他们出于别的原因还
没有评价?
本章不对上述问题做出解答,但是我们要思考数据集中类似这样的潜在问题该怎么解决。这
些思考有助于提升推荐算法的准确性。
4.1.1 亲和性分析算法
我们在第1章介绍了一种基础的亲和性分析算法,尝试了所有可能的规则组合,计算了每条规则的置信度和支持度,并根据这两个标准进行排序,选取最佳规则。
然而,这个方法效率不高。好在第1章所使用的数据集中,每条交易数据只涉及五种商品。
但现实并非如此,即使是再不起眼的小卖铺出售的商品也达上百种之多,网店更是有成千上万种
商品(甚至几百万种!)。如果规则生成方法像第1章那样过于简单,计算这些规则所需要的时间
复杂度将呈指数级增长。随着商品数量的增加,计算所有规则所需的时间增长得很快。更具体地
说,所有可能的规则数量是2n1。数据集有5个特征,可能的规则就有31条;有10个特征,可能
的规则就有1023条;仅仅有100个特征,规则数就能达到30位数字。即使计算能力大幅提升也未
必能赶上在线商品的增长速度。因此,与其跟计算机过不去,不如寻找更加聪明的算法。
Apriori算法可以说是经典的亲和性分析算法。它只从数据集中频繁出现的商品中选取共同出
现的商品组成频繁项集(frequent itemset),避免了上述复杂度呈指数级增长的问题。一旦找到
频繁项集,生成关联规则就很容易了。
Apriori算法背后的原理简洁却不失巧妙。首先,确保了规则在数据集中有足够的支持度。
Apriori算法的一个重要参数就是最小支持度。比如,要生成包含商品A、B的频繁项集(A, B),
要求支持度至少为30,那么A和B都必须至少在数据集中出现30次。更大的频繁项集也要遵守该
项约定,比如要生成频繁项集(A, B, C, D),那么子集(A, B, C)必须是频繁项集(当然D自己也
要满足最小支持度标准)。
生成频繁项集后,将不再考虑其他可能的却不够频繁的项集(这样的集合有很多),从而大
大减少测试新规则所需的时间。
其他亲和性分析算法有Eclat和频繁项集挖掘算法(FP-growth)。从数据挖掘角度看,这些
算法比起基础的Apriori算法有很多改进,性能也有进一步提升。接下来,先来看一下最基础的
Apriori算法。
4.1.2 选择参数
挖掘亲和性分析所用的关联规则之前,我们先用Apriori算法生成频繁项集。接着,通过检测频繁项集中前提和结论的组合,生成关联规则(例如,如果用户喜欢电影X,那么他很可能喜欢
电影Y)。
第一个阶段,需要为Apriori算法指定一个项集要成为频繁项集所需的最小支持度。任何小于
最小支持度的项集将不再考虑。如果最小支持度值过小,Apriori算法要检测大量的项集,会拖慢
的运行速度;最小支持度值过大的话,则只有很少的频繁项集。
找出频繁项集后,在第二个阶段,根据置信度选取关联规则。可以设定最小置信度,返回一
部分规则,或者返回所有规则,让用户自己选。
本章,我们设定最小置信度,只返回高于它的规则。置信度过低将会导致规则支持度高,正
确率低;置信度过高,导致正确率高,但是返回的规则少。
4.2 电影推荐问题
产品推荐技术是门大生意。网店经常用它向潜在用户推荐他们可能购买的产品。好的推荐算
法能带来更高的销售业绩。每年有几百万乃至几千万用户进行网购,向他们推荐更多的商品,潜
在收益着实可观。
产品推荐问题被人们研究了多年,但它一直不温不火,直到2007年到2009年间,Netflix公司
推出数据建模大赛,并设立Netflix Prize奖项之后,才得到迅猛发展。该竞赛意在寻找比Netflix
公司所使用的预测用户为电影打分的系统更准确的解决方案。最后获奖队伍以比现有系统高10
个百分点的优势胜出。虽然这个改进看起来不是很大,但是Netflix公司却能借助它实现更精准的
电影推荐服务,从而多赚上百万美元。
4.2.1 获取数据集
自打Netflix Prize奖项设立以来,美国明尼苏达大学的Grouplens研究团队公开了一系列用于
测试推荐算法的数据集。其中,就包括几个大小不同的电影评分数据集,分别有10万、100万和
1000万条电影评分数据。
数据集下载地址为http://grouplens.org/datasets/movielens/。本章将使用包含100万条数据的
MovieLens数据集。下载数据集,解压到你的Data文件夹。启动IPython Notebook笔记本,输入以
下代码。
import os
data_folder = os.path.join(".","data")
ratings_filename = os.path.join(data_folder,'u.data')
4.2.2 用 pandas 加载数据
MovieLens数据集非常规整,但是有几点跟pandas.read_csv方法的默认设置有出入,所以
要调整参数设置。第一个问题是数据集每行的几个数据之间用制表符而不是逗号分隔。其次,没
有表头,这表示数据集的第一行就是数据部分,我们需要手动为各列添加名称。
加载数据集时,把分隔符设置为制表符,告诉pandas不要把第一行作为表头(header=None),
设置好各列的名称。代码如下:
import pandas as pd
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[:5]
| UserID | MovieID | Rating | Datetime | |
|---|---|---|---|---|
| 0 | 196 | 242 | 3 | 1997-12-04 15:55:49 |
| 1 | 186 | 302 | 3 | 1998-04-04 19:22:22 |
| 2 | 22 | 377 | 1 | 1997-11-07 07:18:36 |
| 3 | 244 | 51 | 2 | 1997-11-27 05:02:03 |
| 4 | 166 | 346 | 1 | 1998-02-02 05:33:16 |
4.2.3 稀疏数据格式
这是一个稀疏数据集,我们可以将每一行想象成巨大特征矩阵的一个格子,前几章用到过这
种矩阵。在这个矩阵中,每一行表示一个用户,每一列为一部电影。第一列为每一个用户给第一
部电影打的分数,第二列为每一个用户给第二部电影打的分数,以此类推。
数据集中有1000名用户和1700部电影,这就意味着整个矩阵很大。将矩阵读到内存中及在它
基础上进行计算可能存在难度。然而,这个矩阵的很多格子都是空的,也就是对大部分用户来说,
他们只给少数几部电影打过分。比如用户#213没有为电影#675打过分,大部分用户没有为大部分
电影打过分。
用上述图表中的格式也能表示矩阵,且更为紧凑。序号为0的那一行表示,用户#196在1997
年12月4日为电影#242打了3分(满分是5分)。
任何没有出现在数据集中的用户和电影组合表示它们实际上是不存在的。这比起在内存中保
存大量的0,节省了很多空间。这种格式叫作稀疏矩阵(sparse matrix)。根据经验来说,如果数
据集中60%或以上的数据为0,就应该考虑使用稀疏矩阵,从而节省不少空间。
在对稀疏矩阵进行计算时,我们关注的通常不是那些不存在的数据,不会去比较众多的0值,
相反我们关注的是现有数据,并对它们进行比较。
4.3 Apriori 算法的实现
本章数据挖掘的目标是生成如下形式的规则:如果用户喜欢某些电影,那么他们也会喜欢这
部电影。作为对上述规则的扩展,我们还将讨论喜欢某几部电影的用户,是否喜欢另一部电影。
要解决以上问题,首先要确定用户是不是喜欢某一部电影。为此创建新特征Favorable,若
用户喜欢该电影,值为True。
all_ratings["Favorable"] = all_ratings["Rating"] > 3
#我们在数据集中看一下这个新特征
all_ratings[10:15]
| UserID | MovieID | Rating | Datetime | Favorable | |
|---|---|---|---|---|---|
| 10 | 62 | 257 | 2 | 1997-11-12 22:07:14 | False |
| 11 | 286 | 1014 | 5 | 1997-11-17 15:38:45 | True |
| 12 | 200 | 222 | 5 | 1997-10-05 09:05:40 | True |
| 13 | 210 | 40 | 3 | 1998-03-27 21:59:54 | False |
| 14 | 224 | 29 | 3 | 1998-02-21 23:40:57 | False |
从数据集中选取一部分数据用作训练集,这能有效减少搜索空间,提升Apriori算法的速度。
我们取前200名用户的打分数据。
ratings = all_ratings[all_ratings['UserID'].isin(range(200))]
接下来,新建一个数据集,只包括用户喜欢某部电影的数据行
favorable_ratings = ratings[ratings['Favorable']]
favorable_ratings[:5]
| UserID | MovieID | Rating | Datetime | Favorable | |
|---|---|---|---|---|---|
| 16 | 122 | 387 | 5 | 1997-11-11 17:47:39 | True |
| 20 | 119 | 392 | 4 | 1998-01-30 16:13:34 | True |
| 21 | 167 | 486 | 4 | 1998-04-16 14:54:12 | True |
| 26 | 38 | 95 | 5 | 1998-04-13 01:14:54 | True |
| 28 | 63 | 277 | 4 | 1997-10-01 23:10:01 | True |
在生成项集时,需要搜索用户喜欢的电影。因此,接下来,我们需要知道每个用户各喜欢哪
些电影,按照User ID进行分组,并遍历每个用户看过的每一部电影。
favorable_reviews_by_users = dict((k, frozenset(v.values<

本篇博客详细介绍了如何利用Apriori算法进行电影推荐。首先,通过亲和性分析找出用户共同观看的电影,接着在稀疏数据集上实现Apriori算法,生成频繁项集并抽取关联规则。在测试集上验证规则的置信度,从而得出有效的电影推荐策略。
979

被折叠的 条评论
为什么被折叠?



