赞
踩
本文将利用kaggle上的电影数据tmdb-5000(已上传,可免费下载;若收费,请联系作者修改),实现一个电影推荐系统。由于数据集并不涉及到用户行为数据,所以我们只能用基于统计或者基于内容的推荐方法。
我们将整个项目分为三个部分。
在第一部分,我们看到tmdb-5000的两个csv文件里面实际上包含着json格式的数据,我们需要对其进行提取。
在第二部分,我们对缺失值和关键词信息进行处理,提高数据质量;我们还对部分信息进行可视化展示,方便直观了解数据。
在第三部分,我们将整个推荐系统分为召回和过滤两个阶段。
下面,我们将详细介绍每一部分。
点开tmdb_5000_movies.csv文件,可以发现某些数据是字典,如下
特征"genres"下第一行
'[{"id": 28, "name": "Action"}, {"id": 12, "name": "Adventure"}, {"id": 14, "name": "Fantasy"}, {"id": 878, "name": "Science Fiction"}]'
用json.load()函数来读取此类字典数据,读取后为
[{'id': 28, 'name': 'Action'},
{'id': 12, 'name': 'Adventure'},
{'id': 14, 'name': 'Fantasy'},
{'id': 878, 'name': 'Science Fiction'}]
对于特征"genres",我们不需要其中的id,仅仅需要类别名称,因此,从"genres"中抽取类别名称。
具体的,我们在tmdb_5000_movies.csv文件中,
在tmdb_5000_credits.csv文件中,
这样抽取完成之后,我们将两个数据集根据电影id合并起来,形成一个dataframe,方便后面数据处理。
此时,dataframe看起来是这样的
经过初步处理之后的数据,其实是有些问题的,对于推荐系统而言,
数据经过处理之后,我们可以进行可视化,对数据有一个直观的了解,具体的,
由于我们关心的是电影的推荐,所以,我们将以下特征舍去
舍去无用特征之后,我们剩下如下特征,
为了直观看当前数据的缺失值情况,我们给出缺失值表格
从上面表格可以看出,除了keywords之外,其余特征缺失值占总体数据比例非常低(均在1%之下),我们对这些缺失值直接做舍弃处理。
我们主要考虑keywords缺失值。
然而实际情况是,我们有4000多个数据,当仅用100个数据对overview进行tf-idf处理时,得到的结果已经很不理想。以第一行数据为例,
可以看到,实际keywords与overview和genres的处理结果相差很大,为了避免影响数据质量,我们决定不对keywords进行填充,对缺失值所在行直接舍去。
此时,我们一同舍去的还有overview,因为我们只需要用genres和keywords对电影内容进行刻画就行,而相似电影的overview可能完全不同。因此,我们
我们主要对date和keywords进行处理,具体来说,
之所以对date这样处理,是因为电影往往和年代有关,比如90年代的电影相比于80年代的电影,有更大的区分度。
之所以对关键词这样处理,是因为后面我们将关键词作为特征来计算相似度,我们需要尽量保证特征之间的独立性,以及特征方差较大。
对date的处理结果如下
而对keywords的处理,我们首先用nltk的PorterStemmer()找出一个关键词的词根,然后用nltk的wordnet给出关键词的同义词。但是,这样比较耗费时间,同时效果并不明显。这是因为,经过删除出现频率较低的关键词之后,我们的关键词已经从9000多降低到2000多,再进行同义词处理效果不明显。
另外,我们还要对actors进行处理。这是因为观众往往仅关注少数的几个主演,对于其他演员并不敏感。
第一张图:演员词云展示
从词云图中可以明显看出,Robert De Niro(罗伯特·德尼罗)、Nicolas Cage(尼古拉斯凯奇)、Bruce Willis(布鲁斯威利斯)、Morgan Freeman等人出演电影较多。实际上,这些人也都是非常著名和成功的演员。
第二张图:导演词云展示
通过词云,可以明显找到steven spielberg(斯蒂芬 斯皮尔伯格)、Clint Eastwood(克林特·伊斯特伍德)等众多名导演。
第三张图:电影类型的时间趋势图
上面实际上是从1916年到2015年间,美国电影的类别趋势图。可以较为明显的看到,从95年左右电影数量开始大量增长,同时,较为流行的电影类型始终是 drama(剧情片)、thriller(惊悚)、action(动作片)、romance(爱情片)和crime(犯罪片)等。
第四张图:不同年代的电影占比
从上图中可以明显看出,90年代至今的电影占据了大多数,其中相比于90年代,00年代的电影数量显著增加,而10年代之所以数量较少,是因为10年代的仅仅统计到2015年。
第五张图:不同流行度电影的数量
可以看到,大部分电影的流行度都较低,流行度超过200以上的非常少。
第六张图:不同打分下的电影数量
从上面可以看出来,大部分打分都集中在5-8分,但相比于低分段0-5分的其他分数,0分的电影数量反而更多。
经过上面的数据清洗,我们基本上得到想要的数据。现在,根据这些数据,对于给定的一部电影,我们推荐5部电影。
我们将过程分为 召回 和过滤部分。在召回阶段,我们从所有电影中选出40部电影,在过滤部分,我们从这40部电影中,进一步筛选出5部电影作为最终推荐。
在召回阶段,通过考虑电影的类别信息、导演信息、主演信息和内容的关键词信息,构建特征,通过计算电影之间在给定特征下的相似度,我们给出最相似的40部电影。
在过滤阶段,我们进一步考虑电影的年份信息、评分信息、流行度信息等,对电影进行进一步打分。具体的,
基于上述想法,我们构建了推荐系统。
我们给出两个例子,测试推荐结果是否吸引人。
第一个例子,对于电影 阿凡达(Avatar),电影id为19995,推荐结果为
['Captain America: The Winter Soldier',
'Treasure Planet',
'Star Trek Into Darkness',
'Titan A.E.',
"Ender's Game"]
对于电影阿凡达,我们是清楚的,我们看看系统推荐了什么,
可以看到,当一个人看完阿凡达之后,系统将会推荐上面5部电影,就我看过的美国队长2、星际迷航2和安德的游戏而言,是非常恰当的,再就是星银岛和冰冻星球,年份相对较早,不过属于经典之作,应该也值得一看。
第二个例子,对于电影 海底总动员(Finding Nemo),电影id为12,推荐结果为
['The Secret of Kells',
"VeggieTales: The Pirates Who Don't Do Anything",
'Winnie the Pooh',
'Tangled',
'Arthur Christmas']
从上到下,电影名称依次是,凯尔经的秘密(2009,豆瓣评分8.5,奇幻冒险动画),无所事事的海盗(2008,豆瓣评分6.8,冒险家庭喜剧动画),小熊维尼(2011,豆瓣评分8.0,冒险喜剧动画),魔法奇缘(2010,豆瓣评分8.2,奇幻冒险动画),亚瑟圣诞(2011,豆瓣评分7.6,喜剧动画)。
从推荐的内容来看,评分都较高,大部分和海底总动员一样,属于适合家庭一起观看的喜剧经典动画。
评价:总体来看是达到预期效果的,期望系统推荐经典的高评分的相似电影,有些电影属于冷门好看的,这正是我们期待的效果。
不足:对于原始信息中,有些特征,比如电影简介、电影投入、电影收益之类的特征,我们没有使用,如果能够有效利用,或许能提供其他种类的推荐;再就是我们在设计特征的时候,实际上是人工设置的,可能换一种设置方法就能推荐不同的电影,这个也是值得商榷的。
附:github代码
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。