推荐系统概述

  1. 云栖社区>
  2. 互联网架构师>
  3. 博客>
  4. 正文

推荐系统概述

技术小能手 2018-10-31 11:02:38 浏览1353
展开阅读全文

“聆忠言者众,惟智者受益。” — 哈珀·李

许多人把推荐系统视为一种神秘的存在,他们觉得推荐系统似乎知道我们的想法是什么。Netflix 向我们推荐电影,还有亚马逊向我们推荐该买什么样的商品。推荐系统从早期发展到现在,已经得到了很大的改进和完善,以不断地提高用户体验。尽管推荐系统中许多都是非常复杂的系统,但其背后的基本思想依然十分简单。

推荐系统是什么?

推荐系统是信息过滤系统的一个子类,它根据用户的偏好和行为,来向用户呈现他(或她)可能感兴趣的物品。推荐系统会尝试去预测你对一个物品的喜好,以此向你推荐一个你很有可能会喜欢的物品。

如何构建一个推荐系统?

现在已经有很多种技术来建立一个推荐系统了,我选择向你们介绍其中最简单,也是最常用的三种。他们是:一,协同过滤;二,基于内容的推荐系统;三,基于知识的推荐系统。我会解释前面的每个系统相关的弱点,潜在的缺陷,以及如何去避免它们。最后,我在文章末尾为你们准备了一个推荐系统的完整实现。

协同过滤

协同过滤,是首次被用于推荐系统上的技术,至今仍是最简单且最有效的。协同过滤的过程分为这三步:一开始,收集用户信息,然后以此生成矩阵来计算用户关联,最后作出高可信度的推荐。这种技术分为两大类:一种基于用户,另一种则是基于组成环境的物品。

基于用户的协同过滤

基于用户的协同过滤本质上是寻找与我们的目标用户具有相似品味的用户。如果Jean-Pierre和Jason曾对几部电影给出了相似的评分,那么我们认为他们就是相似的用户,接着我们就可以使用Jean Pierre的评分来预测Jason的未知评分。例如,如果Jean-Pierre喜欢星球大战3:绝地武士归来和星球大战5:帝国反击战,Jason也喜欢绝地武士归来,那么帝国反击战对Jason来说是就是一个很好的推荐。一般来说,你只需要一小部分与Jason相似的用户来预测他的评价。

9aea093257eb126a451fef3d80a3b3187ba6dc77

在下表中,每行代表一个用户,每列代表一部电影,只需简单地查找这个矩阵中行之间的相似度,就可以找到相似的用户了。

26d0264247f132008b28fcc86da7193be9e82eee

然而,基于用户的协同过滤在实现中存在一些以下问题:

 ●  用户偏好会随时间的推移而改变,推荐系统生成的许多推荐可能会随之变得过时。
 ●  用户的数量越多,生成推荐的时间就越长。
 ●  基于用户会导致对托攻击敏感,这种攻击方法是指恶意人员通过绕过推荐系统,使得特定物品的排名高于其他物品。
(托攻击即Shilling Attack,是一种针对协同过滤根据近邻偏好产生推荐的特点,恶意注入伪造的用户模型,推高或打压目标排名,从而达到改变推荐系统结果的攻击方式)
  • 194年12月,我们小分队在滇西北找矿。小分队一共8人,其中4名警战士每人配备一支冲锋枪。一天,出发前,一位纳西族老乡搭我们的车去维西。那天路上积雪很大,雪下的路面坑洼不平,车子行驶一段就会被雪坞住。我们不得不经常下来推车。就在我们又一次下车推车的时候,一群褐黄色的东西慢慢向我们靠近。我们正惊疑、猜测时,纳西族老乡急喊:“快、快赶紧上车,是一群狼。”司机小王赶紧发动车,加大油门……但是很不幸,车轮只是在原地空转,根本无法前进。这时狼群已靠近汽车……大家看得清清楚楚——8只狼,个个都象小牛犊似的,肚子吊得老高。战士小吴抄起冲锋枪,纳西族老乡一手夺下小吴的抢。比较沉着地高声道:“不能开枪,枪一响,它们或钻到车底下或钻进树林,狼群会把车胎咬坏,把我们围起来,然后狼会嚎叫召集来更多的狼和我们拼命。”他接着说:“狼饿疯了,它们是在找吃的,车上可有吃的?”我们几乎同声回答:“有。”“那就扔下去给它们吃。”老乡像是下达命令。从来没有经历过这样的事,当时脑子里一片空白,除了紧张,大脑似乎已经不会思考问题。听老乡这样说,我们毫不犹豫,七手八脚把从丽江买的腊肉、火腿还有十分珍贵的鹿子干巴往下丢了一部分。狼群眼都红了,兴奋地大吼着扑向食物,大口的撕咬吞咽着,刚丢下去的东西一眨眼就被吃光了。老乡继续命令道:“再丢下去一些!”第二批大约50斤肉品又飞出了后车门,也就一袋烟的工夫,又被8只狼分食的干干净净。吃完后8只狼整齐地坐下,盯着后车门。这时,我们几人各个屏气息声,紧张的手心里都是冷汗,甚至能够清晰的听到自己心跳的声音……我们不知道能有什么办法令我们从狼群中突围出去。看到这样的情形,老乡又发话道:“还有吗?一点不留地丢下,想保命就别心疼这些东西了!”此时,除了紧张、害怕还有羞愤……!作为战士,我们是有责任保护好这些物资的,哪怕牺牲自己。但是现实情况是我们的车被坞到雪地里出不来,只能被困在车里。我们的子弹是极有限的,一旦有狼群被召唤来,我们会更加束手无策。我们几人相互看了一眼,迟疑片刻,谁也没有说什么,忍痛将车上所有的肉品,还有十几包饼干全都甩下车去!8只狼又是一顿大嚼。吃完了肉,它们还试探性的嗅了嗅那十几包饼干,但没有吃。这时我清楚地看到狼的肚子已经滚圆,先前暴戾凶恶的目光变得温顺。其中一只狼围着汽车转了两圈,其余7只狼没动。片刻,那只狼带着狼群朝树林钻去......不可思议的事情发生了……不一会儿,8只狼钻出松林,嘴里叼着树枝,分别放到汽车两个后轮下面。我们简直不敢相信自己的眼睛……这些狼的意思是想用树枝帮我们垫起轮胎,让我们的车开出雪窝。我激动地大笑起来……哈……哈……刚笑了两声,另外一个战士忙用手捂住了我的嘴,他怕这突兀的笑声惊毛了狼。接着,8只狼一齐钻到车底,但见汽车两侧积雪飞扬。我眼里滚动着泪花,大呼小王:“狼帮我们扒雪呢,赶快发动车,”车启动了,但是没走两步,又打滑了。狼再次重复刚才的动作:“先往车轮下垫树枝,然后扒雪……”。就这样,每重复一次,汽车就前进一段,大约重复了十来次。最后一次,汽车顺利地向前行了一里多地,接近了山顶。再向前就是下坡路了。这时,8只狼在车后一字排开坐着,其中一只比其他7只狼稍稍向前。老乡说:“靠前面的那只是头狼,主意都是他出的。”我们激动极了,一起给狼鼓掌,并用力地向它们挥手致意。但是这8只可爱的狼对我们的举动并没有什么反应,只是定定地望了望我们,然后,头狼在前,其余随后,缓缓朝山上走去,消失在松林中......看完不忍思考:连凶猛的狼都懂得报恩,我们是否应该反思自身?自诩为“万物灵长”的人类,们是不是应当让这个世界充满爱94年12月,我们小分队在滇西北找矿。小分队一共8人,其中4名警战士每人

基于物品的协同过滤

基于物品的协同过滤过程很简单。两个物品的相似性基于用户给出的评分来算出。让我们回到Jean-Pierre与Jason的例子,他们两人都喜欢“绝地武士归来”和“帝国反击战”。 因此,我们可以推断,喜欢第一部电影的大多数用户也可能会喜欢第二部电影。所以,对于喜欢“绝地武士归来”的第三个人Larry来说,”帝国反击战“的推荐将是有意义的。

16037781f6b648c271ad39905bc769f740e9ce67

所以,这里的相似度是根据列而不是行来计算的(与上面的用户-电影矩阵中所见的不同)。基于物品的协同过滤常常受到青睐,因为它没有任何基于用户的协同过滤的缺点。首先,系统中的物品(在这个例子中物品就是电影)不会随着时间的推移而改变,所以推荐会越来越具有关联性。此外,通常推荐系统中的物品都会比用户少,这减少了推荐的处理时间。最后,考虑到没有用户能够改变系统中的物品,这种系统要更难于被欺骗或攻击。

基于内容的推荐系统

在基于内容的推荐系统中,元素的描述性属性被用来构成推荐。“内容Content”一词指的就是这些描述。举个例子,根据Sophie的听歌历史,推荐系统注意到她似乎喜欢乡村音乐。因此,系统可以推荐相同或相似类型的歌曲。更复杂的推荐系统能够发现多个属性之间的关系,从而产生更高质量的推荐。例如,音乐基因组计划(Music Genome Project)根据450个不同的属性将数据库中的每支歌曲进行分类。该项目为Pandor的歌曲推荐提供技术支持。(Pandor提供在线音乐流媒体服务,类似Spolify)

基于知识的推荐系统

基于知识的推荐系统在物品购买频率很低的情况下特别适用。例如房屋、汽车、金融服务甚至是昂贵的奢侈品。在这种情况下,推荐的过程中常常缺乏商品的评价。基于知识的推荐系统不使用评价来作出推荐。相反,推荐过程是基于顾客的需求和商品描述之间的相似度,或是对特定用户的需求使用约束来进行的。这使得这种类型的系统是独一无二的,因为它允许顾客明确地指定他们想要什么。关于约束,当应用时,它们大多是由该领域的专家实施的,这些专家从一开始就知道该如何实施这些约束。例如,当用户明确指出在一个特定的价格范围内寻找一个家庭住宅时,系统必须考虑到这个用户规定的约束。

推荐系统中的冷启动问题

推荐系统中的主要问题之一是最初可用的评价数量相对较小。当新用户还没有给电影打分,或者一部新的电影被添加到系统中时,我们该怎么做呢?在这种情况下,应用传统的协同过滤模型会更加困难。尽管基于内容和基于知识的推荐算法在面临冷启动问题时比协同过滤更具有鲁棒性,但基于内容和基于知识并不总是可用的。因此,一些新方法,比如混合系统,已经被设计出用来解决这个问题了。

混合推荐系统

文章到目前为止所介绍的不同类型的推荐系统都各有优劣,他们根据不同的数据给出推荐。 一些推荐系统,如基于知识的推荐系统,在数据量有限的冷启动环境下最为有效。其他系统,如协同过滤,在有大量数据可用时则更加有效。在多数情况下,数据都是多样化的,我们可以为同一任务灵活采用多种方法。 因此,我们可以结合多种不同技术的推荐来提高整个系统的推荐质量。许多的组合性技术已经被探索出来了,包括:

 ●  加权:为推荐系统中的每种算法都赋予不同的权重,使得推荐偏向某种算法
 ●  交叉:将所有的推荐结果集合在一起展现,没有偏重
 ●  增强:一个系统的推荐将作为下一个系统的输入,循环直至最后一个系统为止
 ●  切换:随机选择一种推荐方法

混合推荐系统中的一个最有名的例子是于2006至2009年举行的Netflix Price算法竞赛。这个竞赛的目标是将Netflix的电影推荐系统Cinematch的算法准确率提高至少10%。Bellkor’s Pragmatix Chaos团队用一种融合了107种不同算法的方案将Cinematch系统的推荐准确率提高了10.06%,并最终获得了100万美元奖金。你可能会对这个例子中的准确率感到好奇,准确率其实就是对电影的预测评分与实际评分接近程度的度量。

推荐系统与AI?

推荐系统常用于人工智能领域。推荐系统的能力 – 洞察力,预测事件的能力和突出关联的能力常被用于人工智能中。另一方面,机器学习技术常被用于实现推荐系统。例如,在Arcbees,我们使用了神经网络和来自IMdB的数据成功建立了一个电影评分预测系统。神经网络可以快速地执行复杂的任务并轻松地处理大量数据。通过使用电影列表作为神经网络的输入,并将神经网络的输出与用户评分进行比较,神经网络可以自我学习规则以预测特定用户的未来评分。

专家建议

在我读过许多资料中,我注意到有两个很重要的建议经常被推荐系统领域内的专家提及。第一,基于用户付费的物品进行推荐。当一个用户有购买意愿时,你就可以断定他的评价一定是更具有相关性与准确的。第二,使用多种算法总是比改进一种算法要好。Netflix Prize竞赛就是一个很好的例子。

实现一个基于物品的推荐系统

下面的代码演示了实现一个基于物品的推荐系统是多么的简单与快速。所使用的语言是Python,并使用了Pandas与Numpy这两个在推荐系统领域中最流行的库。所使用的数据是电影评分,数据集来自MovieLens。

第一步:寻找相似的电影

1.读取数据

import pandas as pd

import numpy as np

 

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.构造用户的电影矩阵


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

movieStats = ratings.groupby('title').agg({'rating'[np.size, np.mean]})

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)):

    #取出与评分过电影相似的电影

    sims = corrMatrix[myRatings.index[i]].dropna()

    #以用户对这部电影的评分高低来衡量它的相似性

    sims = sims.map(lambda xx * myRatings[i])

    #将结果放入相似性候选列表中

    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。

我希望我已经成功让你看到,实现一个简单而有效的推荐系统中并没有什么复杂之处。如果你有任何问题,不要犹豫,直接评论就好了。


原文发布时间为:2018-10-28

本文来自云栖社区合作伙伴“互联网架构师”,了解相关信息可以关注“互联网架构师”。

网友评论

登录后评论
0/500
评论
技术小能手
+ 关注
所属团队号: 互联网架构师