双11刚刚过去,双12即将到来,不知大家的手是否还在?经历过某猫某东某宝拼杀的各位买家,大概都有过被这些平台猜透小心思,“看了又看、买了又买”的经历。那么,它们是怎样猜透你的心的呢?
今天,我们来介绍一下推荐系统算法中的元老级算法:基于物品的协同过滤算法。
基于物品的协同过滤算法
不管你在“双11”或者“618”这样的“商造节日”中有没有“剁”过手,对“看了该商品的人还看了”这样的推荐形式也一定不陌生。无论是淘宝还是京东,抑或其他电商网站,这样的推荐形式都可以说是推荐系统的标配。类似的还有点评类网站的“喜欢了这部电影的人还喜欢”,社交媒体网站的“关注了TA的人还关注了”,等等。文案大概类似,动词不同而已。这样的推荐形式都来自一个“古老”的推荐算法——基于物品的协同过滤。
做推荐系统不知道“基于物品的协同过滤”,等同于程序员不懂得冒泡排序。这个朴素的算法就像乔峰大战聚贤庄所用的“太祖长拳”一样,简单、直接、有效,读过高中就懂,用得好就能战胜绝大多数武林豪杰。下面就来聊聊这个朴素的算法。
基于物品的协同过滤诞生于1998年,是由亚马逊首先提出的。2001年,其发明者发表了相应的论文。这篇论文在Google学术上的引用数已经近7000次,并且在WWW2016大会上荣获“时间检验奖”,颁奖词是:“这篇杰出的论文深深地影响了实际应用。”历经15年,它仍然在发光发热,显然这个奖它当之无愧。虽然今天各家公司都在使用这个算法,好像它是一个公共资源一样,但亚马逊早在1998年,即论文发表前三年就申请了专利。
算法原理
通常人的行为会有惯性,这种惯性可能是兴趣使然,可能是从众心理使然,也可能是下意识的行为使然。表现就是,看着碗里的想着锅里的,因为碗里的和锅里的总是很类似。这就是基于物品的协同过滤算法最原始的想法:给你推荐和你喜欢的物品相似的物品。问题在于这个“相似的物品”是如何计算出来的。在基于内容的推荐系统中,相似物品是用内容的相似性计算出来的,这当然也是很符合直觉的做法。但是实际上人的群体行为还会有一些内容特征抓不到的相似性,同一个群体喜欢的物品,总是有某种共同的因素蕴藏其中,这种共同的因素虽然并不能被准确地表述出来,但可以用来做出很好的推荐。
解释了对基于物品的协同过滤算法的直觉理解后,再看看在技术上有何必要性。
在基于物品的协同过滤算法出现之前,信息过滤系统最常使用的是基于用户的协同过滤算法。基于用户的协同过滤算法首先计算相似用户,然后再根据相似用户的喜好推荐物品,这个算法有以下几个问题。
反观基于物品的协同过滤算法,它首先计算相似物品,然后再根据用户消费过或者正在消费的物品为其推荐相似的物品,基于物品的算法怎样解决上面的这三个问题呢?
首先,严格地说,同一时期可以推荐的物品数量往往少于用户数量,所以一般计算物品之间的相似度就不会成为瓶颈。其次,物品之间的相似度不易改变,没有用户的品味变化快。这样就完全解耦了用户兴趣迁移这个问题。最后,物品对应的消费者数量较大,所以计算出的物品相似度比用户相似度更可靠。
协同过滤算法最依赖的是用户物品的关系矩阵,基于物品的协同过滤算法也不例外,它的基本步骤如下。
接下来详细讲解一下如何计算物品之间的相似度。从用户物品关系矩阵中得到的物品向量长什么样子呢?
接下来就是如何两两计算物品的相似度了,一般选择余弦相似度,当然还有其他的相似度计算法方法。计算公式如下:
在这个公式中,分母表示两个物品向量的长度,求元素值的平方和再开方。分子是两个向量的点积,相同位置的元素值相乘再求和。
这个公式的物理意义在于计算两个向量的夹角余弦值。相似度为1时,对应角度为0°,如胶似漆;相似度为0时,对应角度为90°,毫不相干,互为“路人甲”。
看上去计算量很大,貌似每一个求和的复杂度都和向量维度,即用户数量是一样的。但是别忘了,前面说过它们都是稀疏向量,也就是向量中绝大多数值都是0,求和时不用算,求点积时更不用算,只计算两个物品的公共用户即可,只是少许几个乘积而已。
关于这个算法,物品之间的相似度计算有很多可以改进之处。通常有以下两个改进方向。
上面提到的相似度计算方法不只适用于评分矩阵,也适用于行为矩阵。所谓行为矩阵,即矩阵元素为0或者1的布尔值,也就是隐式反馈。隐式反馈取值特殊,有一些基于物品的改进推荐算法无法应用,比如著名的Slope One算法,稍后会讲到。
实际上,基于物品的协同过滤算法和基于用户的协同过滤算法在计算相似度这一步是一模一样的,区别就是一个计算行向量的相似度,另一个计算列向量的相似度,只需要将用户行为矩阵转置一下即可。
在得到物品相似度之后,接下来就是为用户推荐他可能会感兴趣的物品,基于物品的协同过滤算法有两种应用场景。
第一种属于Top K 推荐,常常表现为类似“猜你喜欢”这样的形式。触发方式是当用户访问首页时,汇总和用户已经消费过的物品相似的物品,按照汇总后分数从高到低推出。汇总的公式是这样的:
这个公式的核心思想和基于用户的协同过滤算法一样,用相似度加权汇总。要预测一个用户u 对一个物品i 的评分数,就要遍历用户u 评分过的所有物品。假如一共有m 个物品,用每一个物品和待计算物品i的相似度乘以用户的评分,加权求和后除以所有这些相似度的总和,就得到了一个加权平均评分,作为用户u 对物品i的分数预测。
和基于物品的协同过滤算法一样,我们在计算时不必对所有物品都计算一遍,只需要按照用户评过分的物品,逐一取出和它们相似的物品就可以了。
这个过程离线完成后,去掉那些用户已经消费过的物品,保留分数最高的K 个结果进行存储。当用户访问首页时,直接展示出来即可。
第二种属于相关推荐,也就是本文开篇时提到的场景。这类推荐不需要提前合并计算,当用户访问一个物品的详情页面时,或者完成一个物品消费的结果页面时,可以直接获取这个物品的相似物品推荐,也就是“看了又看”或者“买了又买”这样的推荐结果。
对于经典的基于物品的协同过滤算法,相似度矩阵计算无法实时更新,整个过程都是离线完成的,而且还有另一个问题,计算相似度时没有考虑相似度的置信问题。例如,两个物品都被同一个用户喜欢,且仅仅被这一个用户喜欢,那么余弦相似度计算的结果是1,这个1明显不可信,但在最后汇总计算推荐分数时,却对结果的影响很大。
Slope One算法针对这些问题做了改进。Slope One算法专门针对评分矩阵,不适用于行为矩阵。Slope One算法计算的不是物品之间的相似度,而是物品之间的距离,即相似度的反面。举个例子就一目了然了。下表是一个简单的评分矩阵。
用户 | 物品A | 物品B | 物品C |
---|---|---|---|
用户1 | 5 | 没有评分 | 2 |
用户2 | 没有评分 | 4 | 3 |
用户3 | 3 | 3 | 5 |
这个矩阵反映了这些事实:用户1给物品A、C评分,分别是5、2;用户2给物品B、C评分,分别是4、3;用户3给物品A、B、C评分,分别是3、3、5。现在,先来两两计算物品之间的平均距离,如下表所示。
—— | 物品A | 物品B | 物品C |
---|---|---|---|
物品A | 0 | 0(1) | -0.5(2) |
物品B | 0(1) | 0 | -0.5(2) |
物品C | 0.5(2) | 0.5(2) | 0 |
根据计算方法,以物品B和物品C为例:
在距离矩阵表中,括号里的数字表示两个物品的共同用户数量,代表两个物品平均距离的置信程度。比如物品A和物品B之间的平均距离是0,共同评分用户数是1,知道这个平均距离后,就可以用一个已评分物品的评分去预测另一个物品的评分。
用这个距离矩阵去预测那些还没有被用户评分的物品会被用户评多少分,方式就是根据用户已经评分的物品,以及物品之间的评分距离来推算,公式如下:
这个公式中包含以下两个部分。
举个例子:如果只知道用户2给物品B的评分是4,物品B和物品A之间的平均距离是0,因此根据这一个物品可以预测用户2给物品A的评分也是4。类似根据物品C来预测用户2给物品A的评分为3.5。再按照共同评分用户数求加权平均后,用户2可能会给物品A的评分为:
小结
本文在基于用户的协同过滤算法基础上介绍了一个比较常见的算法——基于物品的协同过滤算法。这个算法常常在电商网站上见到,“买了又买”“看了又看”这样的相关推荐,都是由这个推荐算法产生的。
最后我们介绍了一个改良版的基于物品的协同过滤算法——Slope One算法。这个算法的核心思想是计算物品之间的评分距离,再采用共同评分用户数加权来得到结果。
内容简介:本书是一本关于推荐系统产品如何落地的综合图书,内容覆盖产品、算法、工程、团队和个人成长。书中不仅梳理了从事推荐系统工作需要具备的思维模式和需要了解的问题类型,还从产品和商业角度分析了当前*火爆的信息流内在逻辑。本书用非常通俗易懂的方式介绍了推荐系统的经典算法原理,并有相应的配套实践代码,以帮助初入门的算法工程师快速上手。除了推荐算法,书中还包含一些不属于推荐算法但是很常见的实用算法。除算法原理之外,还有典型的工程架构描述,以及架构内部的具体模块细节描述。这些都是在设计推荐系统的过程中不可或缺而又不容易在公开场合获得的内容。此外,本书还涉及一部分推荐系统安全相关的知识,以及团队搭建经验和个人成长心得。本书适合以推荐系统为代表的效果类产品从业者阅读,包括决策者,以及产品、算法、架构、安全、运营人员。这是一本可以架起不同工种之间友好沟通桥梁的书。
作者简介:陈开江,偶以“刑无刀”的名义“出没江湖”,初于北京理工大学学习自然语言处理,先后任职于新浪微博、车语传媒、贝壳找房等公司,做自然语言处理及推荐系统开发等工作,也曾有两三年与推荐系统有关的创业经验。有译著《机器学习:实用案例解析》,在公众号ResysChina上发表过推荐系统系列文章,在极客时间开设有《推荐系统36式》付费专栏。