我们许多人将推荐系统视为似乎知道我们思想的神秘实体。试想一下Netflix的建议电影的推荐引擎,或者是建议我们应该购买什么产品的亚马逊。自他们成立以来,这些工具经过改进和完善来不断提升用户体验。虽然其中很多是非常复杂的系统,但其背后的基本思想仍然非常简单。
推荐系统是信息过滤系统的一个子类,基于偏好和行为向用户呈现他或她可能感兴趣的项目。他们试图预测你对一个项目的赞赏,并建议你更可能欣赏的。
尽管建立推荐系统的技术有很多,但我选择了三种最简单,最常用的方法:第一种是协同过滤,第二种是基于内容的系统,第后一种是基于知识的系统。对于每个系统,我将解释相关的弱点,潜在的陷阱,以及如何规避它们。最后,一个推荐系统的完整实现将在最后等待着你。
所使用的第一种技术仍然是最简单和最有效的技术,即协同过滤。这个三步过程从收集用户信息开始,然后形成一个矩阵来计算关联,最后提出一个相当高的可信度的推荐。该技术分为两大类:一类基于用户,另一类基于组成环境的项目。
基于用户的协同过滤背后的想法是找到与我们的目标用户有相似口味的用户。如果Jean-Pierre和Jason过去以类似的方式评价过几部电影,那么我们就把这两部电影看作是类似的用户,我们可以利用Jean-Pierre的评级来预测Jason的未知评价。例如,如果Jean-Pierre爱看《绝地归来》和《帝国反击》,杰森也爱看《绝地归来》,那么《帝国反击》对Jason来说将是一个很好的建议。一般来说,您只需要一小部分与Jason相似的用户来预测他的评价。
在表格中,每行表示一个用户,每列表示一部电影,只需找到矩阵中的行之间的相似之处来找到相似的用户。
然而,这种实现的方式有一些问题
这个过程很简单。两个项目的相似性是根据用户给出的评分来计算的。让我们再用Jean-Pierre和Jason举例,他们都喜欢《绝地归来》和《帝国反击战》。因此,我们可以推断,喜欢第一部电影的大多数用户也可能会欣赏第二部电影。所以,将《帝国反击战》推荐给喜欢《绝地归来》的Larry将是有意义的。
因此,根据列而不是行来计算相似性(如在上面呈现的用户/电影矩阵中所见)。基于项目的协作过滤通常是有利的,因为它没有任何用户过滤的缺点。首先,系统中的项目(这种情况下的电影)不会随着时间的推移而改变,所以建议将更加相关。另外,通常有代表性地的项目比用户更少,这减少了处理时间。最后,考虑到没有用户可以改变,这些系统的欺骗要复杂得多。
在基于内容的推荐系统中,元素的描述性属性被用来提出建议。术语“内容”是指这些描述。例如,看着Sophie的听歌历史,系统注意到她似乎喜欢这种乡村风格。因此,该系统可以推荐相同或相似流派的歌名。更复杂的系统能够检测多个属性之间的关系,从而产生更高质量的建议。例如,音乐基因组项目根据450个不同的属性将其中的每首歌曲分类到数据库中。这个项目就是潘多拉音乐的强力推荐。
基于知识的推荐系统在罕有地购买的项目环境中特别有用。例子包括房屋,汽车,金融服务,甚至昂贵的奢侈品。在这种情况下,推荐过程常常会受到产品评分不够的影响。基于知识的系统不使用评分来提出建议。相反,建议过程是基于客户要求和项目描述之间的相似性,或使用指定用户需求的约束来执行的。这使得这种类型的系统是独一无二的,因为它允许用户明确地指定他们想要的。如果适用的话,这些制约因素大部分由该领域的专家来执行,从一开始就为人所知。例如,当用户明确指定他在一个价格范围内寻找住宅时,系统必须考虑到这个规格。
推荐系统的主要问题之一是最初可用的评级数量相对较小。当新用户还没有记录的电影,或者新电影被添加到系统时,我们可以做什么?在这种情况下,应用传统的协同过滤模型会更困难。尽管基于内容的和基于知识的方法在冷启动的情况下比协作模型更加稳健,但内容或知识可能并不总是可用的。因此,许多过程,例如混合系统,都是为了解决这个问题而设计的。
值得注意的是,到目前为止所提出的不同类型的系统都有优点和缺点,并根据各种数据点提出建议。一些推荐系统,如基于知识的推荐系统,在数据量有限的冷启动环境中最为有效。其他系统(如协作方法)在大量数据可用时更为有效。在很多情况下,数据是多样化的,我们可以灵活地使用多种方法来完成同一个任务。因此,我们可以结合几种技术的建议来提高整个系统的质量。许多组合技术已经被探索了,包括:
其中一个最着名的混合系统例子是在2006年至2009年间的Netflix Prize编码竞赛中被人们所了解。目标是通过将其算法的精确度提高至少10%来改进Netflix的电影推荐系统Cinematch。Bellkor的Pragmatix Chaos团队以一个解决方案赢得了100万美元的奖金,这个解决方案结合了107种不同的算法,并将Cinematch的建议提高了10.06%。如果你想知道,准确性是衡量电影的收视率与随后的实际收视率的紧密联系的一个衡量标准。
推荐系统通常被用于人工智能环境。他们提供洞察力、预测事件和突出相关性的能力通常对他们在人工智能中的使用负责。另一方面,机器学习技术通常用于实现推荐系统。例如,在Arcbees,我们成功地使用神经网络和来自互联网电影数据库(IMDb)的数据成功地建立了电影评分预测系统。神经网络可以快速执行复杂的任务,并轻松处理大数据。通过使用电影列表作为输入并将输出与用户的评价进行比较,神经网络可以自己学习规则以预测特定用户的未来评价。
在我的阅读过程中,我注意到两个很好的提议总是在这个领域的专家中来来回回。第一个是基于用户支付的项目建议。当用户愿意付款时,你可以放心他或她给出的评价将更加相关和准确。第二个是,拥有更多的算法总是比改善单个算法更好。Netflix Prize就是一个很好的例子。
以下代码演示了实现协作过滤项目推荐系统有多么的简单和迅速。使用的语言是Python,我使用的是在该领域最受欢迎的熊猫(Pandas)和Numpy库。所使用的数据是电影分级,而该集可在MovieLens上使用。
1.读取数据:
import pandas as pd
ratings_cols = ['user_id', 'movie_id', 'rating']
ratings = pd.read_csv('u.data', sep='\t', names=ratings_cols, usecols=range(3))
movies_cols = ['movie_id', 'title']
movies = pd.read_csv('u.item', sep='|', names=movies_cols, usecols=range(2))
ratings = pd.merge(ratings, movies)
2.构建用户X的电影矩阵:
movieRatings = ratings.pivot_table(index=['user_id'],columns=['title'],values='rating')
3.选择一部电影,并在这部电影和所有其他影片之间产生相似度得分(相关性):
starWarsRatings = movieRatings['Star Wars (1977)']
similarMovies = movieRatings.corrwith(starWarsRatings)
similarMovies = similarMovies.dropna()
df = pd.DataFrame(similarMovies)
4.去除不受欢迎的电影,避免提出不合适的建议:
ratingsCount = 100
popularMovies = movieStats['rating']['size'] >= ratingsCount
movieStats[popularMovies].sort_values([('rating', 'mean')], ascending=False)[:15]
5.提取与我们的目标相似的流行电影:
df = movieStats[popularMovies].join(pd.DataFrame(similarMovies, columns=['similarity']))
df.sort_values(['similarity'], ascending=False)[:15]
1.在每对电影中产生相似的分数,并只保留流行的电影:
userRatings = ratings.pivot_table(index=['user_id'],columns=['title'],values='rating')
corrMatrix = userRatings.corr(method='pearson', min_periods=100)
2.为每一个被我们的用户看过和评价的电影生成建议(这里我们选择了用户0):
myRatings = userRatings.loc[0].dropna()
simCandidates = pd.Series()
for i in range(0, len(myRatings.index)):
# Retrieve similar movies to this one that I rated
sims = corrMatrix[myRatings.index[i]].dropna()
# Now scale its similarity by how well I rated this movie
sims = sims.map(lambda x: x * myRatings[i])
# Add the score to the list of similarity candidates
simCandidates = simCandidates.append(sims)
simCandidates.sort_values(inplace = True, ascending = False)
3.相同的电影的分数相加:
simCandidates = simCandidates.groupby(simCandidates.index).sum()
simCandidates.sort_values(inplace = True, ascending = False)
4.只保留那些尚未被用户看过的电影:
filteredSims = simCandidates.drop(myRatings.index)
在上述情况下,熊猫(Pandas)和我们的内部CPU足以在MovieLens数据集上工作。但是,更大的集合可能会被处理的时间更长。因此,你可能会想转向一些解决方案,如 Spark 或 MapReduce,它们有更强的处理能力。
希望我已经成功地帮助你看到,实施一个简单而有效的推荐系统没有什么复杂的。不要犹豫,评论和提问你的问题!