本文主要介绍什么是推荐系统,为什么需要推荐系统,如何实现推荐系统的方案,包括实现推荐系统的一些常见模型,希望给读者提供学习实践参考。
为什么需要推荐系统
对于信息消费者,需要从大量信息中找到自己感兴趣的信息,而在信息过载时代,用户难以从大量信息中获取自己感兴趣、或者对自己有价值的信息。
对于信息生产者,需要让自己生产的信息脱颖而出,受到广大用户的关注。从物品的角度出发,推荐系统可以更好地发掘物品的长尾(long tail)。
长尾效应是美国《连线》杂志主编 Chris Anderson 在 2006 年出版的《长尾理论》一书中指出,传统的 80/20 原则(80% 的销售额来自于 20% 的热门品牌)在互联网的加入下会受到挑战。互联网条件下,由于货架成本极端低廉,电子商务网站往往能出售比传统零售店更多的商品。这些原来不受到重视的销量小但种类多的产品或服务由于总量巨大,累积起来的总收益超过主流产品的现象。
主流商品往往代表了绝大多数用户的需求,而长尾商品往往代表了一小部分用户的个性化需求。
推荐系统通过发掘用户的行为,找到用户的个性化需求,从而将长尾商品准确地推荐给需要它的用户,帮助用户发现那些他们感兴趣但很难发现的商品。
推荐系统的任务在于:
一方面帮助用户发现对自己有价值的信息。
另一方面让信息能够展现在对它感兴趣的用户面前,从而实现信息消费者和信息生产者的双赢。
推荐系统的本质
通过一定的方式将用户和物品联系起来,而不同的推荐系统利用了不同的方式。
推荐系统就是自动联系用户和物品的一种工具,它能够在信息过载的环境中帮助用户发现令他们感兴趣的信息,也能将信息推送给对它们感兴趣的用户。
评价指标
从产品的角度出发,评价一个推荐系统可以从以下维度出发:
用户满意度:用户作为推荐系统的重要参与者,其满意度是评测推荐系统的最重要指标。但是,用户满意度没有办法离线计算,只能通过用户调查或者在线实验获得。
预测准确度:预测准确度度量一个推荐系统或者推荐算法预测用户行为的能力。这个指标是最重要的推荐系统离线评测指标,从推荐系统诞生的那一天起,几乎 99% 与推荐相关的论文都在讨论这个指标。
在计算该指标时需要有一个离线的数据集,该数据集包含用户的历史行为记录。然后,将该数据集通过时间分成训练集和测试集。
最后,通过在训练集上建立用户的行为和兴趣模型预测用户在测试集上的行为,并计算预测行为和测试集上实际行为的重合度作为预测准确度。
覆盖率:覆盖率( coverage )描述一个推荐系统对物品长尾的发掘能力。覆盖率有不同的定义方法,最简单的定义为推荐系统能够推荐出来的物品占总物品集合的比例。
多样性:用户的兴趣是广泛的,为了满足用户广泛的兴趣,推荐列表需要能够覆盖用户不同的兴趣领域,即推荐结果需要具有多样性。
新颖性:新颖的推荐是指给用户推荐那些他们以前没有听说过的物品。在一个网站中实现新颖性的最简单办法是,把那些用户之前在网站中对其有过行为的物品从推荐列表中过滤掉。
惊喜度:与新颖性不同,如果推荐结果和用户的历史兴趣不相似,但却让用户觉得满意,那么就可以说推荐结果的惊喜度很高,而推荐的新颖性仅仅取决于用户是否听说过这个推荐结果。
信任度:对于基于机器学习的自动推荐系统,同样存在信任度( trust )的问题,如果用户信任推荐系统,那就会增加用户和推荐系统的交互。
同样的推荐结果,以让用户信任的方式推荐给用户就更能让用户产生购买欲,而以类似广告形式的方法推荐给用户就可能很难让用户产生购买的意愿。
度量推荐系统的信任度只能通过问卷调查的方式,询问用户是否信任推荐系统的推荐结果。
实时性:推荐系统需要实时地更新推荐列表来满足用户新的行为变化,推荐系统需要能够将新加入系统的物品推荐给用户。这主要考验了推荐系统处理物品冷启动的能力。
健壮性:任何一个能带来利益的算法系统都会被人攻击,这方面最典型的例子就是搜索引擎。
搜索引擎的作弊和反作弊斗争异常激烈,而健壮性(即 robust,鲁棒性)指标衡量了一个推荐系统抗击作弊的能力。
基于用户行为推荐
用户行为
用户行为可以分为显性反馈行为(explicit feedback)和隐性反馈行为(implicit feedback)。
显性反馈行为:指用户明确表示对物品喜好的行为,主要方式就是评分和喜欢/不喜欢。
常见的显性反馈行为可以参考如下表格:
隐性反馈行为(implicit feedback):指的是那些不能明确反应用户喜好的行为。最具代表性的隐性反馈行为就是页面浏览行为。
用户浏览一个物品的页面并不代表用户一定喜欢这个页面展示的物品,比如可能因为这个页面链接显示在首页,用户更容易点击它而已。
相比显性反馈,隐性反馈虽然不明确,但数据量更大。在很多网站中,很多用户甚至只有隐性反馈数据,而没有显性反馈数据。
基于用户行为数据设计的推荐算法一般称为协同过滤算法。学术界对协同过滤算法进行了深入研究,提出了很多方法。
比如基于邻域的算法(neighborhood-based)、隐语义模型(latent factor model)、基于图的随机游走算法(random walk on graph)等。
下面主要展开介绍基于领域的算法和隐语义模型算法。
基于领域的算法
基于邻域的方法是最著名的、在业界得到最广泛应用的推荐算法,主要包含下面两种算法:
基于用户的协同过滤算法(UserCF)。
基于物品的协同过滤算法(ItemCF)。
算法涉及的基本步骤如下:
收集用户偏好,把用户对物品的偏好转换成可量化的综合评分值。
找到相似的用户或物品。
计算推荐。
计算相似度主要有以下 3 种计算方式:
①欧氏距离(Euclidean Distance)
向量欧式距离:
相似度:
②皮尔逊相关系数(Pearson Correlation Coefficient)
协方差,用来衡量 2 个向量的变化趋势是否一致:
标准差:
皮尔逊相关系数:
皮尔逊相关系数使用协方差除以 2 个向量的标准差得到,值的范围[-1,1]。
③Cosine 相似度(Cosine Similarity,余弦距离)
Cosine 相似度其实就是求 2 个向量的夹角。3 种计算相关系数的算法中,皮尔逊相关系数在生产中最为常用。
通过相似度计算出若干个最相似的邻居后,如何选择邻居?主要有以下方式:
基于固定数量的邻居:该方式直接选择固定数量的邻居,有可能把相似度较小的对象也引入。
基于相似度门槛的邻居:该方式先用相似度门槛筛选出邻居的一个集合,再从集合里面挑选出相似度较大的邻居。可以避免把相似度较小的对象引入,效果更好。
简单而言,就是给用户推荐和他兴趣相似的其他用户喜欢的物品。
在一个在线个性化推荐系统中,当一个用户 A 需要个性化推荐时,可以先找到和他有相似兴趣的其他用户,然后把那些用户喜欢的、而用户 A 没有听说过的物品推荐给 A 。这种方法称为基于用户的协同过滤算法。
用户 A 与用户 C 的兴趣比较相似,用户 C 喜欢了物品 4,所以给用户 A 推荐物品 4。
已知用户评分矩阵 Matrix R(一般都是非常稀疏的),推断矩阵中问号处的评分值。
对于一个新用户,很难找到邻居用户。
对于一个新物品,所有最近的邻居都在其上没有多少打分。
相似度计算最好使用皮尔逊相似度。
计算用户相似度考虑共同打分物品的数目。
比如乘上,n 为共同打分的商品数,N 为指定阈值,这样可以让 2 个用户的共同打分的商品数越少,相似度越小。
对打分进行归一化处理,比如把原来分数值范围是[0,10],归一化后变成[0,1]。
设置一个相似度阈值。
数据稀疏问题,数据存取困难。
数百万用户计算,用户之间两两计算相似度,计算量过大。
人是善变的。
基于物品的协同过滤算法(简称 ItemCF)就是给用户推荐那些和他们之前喜欢的物品相似的物品。
比如,该算法会因为你购买过《数据挖掘导论》而给你推荐《机器学习》。
不过,ItemCF 算法并不利用物品的内容属性计算物品之间的相似度,它主要通过分析用户的行为记录计算物品之间的相似度。
该算法认为,物品 A 和物品 B 具有很大的相似度是因为喜欢物品 A 的用户大都也喜欢物品 B。
物品 1 和物品 3 都被用户 A 和用户 B 喜欢,所以认为是相似物品,所以当用户 C 喜欢物品 1,就给用户 C 推荐物品 3。
算法主要步骤如下:
计算物品之间的相似度。
根据物品的相似度和用户的历史行为给用户生成推荐列表。
需要用户 5 对物品 1 的评分 r_15,由于物品 3、物品 6 是与物品 1 最为相似的 2 个物品,取相似度作为权重,所以 r_15 可以预测如下:
计算性能高,通常用户数量远大于物品数量,实际计算物品之间的相似度,可以只选择同一个大分类下的类似物品来计算,以此减少计算量。
可预先保留结果,物品并不善变。
UserCF 给用户推荐那些和他有共同兴趣爱好的用户喜欢的物品,而 ItemCF 给用户推荐那些和他之前喜欢的物品类似的物品。
从这个算法的原理可以看到:
UserCF 的推荐结果着重于反映和用户兴趣相似的小群体的热点。
ItemCF 的推荐结果着重于维系用户的历史兴趣。
换句话说:
UserCF 的推荐更社会化,反映了用户所在的小型兴趣群体中物品的热门程度。
ItemCF 的推荐更加个性化,反映了用户自己的兴趣传承。
基于用户标签推荐
推荐系统的目的是联系用户的兴趣和物品,这种联系需要依赖不同的媒介。
目前流行的推荐系统基本上通过 3 种方式联系用户兴趣和物品:
基于用户推荐 UserCF:利用和用户兴趣相似的其他用户,给用户推荐那些和他们兴趣爱好相似的其他用户喜欢的物品。
基于物品推荐 ItemCF:给用户推荐与他喜欢过的物品相似的物品。
基于特征:这里的特征有不同的表现方式,比如可以表现为物品的属性集合(比如对于图书,属性集合包括作者、出版社、主题和关键词等),也可以表现为隐语义向量(latent factor vector)。
标签相关问题
根据维基百科的定义,标签是一种无层次化结构的、用来描述信息的关键词,它可以用来描述物品的语义。
根据给物品打标签的人的不同,标签应用一般分为两种:
一种是让作者或者专家给物品打标签。
另一种是让普通用户给物品打标签,也就是 UGC(User Generated Content,用户生成的内容)的标签应用 UGC 的标签系统是一种表示用户兴趣和物品语义的重要方式。
当一个用户对一个物品打上一个标签,这个标签一方面描述了用户的兴趣,另一方面则表示了物品的语义,从而将用户和物品联系了起来。
因此下面主要讨论 UGC 的标签应用,研究用户给物品打标签的行为,探讨如何通过分析这种行为给用户进行个性化推荐。
从产品的角度,我们需要理解用户打标签的行为,为什么要打标签,只有深入了解用户的行为,我们才能基于这个行为设计出令他们满意的个性化推荐系统。
用户这个行为背后的原因主要可以从 2 个维度进行探讨:
社会维度,有些用户标注是给内容上传者使用的(便于上传者组织自己的信息),而有些用户标注是给广大用户使用的(便于帮助其他用户找到信息)。
功能维度,有些标注用于更好地组织内容,方便用户将来的查找,而另一些标注用于传达某种信息,比如照片的拍摄时间和地点等。
用户常打的标签如下:
表明物品是什么。
表明物品的种类。
表明谁拥有物品,比如很多博客的标签中会包括博客的作者等信息。
表达用户的观点,比如用户认为网页很有趣,就会打上标签 funny(有趣),认为很无聊,就会打上标签 boring(无聊)。
用户相关的标签,比如 my favorite(我最喜欢的)、my comment(我的评论)等。
用户的任务,比如 to read(即将阅读)、 job search(找工作)等。
用户浏览某个物品时,标签系统非常希望用户能够给这个物品打上高质量的标签,这样才能促进标签系统的良性循环。因此,很多标签系统都设计了标签推荐模块给用户推荐标签。
一般认为,给用户推荐标签有以下好处:
方便用户输入标签,让用户从键盘输入标签无疑会增加用户打标签的难度,这样很多用户不愿意给物品打标签,因此我们需要一个辅助工具来减小用户打标签的难度,从而提高用户打标签的参与度。
提高标签质量,同一个语义不同的用户可能用不同的词语来表示。这些同义词会使标签的词表变得很庞大,而且会使计算相似度不太准确。
而使用推荐标签时,我们可以对词表进行选择,首先保证词表不出现太多的同义词,同时保证出现的词都是一些比较热门的、有代表性的词。
用户 u 给物品 i 打标签时,我们有很多方法可以给用户推荐和物品 i 相关的标签。
比较简单的方法有 4 种:
给用户 u 推荐整个系统里最热门的标签(这里将这个算法称为 PopularTags),这个算法太简单了,甚至于不能称为一种标签推荐算法。
给用户 u 推荐物品 i 上最热门的标签(这里将这个算法称为 ItemPopularTags)。
用户 u 推荐他自己经常使用的标签(这里将这个算法称为 UserPopularTags)。
前面两种的融合(这里记为 HybridPopularTags),该方法通过一个系数将上面的推荐结果线性加权,然后生成最终的推荐结果。
一个最简单的算法
基本步骤如下:
统计每个用户最常用的标签。
对于每个标签,统计被打过这个标签次数最多的物品。
对于一个用户,首先找到他常用的标签,然后找到具有这些标签的最热门物品推荐给这个用户。
对于上面算法,用户 u 对于物品 i 的兴趣公式如上:
是用户 u 打过的标签集合。
是物品 i 被打过标签的集合。
是用户 u 打过标签 b 的次数。
是物品 i 被打过标签 b 的次数。
某用户使用过“幽默”标签 10 次,“搞笑”标签 3 次,“讽刺”标签 6 次。这 3 个标签被物品 A 使用的次数分别的 4、7、2。
由此计算用户对物品的兴趣值为:
上面的计算公式会倾向于给热门标签对应的热门物品很大的权重,因此会造成推荐热门的物品给用户,从而降低推荐结果的新颖性,还有数据稀疏性的问题,可以通过计算结果除以惩罚项来进行修正。
系统冷启动问题
问题简介
系统冷启动(cold start)问题主要在于如何在一个新开发的网站上(还没有用户,也没有用户行为,只有一些物品的信息)设计个性化推荐系统,从而在网站刚发布时就让用户体验到个性化推荐服务这一问题。
主要可以分为 3 类:
用户冷启动:用户冷启动问题主要在于如何给新用户做个性化推荐。当新用户到来时,我们没有他的行为数据,所以也无法根据他的历史行为预测其兴趣,从而无法借此给他做个性化推荐。
物品冷启动:物品冷启动问题主要在于如何解决将新的物品推荐给可能对它感兴趣的用户。
系统冷启动:系统刚刚新上线,用户、物品数据较少。
解决思路
针对上述 3 类冷启动问题,一般来说,可以参考如下解决方案:
提供非个性化的推荐:非个性化推荐的最简单例子就是热门排行榜,我们可以给用户推荐热门排行榜,然后等到用户数据收集到一定的时候,再切换为个性化推荐。这也是最常见的解决方案。
利用用户注册时提供的年龄、性别等数据做粗粒度的个性化。
要求用户在首次登录时提供反馈,比如输入感兴趣的标签,或感兴趣的物品。收集用户对物品的兴趣信息,然后给用户推荐那些和这些物品相似的物品。
对于新加入的物品,可以利用内容信息,将它们推荐给喜欢过和它们相似的物品的用户。
在系统冷启动时,可以引入专家的知识,通过一定的高效方式迅速建立起物品的相关度表。
评估指标
令是根据用户在训练集上的行为给用户作出的推荐列表,是用户在测试集上的行为列表。
准确率
用于度量模型的预测值与真实值之间的误差。
召回率
用于度量有多个正例被分为正例,这里是正确推荐的数量占测试集合上用户行为列表的比例。
覆盖率
用户衡量推荐的物品占全部商品的比例,一般我们推荐的物品希望尽可能覆盖更多类别 。常见有 2 种计算方法:
通过推荐的商品占总商品的比例:
或者通过推荐物品的熵值得到覆盖率,熵值越大,覆盖率越大:
多样性
用于衡量每次推荐里面的推送的物品占所有可能性的比率,多样性越大,每次推荐的物品越丰富。
实际上,不同的平台还有不同的衡量标准,例如用户满意度,广告收益,需要结合实际业务情况做策略调整。
系统架构
基于特征的推荐系统
再次回顾一下上面提到的推荐系统联系用户和物品的 3 种途径。
将这 3 种方式都抽象一下就可以发现,如果认为用户喜欢的物品也是一种用户特征,或者和用户兴趣相似的其他用户也是一种用户特征,那么用户就和物品通过特征相联系。
用户特征种类特别多,主要包括以下几类:
用户注册属性:年龄、性别、国籍等。
用户行为特征:浏览、点赞、评论、购买等。
系统整体架构
由于推送策略本身的复杂性,如果要在一个系统中把上面提到的各种特征和任务都统筹考虑,那么系统将会非常复杂,而且很难通过配置文件方便地配置不同特征和任务的权重。
因此,推荐系统需要由多个推荐引擎组成,每个推荐引擎负责一类特征和一种任务,而推荐系统的任务只是将推荐引擎的结果按照一定权重或者优先级合并、排序然后返回。
这样做有 2 个好处:
可以方便地增加/删除引擎,控制不同引擎对推荐结果的影响。对于绝大多数需求,只需要通过不同的引擎组合实现。
可以实现推荐引擎级别的用户反馈。每一个推荐引擎其实代表了一种推荐策略,而不同的用户可能喜欢不同的推荐策略:
有些用户可能喜欢利用他的年龄性别作出的推荐。
有些用户可能比较喜欢看到新加入的和他兴趣相关的视频。
有些用户喜欢比较新颖的推荐。
有些用户喜欢专注于一个邻域的推荐。
有些用户喜欢多样的推荐。
我们可以将每一种策略都设计成一个推荐引擎,然后通过分析用户对推荐结果的反馈了解用户比较喜欢哪些引擎推荐出来的结果,从而对不同的用户给出不同的引擎组合权重。
推荐引擎架构
推荐引擎使用一种或几种用户特征,按照一种推荐策略生成一种类型物品的推荐列表,基本架构如下图:
如上图,推荐引擎架构主要包括 3 部分:
用户行为数据模块:图中 A 部分,该部分负责从数据库或者缓存中拿到用户行为数据,通过分析不同行为,生成当前用户的特征向量。
不过如果是使用非行为特征,就不需要使用行为提取和分析模块了。该模块的输出是用户特征向量。
物品数据模块:图中 B 部分,该部分负责将用户的特征向量通过特征-物品相关矩阵转化为初始推荐物品列表。
最终结果生成模块:图中 C 部分,该部分负责对初始的推荐列表进行过滤、排名等处理,从而生成最终的推荐结果。
其中,有几个模块需要特别介绍一下:
候选物品集合:特征-物品相关推荐模块还可以接受一个候选物品集合。候选物品集合的目的是保证推荐结果只包含候选物品集合中的物品。它的应用场合一般是产品需求希望将某些类型的电视剧推荐给用户。
比如有些产品要求给用户推荐最近一周加入的新物品,那么候选物品集合就包括最近一周新加的物品。
过滤模块:在得到初步的推荐列表后,还不能把这个列表展现给用户,首先需要按照产品需求对结果进行过滤,过滤掉那些不符合要求的物品。
一般来说,过滤模块会过滤掉以下物品:
用户已经产生过行为物品,因为推荐系统的目的是帮助用户发现物品,因此没必要给用户推荐他已经知道的物品,这样可以保证推荐结果的新颖性。
候选物品以外的物品,候选物品集合一般有两个来源,一个是产品需求。比如在首页可能要求将新加入的物品推荐给用户,因此需要在过滤模块中过滤掉不满足这一条件的物品。
另一个来源是用户自己的选择,比如用户选择了某一个价格区间,只希望看到这个价格区间内的物品,那么过滤模块需要过滤掉不满足用户需求的物品。
某些质量很差的物品,为了提高用户的体验,推荐系统需要给用户推荐质量好的物品,那么对于一些绝大多数用户评论都很差的物品,推荐系统需要过滤掉。这种过滤一般以用户的历史评分为依据,比如过滤掉平均分在 2 分以下的物品。
排名模块:经过过滤后的推荐结果直接展示给用户一般也没有问题,但如果对它们进行一些排名,则可以更好地提升用户满意度。实际进行排名时,可以基于新颖性、多样性、用户反馈进行排名优化。
总结
除了本文介绍的模型算法,基于用户行为推荐还有隐语义模型,基于图的模型比较常见,还有的基于上下文、社交网络推荐。实际有一些常见的算法库可以实现推荐系统运算,包括 LibRec,Crab 等。
参考资料:
《推荐系统实践》
一文读懂推荐系统知识体系
https://cloud.tencent.com/developer/article/1070529
个性化推荐系统总结
https://www.jianshu.com/p/319e4933c5ba
推荐系统介绍
https://www.cnblogs.com/redbear/p/8594939.html
作者:陈彩华
编辑:陶家龙、孙淑娟
投稿:有投稿、寻求报道意向技术人请联络 editor@51cto.com
陈彩华(caison),从事服务端开发,善于系统设计、优化重构、线上问题排查工作,主要开发语言是 Java,微信号:hua1881375。
精彩文章推荐: