推荐领域新人必看书籍:《推荐系统实践》

简介: 这本书非常适合推荐领域的新手,因为这本书的主要目的更接近于科普,而不是描述具体的推荐算法。


什么是推荐系统?


如果有一位你喜欢的女士约你一起外出,肯定不需要别人推荐你是否赴约吧!(信息量太小则不需要被推荐)

那么,如果有一百位呢?(出现信息过载)

你肯定会检查下你最心仪的那位女士有没有约你。如果她也约你了,你照样不需要别人的推荐。(有明确目标则使用搜索系统)

但如果这一百位女士中没有你熟悉的人呢?你是不是需要被推荐一位最合适的女士呢?(没有明确目标则使用推荐系统)


这就是推荐系统。当你遇到信息过载时,而你又没有明确的目标,这时你需要向一个自动化的“专家”描述你的需求。它可以分析你的历史兴趣、分析信息流中的信息内容、分析当前的情况,从而挑选出符合你要求的信息给你。


推荐系统的基本任务就是联系用户和信息,解决信息过载的问题。


什么是好的推荐系统?


▐  推荐信息的方式


首先,推荐系统是通过什么方式将信息推荐给我们的呢?

  1. 问问朋友。“嘿!最近有什么好电影?”让好友给自己推荐信息,这称为社会化推荐。
  2. 搜一下之前喜欢的商品,看有没有新的相关商品。“什么?!周星驰又出新电影了”,这称为基于内容的推荐。
  3. 看排行榜。我来看看今天的电影热门Top10有哪些好看的电影,这称为基于协同过滤的推荐。


▐  推荐系统的评价方式


推荐系统需要载体,它往往以应用的形式出现。那么我们该如何评价一个推荐系统好不好呢?
一个完整的推荐系统存在三个参与方:用户、物品提供者和提供推荐系统的网站,所以一个好的推荐系统应该是一个能让三方共赢的系统。早期的推荐系统只是看预测的推荐准不准确。但光准确还不够,还要有意义。例如:我预测明天太阳从东方升起。这预测没有任何意义,但你就说准不准吧。
所以,好的推荐系统不仅仅能够准确预测用户的行为,而且能够扩展用户的视野,帮助用户发现那些他们可能会感兴趣,但却不那么容易发现的东西。同时,好的推荐系统还要能够帮助商家将埋没在长尾(幂律分布,Power Law)中的好商品介绍给可能会对他们感兴趣的用户。

接下来,我们把主观上的判断感受转换成客观的评价指标。

  1. 用户满意度。我们可以用点击率、用户停留时间和转换率等指标度量用户满意度。
  2. 预测准确度。这是度量一个推荐系统预测用户行为的能力。
  3. 覆盖率。这指的是推荐系统对物品长尾的发掘能力。简单来说就是推荐系统能够推荐出来的物品占总物品集合的比例。
  4. 多样性。也不能老是只推荐我最喜欢的东西给我。假设我80%的时间都在看喜剧片,20%的时间在看动画片。那推荐给我的10部影片中最好8部喜剧,2部动画。
  5. 新颖性。这指的是给用户推荐那些他们以前没有听说过的物品。
  6. 信任度。以让用户信任的方式推荐给用户更能让用户产生购买欲。比如拼多多的好友帮忙砍一刀。如果推荐商品是好友让自己帮忙砍过的,说明好友买过,用户就会对推荐结果更加信任。
  7. 实时性。推荐系统需要实时地更新推荐列表,并且能够将新加入的物品推荐给用户。
  8. 健壮性。这指的是推荐系统抗击作弊的能力。
  9. 商业目标。推荐系统更加注重网站的商业目标是否达成。



推荐系统怎么知道我喜欢什么?


▐  基于用户行为分析的推荐算法


我自己都不知道自己会喜欢什么。而且就算知道会喜欢什么,应该也很难用自然语言表达出来。更何况人的兴趣是会随着时间变化的,所以我们很难将我们的兴趣非常精准地表达给系统。因此,我们需要通过算法自动发掘用户行为数据,从用户的行为中推测出用户的兴趣,从而给用户推荐满足他们兴趣的物品。


基于用户行为的应用最具代表性的就是排行榜和购物车 / 稍后再看功能。排行榜就是基于用户行为统计的最简单的行为,但它大受好评。购物车中的物品也会被分析,其中最有名的就是啤酒和尿布的例子。很多妇女要在家照顾孩子,所以让丈夫去买尿布。而丈夫买尿布的时候还会买自己喜欢的啤酒,所以后来超市就把啤酒和尿布放在了同一个货架上,销量明显上升了。推荐系统做的就是这样的事情,通过用户行为发现规律,从而提高用户的推荐体验。


基于用户行为分析的推荐算法一般被称为协同过滤算法。顾名思义,协同过滤就是指用户可以齐心协力,通过不断地和网站互动,是自己的推荐列表能够不断地过滤掉自己不感兴趣的物品,从而越来越满足自己的需求。


用户行为数据在网站上最简单的存在形式就是日志,他记录了包含用户的网页浏览、购买、点击、评分和评论等等行为。得到用户行为之后,我们需要对这些行为数据进行分析,才能设计推荐算法。


用户活跃度和物品流行度的分布满足Power Law的分布,在互联网领域也叫长尾分布。简单来说,就是热门的东西因为热门所以会被更多的人关注,所以它就更热门了。而且一般来说,新用户倾向于浏览热门的物品。因为他们对网站还不熟悉;而老用户会逐渐开始浏览冷门的物品。


协同过滤算法,即基于用户行为分析的推荐算法,有许多实现方法。例如基于邻域的方法(neighborhood-based)、隐语义模型(Latent Factor Model,LFM)、基于图的随机游走算法等。其中,基于领域的方法可以简单理解为根据周围数据的推荐算法,主要包含:

  1. 基于用户的协同过滤算法(User Collaboration Filter,UserCF)。给用户推荐和他兴趣相似的其他用户喜欢的物品。
  2. 基于物品的协同过滤算法(Item Collaboration Filter,ItemCF)。给用户推荐和他之前喜欢的物品相似的物品。

著名的文章分享网站Digg使用UserCF,因为UserCF的推荐结果着重于反应和用户兴趣相似的小群体的热点;而亚马逊网使用ItemCF,因为ItemCF的推荐结果着重于维护用户的历史兴趣。简单来说,UserCF更社会化,反映小型兴趣群体中物品的热门程度;而ItemCF更个性化,反映用户自己的兴趣传承。


▐  隐语义模型


在实际推荐的过程中,UserCF很好实现,推荐系统只需要把购买过该用户相同物品的其他物品推荐给用户即可,但是在ItemCF中,推荐系统需要推荐该用户购买过的商品的同类商品。分类,又是一个难点。我们可以把自然语言、机器学习和模式识别都分到一类吗?不能,因为他们虽然有关联,但不同。那么我们又该如何将和它们相关的商品分类呢?


隐含语义分析技术(Latent Variable Analysis)出现了,这种分析技术会为你生成隐语义模型(Latent Factor Model,LFM)。隐含语义的意思是你在浏览网站时做了什么事情都会被记录下来,其中包括那些你没有明确表明出自己喜好的动作,例如点击、浏览时长。它基于用户行为统计的自动聚类,使得分类效果远远高于让商品编辑人来对商品进行分类。而隐含语义分析技术有很多著名的模型和方法,其中包括pLSA、LDA、隐含类别模型(Latent Class Model)、隐含主题模型(Latent Topic Model)和矩阵分解(Matrix Factorization)。这些技术和方法在本质上是相同的,你可以简单的理解为降维。


隐含语义分析技术是基于隐性反馈数据集的,这种数据集的特点是只有正样本(用户喜欢什么),而没有负样本(用户不喜欢什么)。这也是一个需要解决的问题。系统对每个用户采集负样本时,要采取那些很热门,而用户却没有行为的物品。同时,要保证正负行为样本的数量平衡。


隐语义模型LFM和基于邻域的方法哪个更好呢?答案是他们各有优势。

  1. LFM是基于机器学习的方法,有更好的理论基础;而基于邻域的方法是基于统计方法,没有学习过程。
  2. 基于邻域的方法需要维护一张离线的相关表,需要占据很大的内存;而LFM在建模的过程中,如果Factor是一个隐类,就可以很好地节省离线计算的内存。
  3. LFM和基于邻域的方法的算法时间复杂度总体上没有本质区别。LFM稍高些,因为该算法需要多次迭代。
  4. 基于邻域的方法需要将相关表缓存在内存中,从而可以在线进行实时预测;而LFM在生成一个用户推荐列表时速度太慢,因此不能在线实时计算和推荐。
  5. 基于邻域的方法可以很好地给出推荐解释,即为什么要推荐你这些商品;而LFM无法提供这样的解释。


现在,我们知道了推荐系统是如何推荐商品给用户的。那么我们该如何实现这些算法呢?


用户行为其实很容易用二分图表示,所以我们往往也把基于邻域的模型成为基于图的模型。一类顶点代表用户,一类顶点代表商品。研究人员设计了很多计算图中顶点之间相关性的方法,这里我提一个很有代表性的方法——一种基于随机游走的PersonalRank算法。


假设要给用户进行个性化推荐,可以从用户对应的节点开始在二分图上随机游走。游走到一个节点时,可以选择按照特定概率决定继续游走,还是停止这次游走并回到最初用户节点并重新开始游走。如果继续游走,那么就从该节点的相邻节点按照均匀分布随机选择一个节点作为下次游走的节点。经过多次游走后,每个物品节点的被访问概率会收敛到一个数字。这个数字就是最终的推荐列表中物品的权重。


在没有大量用户数据的情况下如何设计推荐系统呢?


对于很多在开始阶段就希望有个性化推荐应用的网站来说,如何在没有大量用户数据的情况下设计个性化推荐系统并且让用户对推荐结果满意,这就是冷启动问题。

冷启动问题主要分为三类:

  1. 用户冷启动。主要解决如何给新用户做个性化推荐。
  2. 物品冷启动。主要解决如何将新的物品推荐给可能对它感兴趣的用户。
  3. 系统冷启动。主要解决在发布网站的初期就让用户体验到个性化推荐服务。


对于冷启动问题,解决方案也有很多。

  1. 利用用户注册信息。包括人口统计学信息、用户自己描述的兴趣、从其它网站导入的行为数据。
  2. 选择合适的物品启动用户的兴趣。在新用户第一次访问网站时,先给用户提供一些物品,让用户反馈对这些物品的兴趣,然后根据反馈结果提供个性化推荐。
  3. 利用物品的内容信息。主要解决新加入的物品如何推荐给潜在的用户。对于UserCF,可以将物品投放给曾经喜欢过和它内容相似的其他用户;对于ItemCF,物品冷启动的问题比较严重,我们只能频繁更新物品相似度表(比如半小时计算一次)。
  4. 发挥专家的作用。例如个性化电台应用Pandora雇佣了一批专家,使用400多个特征标注了所有的歌曲,从而计算音乐间的相似度。


推荐系统中很方便并且常见的工具——标签


推荐系统的目的是联系用户和物品,而主流的联系用户和物品的方式有三种。

  1. 利用用户喜欢过的物品,给它推荐相似的物品。(ItemCF)
  2. 利用和用户兴趣相似的其他用户,推荐这些用户喜欢的物品。(UserCF)
  3. 通过一些物品特征(Feature)联系用户和物品,也就是给用户推荐那些具有用户喜欢的特征的物品。这里的特征可以表现为物品的属性集合,也可以表现为隐语义模型,或者表现为”标签“。


标签的官方定义是一种无层次化结构的、用来描述信息的关键词,可以用来描述物品的语义。标签应用分为两种:一种是让作者或者专家给物品打标签;另一种是和让普通用户给物品打标签,也就是用户生成内容(User Generated Content,UGC)。
标签系统中的推荐问题主要有两个。

  1. 如何利用用户打标签的行为为其进行推荐物品?(基于标签的推荐)
  2. 如何在用户给物品打标签时为其推荐合适该物品的标签?(标签推荐)


关于根据标签给用户推荐物品的问题,豆瓣就很好地利用了数据,将标签系统融入到了整个产品线中。首先,在每本书的页面上都提供了一个叫做”豆瓣成员常用标签“的应用,它给出了这本书最常被打的标签。并且在最终的个性化推荐结果里,豆瓣利用标签将用户的推荐聚类,显示了对不同标签下用户的推荐结果。这也是基于标签推荐的最大好处,就是可以利用标签做推荐解释,毕竟要让用户直观上觉得推荐结果有道理是很困难的。
另一个问题就是如何给用户推荐标签。给用户推荐标签的原因有两个:方便用户输入标签和提高标签质量。给用户推荐标签的方法有四种:

  1. 给用户推荐系统里最热门的标签(PopularTags)
  2. 给用户推荐该物品最热门的标签
  3. 给用户推荐他自己最经常使用的标签
  4. 将该物品最热门的标签和用户自己最经常使用的标签,通过一个系数线性加权,生成一个融合后的结果(HybridPopularTags)


推荐算法的最后一块拼图——上下文信息


之前的推荐算法主要集中研究了如何联系用户兴趣和物品,但都忽略了用户所处的上下文(Context)。上下文信息包括用户访问推荐系统的时间、地点、心情等。举些最简单的例子,夏天推荐夏装、冬天推荐冬装;外卖软件只会推荐给你附近的食物;你心情不好的时候音乐软件不会给你放嗨歌。


▐  时间上下文信息


时间是一种重要的上下文信息,主要表现在:

  1. 用户兴趣是变化的。用户的兴趣会因为自身的原因产生变化,比如我前段时间我喜欢爵士乐,而我们现在就特别喜欢流行乐,没道理的。
  2. 物品也是有生命周期的。最明显的例子就是新闻,推荐系统不应该推荐十年前的新闻给用户。
  3. 季节效应。包含天气等季节和节日等情况。春节不可能给我推荐圣诞树是吧。


用户的兴趣是不断变化的,其变化体现在用户不断增加的新行为中。一个实时的推荐系统需要能够实时响应用户的新行为。举个列子,我如果对某一部电影表示了喜欢,那么几秒钟之后,系统就会推荐给我类似的影片,而不是说要等好久。这意味着推荐算法本身具有实时性。同时还要考虑用户的近期行为和长期行为的影响,既要让推荐系统反应出对近期行为的变化,又不能让推荐列表完全受用户近期行为的影响。


如果打开一个图书网站,而这个网站每天都给你推荐一样的图书,那会很无趣对吧?


推荐系统每天推荐结果的变化程度,就是推荐系统的时间多样性。UserCF和ItemCF都可以利用时间信息提高预测的准确率。


▐  地点上下文信息


用户到了不同的地方,兴趣也会有所不同。比如我到了西安,那肯定是想品尝西安的地道美食。这种情况下,地点/距离就成为了推荐算法中最重要的一环。例如Google在2010年推出了Hotpot服务,让用户对自己去过的地方评分,然后通过评分给用户推荐地点。


而用户兴趣和地点相关的特征主要有:

  1. 兴趣本地化。不同国家和地区用户的兴趣存在着一定的从差异性。
  2. 活动本地化。研究人员发现,45%的用户其活动半径不超过10英里,而75%的用户活动半径不超过50英里。

推荐系统的强力帮手——社交网络

社交网络简直就是推荐系统的大杀器。调查结果显示,90%的用户相信朋友对他们的推荐,并且70%的用户相信网上其他用户对广告商品的评论。社交网络定义了用户之间的联系,因此可以用图定义社交网络。社交网络一般分为三类:

  1. 第一类是以Facebook为代表。它的朋友关系是需要双向确认的,所以在社交网络上可以用无向边连接用户。
  2. 第二类是以Twitter为代表。它的朋友关系是单向的,因此在社交网络上可以用有向边连接用户。
  3. 第三类是以豆瓣为代表。用户之间没有明确的关系,但是意味着用户属于不同的社区。


社交网络的用户关注量也呈长尾分布(Power Law),即关注很多人的用户占少数,而绝大多数人只关注很少的人。
利用社交网络进行推荐的优点在于:好友推荐可以增加推荐的信任度,和社交网络可以解决冷启动问题。
而社交网络推荐的缺点在于:很多时候这种推荐并不一定能提高推荐算法的离线精度(准确率和召回率)。毕竟用户好友的兴趣往往和用户的兴趣并不一致。
我们之前提到的基于邻域的方法就可以用在社交网络推荐中,不过由于大型网站中用户的数量十分庞大,所以用户的历史行为数据也十分庞大。如果我们需要比较实时的数据,那么缓存中的数据就要比较频繁地更新,而这是比较重的操作。当然,我们也可以通过一些改造让该算法具有比较快的影响时间。其中,比较好的改造方法是重新设计数据库。Twitter的解决方案是给每个用户维护一个消息队列。当一个用户发一条动态时,所有关注他的用户的消息队列中都会加入这条动态。这么做的优点是用户获取信息墙时可以直接读取消息队列中的消息,所以终端用户的读操作更快。但与之相对应的,写操作会变得很重。如果一个人被很多人关注时,他发了一条动态,就会触发大量的写操作。而Twitter通过大量的缓存解决了这个问题。
相对于之前提到的协同过滤算法,社会化推荐系统的优势不在于增加预测的准确度,而是在于通过用户的好友增加用户对推荐结果的信任度,从而让用户点击那些很冷门的推荐结果。往往社会化推荐的用户满意度是明显高于协同过滤算法的。


推荐系统架构实例


假设前面的推荐算法我都了解并且实现了,那么推荐系统是如何和网站的其它系统接口的?
一般来说,除了推荐系统,网站还会包括用户界面(User Interface,UI)和用户行为数据。网站的UI系统负责给用户展示网页并和用户交互。网站会通过日志系统将用户在UI上的各种各样的行为记录到用户的行为日志中。而推荐系统通过分析用户的行为日志,给用户生成推荐列表,最终展示到网站的界面上。

关于UI,功能往往有:

  1. 通过一定方式展示物品。包括物品的标题、缩略图和介绍等。
  2. 提供推荐理由。这可以增加用户对推荐结果的信任度。
  3. 提供一些按钮让用户对推荐结果进行反馈。这是为了让推荐算法不断改进,从而提高用户的个性化推荐体验。


关于用户行为数据,最关键的问题就是如何收集和存储。


从实时存取的角度上看,购买、收藏、评论、评分、分享等行为都是需要按时存取的,因为用户一旦有了这些行为,界面上就需要体现出来。而例如浏览网页和搜索这类行为并不需要实时存取和展示。一般来说,需要实时存取的数据存储在数据库和缓存中,而大规模的非实时存取的数据存储在分布式文件系统(例如HDFS)中。


推荐系统联系用户和物品的方式,即用户有可能喜欢上该物品的方式主要有三种。

  1. 用户喜欢其他物品,而其他物品与该物品相似。
  2. 和用户有相似性去的好友喜欢该物品。
  3. 用户喜欢具有/具有某种特征,而该物品就具有这种特征。


那么推荐系统的核心任务就非常明显了,一方面是如何为给定用户生成特征,另一个是如何根据特征找到物品。


用户的特征种类非常多,主要包含:

  1. 人口统计学特征。包括用户的年龄、性别、国籍和民族等用户在注册时提供的信息。
  2. 用户的行为特征。包括用户浏览/收藏过的物品、给什么物品打过什么样的分数等。
  3. 用户的话题特征。可以根据用户的历史行为利用话题模型将影视作品、图书聚合成不同的话题,并且计算出每个用户对什么话题感兴趣。


如果一个推荐系统要考虑到各种特征,那么将会非常复杂。因此,推荐系统需要由多个推荐引擎组权重或者优先级合并、排序然后返回。


而推荐引擎的架构主要包括三部分。

  1. 负责从数据库或者缓存中拿到用户行为数据,通过分析不同行为,生成当前用户的特征向量。
  2. 负责将用户的特征向量通过特征-物品相关矩阵转换为初始推荐物品列表。
  3. 负责对初始的推荐列表进行过滤、排名等处理,从而生成最终的推荐结果。



最后


整本书看下来后,推荐系统也算是入门了。而这本书也的确适合推荐领域的新手去看,因为这本书的主要目的更接近于科普,而不是描述具体的推荐算法。读这本书的过程中,我频繁感觉到自己在生活的方方面面都在被推荐系统引导着,这感觉真的是太奇妙了。


团队介绍


我们是大淘宝技术-内容技术-内容消费&社区互动团队,是阿里的一支明星团队,目前负责阿里电商平台的首页、信息流推荐和逛逛,其中手机淘宝首页、信息流、购后链路等场景每天服务数亿用户,大促核心系统峰值QPS千万计。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
存储 消息中间件 缓存
No182.精选前端面试题,享受每天的挑战和学习
No182.精选前端面试题,享受每天的挑战和学习
No182.精选前端面试题,享受每天的挑战和学习
|
3月前
|
消息中间件 缓存 前端开发
No209.精选前端面试题,享受每天的挑战和学习
No209.精选前端面试题,享受每天的挑战和学习
No209.精选前端面试题,享受每天的挑战和学习
|
3月前
|
JavaScript 前端开发 开发者
No29.精选前端面试题,享受每天的挑战和学习
No29.精选前端面试题,享受每天的挑战和学习
|
3月前
|
前端开发 安全 JavaScript
No42.精选前端面试题,享受每天的挑战和学习
No42.精选前端面试题,享受每天的挑战和学习
|
3月前
|
JSON 前端开发 JavaScript
No44.精选前端面试题,享受每天的挑战和学习
No44.精选前端面试题,享受每天的挑战和学习
|
3月前
|
Web App开发 前端开发 JavaScript
No160.精选前端面试题,享受每天的挑战和学习
No160.精选前端面试题,享受每天的挑战和学习
|
3月前
|
Web App开发 移动开发 前端开发
No91.精选前端面试题,享受每天的挑战和学习
No91.精选前端面试题,享受每天的挑战和学习
|
3月前
|
存储 自然语言处理 前端开发
No88.精选前端面试题,享受每天的挑战和学习
No88.精选前端面试题,享受每天的挑战和学习
|
3月前
|
JSON 前端开发 JavaScript
No140.精选前端面试题,享受每天的挑战和学习
No140.精选前端面试题,享受每天的挑战和学习
|
3月前
|
小程序 前端开发 JavaScript
No56.精选前端面试题,享受每天的挑战和学习
No56.精选前端面试题,享受每天的挑战和学习