mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-19 15:43:44 +08:00
del
This commit is contained in:
73
极客时间专栏/geek/AI技术内参/推荐系统核心技术/058 | 简单推荐模型之一:基于流行度的推荐模型.md
Normal file
73
极客时间专栏/geek/AI技术内参/推荐系统核心技术/058 | 简单推荐模型之一:基于流行度的推荐模型.md
Normal file
@@ -0,0 +1,73 @@
|
||||
<audio id="audio" title="058 | 简单推荐模型之一:基于流行度的推荐模型" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/2a/7c/2aed6b1f1a05cac0c674cc7b787aa37c.mp3"></audio>
|
||||
|
||||
今天,我们正式进入专栏的另一个比较大的模块,那就是**推荐系统**。之前我们详细且全面地介绍了搜索系统的各个组成部分。在接下来的几周时间里,我们一起来看推荐系统的技术要点又有哪些。
|
||||
|
||||
我们还是从简单推荐系统聊起,由易到难,逐步为你讲述一些经典的推荐模型。
|
||||
|
||||
推荐系统目前已经深入到了互联网的各类产品中。不管是到电子商务网站购物,还是到新闻阅读网站获取信息,甚至是在出行的时候希望听到不同的音乐,不同种类的推荐系统都在我们的生活中发挥着举足轻重的作用。
|
||||
|
||||
那么,搭建一个最简单的推荐系统,应该如何入手呢?今天我们就来聊一个最基本的推荐模型:**基于流行度的推荐模型**。
|
||||
|
||||
## 最简单的流行度估计
|
||||
|
||||
什么是基于流行度(Popularity-based)?通俗地说,就是什么内容吸引用户,就给用户推荐什么内容。
|
||||
|
||||
这里面其实有一个隐含的假设,那就是物品本身的质量好坏和流行度有一定的正比关系。什么意思呢?就是说好的东西,关注的人自然就多,自然就会有更多的谈论。当然,这是一个主观的假设,并不是所有质量高的物品都会有很高的流行度。然而,在不需要过多其他信息和假设的情况下,流行度可以算是衡量物品质量好坏的一个最简单的测度。
|
||||
|
||||
那么,如果我们能够在每一个时间点上准确地估计到一个物品的流行度,就只需要按照流行度的数值从高到低排序显示所有的物品就可以了。
|
||||
|
||||
然而,这里牵涉到一个问题,那就是如何判断一个物品在任何时间点上的流行度呢?有两个重要的因素影响着物品流行度的估计,那就是**时间和位置**。
|
||||
|
||||
我们先来说一下时间因素。很显然,用户访问每一个应用或者服务都有一定的规律,这种规律导致每一个应用的**流量规律**也不一样。比如,人们可能更倾向于在早上或者傍晚打开新闻网站,看一看一天都发生了什么事情。因此,任何文章投放到这两个时段自然就会有比较高的关注度。这并不代表这些文章就要好于其他的文章,可能仅仅是由于时间的关系。因此,我们在对流行度建模的时候就需要考虑时间的因素。
|
||||
|
||||
另外一个重要的因素是位置。这个“位置”并不是真正的地理位置,而是在一个服务或者网站的什么位置显示你的物品。因为用户心理对于不同位置的感受,在很多类型的服务中常常都有隐含的“**位置偏差**”(Position Bias)。
|
||||
|
||||
这些偏差给我们估计某个物品的流行度带来了很大的困难。比如说,在绝大多数的搜索引擎服务中,排名第一的物品所受到的关注度很可能大大高于排名第二和之后的物品。因此,一个物品只要放到第一的位置,关注度自然就会升高。当然,这并不能完全代表这个物品本身的属性。
|
||||
|
||||
因此,我们在估计物品的流行度时就需要考虑上面所说的这两个重要因素。
|
||||
|
||||
要解决刚才说的两个问题,我们就**不能使用绝对数值来对流行度建模**。比如我们使用在单位时间内点击的数目,购买的数目,或者点赞的数目,都会受到刚才所说的两种偏差的影响。假设一篇文章在9点到10点这个时段被点击了100次,在10点到11点这个时段被点击了50次,这并不能代表这个文章在10点到11点这个时段就变得不受欢迎了,很可能是这个时段的总的用户量比较多。
|
||||
|
||||
因此,**对于流行度的衡量,我们往往使用的是一个“比值”(Ratio),或者是计算某种“可能性”(Probability)**。也就是说,我们计算在总的用户数是N的情况下,点击了某个文章的人数。这个比值,取决于不同的含义,如果是点击,往往叫作点击率;如果是购买,叫作购买率。为了方便讨论,我们在下面的例子中都使用点击率。
|
||||
|
||||
然而,点击率本身虽然解决了一部分时间和位置偏差所带来的影响,但是点击率的估计所需要的数据依然会受到偏差的影响。因此,我们往往希望能够建立无偏差的数据。
|
||||
|
||||
关于如何能够无偏差地估计,这是一个研究课题,我们今天不详细展开。不过,有一种比较经济的方法可以收集没有偏差的数据,那就是把服务的流量分成两个部分。
|
||||
|
||||
一个部分,利用现在已有的对物品流行度的估计来显示推荐结果。另外一个部分,则随机显示物品。这种方法是一种特殊的**EE算法**(Exploitation & Exploration),叫“**epsilon贪心**”(epsilon-Greedy)。
|
||||
|
||||
我们之后还会聊到这个话题。根据这样的方式搜集的数据可以认为是没有位置偏差的。我们从随机显示物品的这部分流量中去估计流行度,然后在另外一个部分的流量里去显示物品。
|
||||
|
||||
如果从数学上对点击率建模,其实可以把一个物品在显示之后是否被点击看成是一个“**伯努利随机变量**”,于是对点击率的估计,就变成了对一个伯努利分布参数估计的过程。
|
||||
|
||||
有一种参数估计的方法叫作“**最大似然估计法**”(Maximum Likelihood Estimation)。简而言之,就是说,希望找到参数的取值可以最大限度地解释当前的数据。我们利用最大似然法就可以求出在某一段时间内的点击率所代表的伯努利分布的参数估计。这个估计的数值就是某个物品当前的点击总数除以被显示的次数。通俗地讲,如果我们显示某个物品10次,被点击了5次,那么在最大似然估计的情况下,点击率的估计值就是0.5。
|
||||
|
||||
很显然,这样的估计有一定的局限性。如果我们并没有显示当前的物品,那么,最大似然估计的分母就是0;如果当前的物品没有被点击过,那么分子就是0。在这两种情况下,最大似然估计都无法真正体现出物品的流行度。
|
||||
|
||||
## 高级流行度估计
|
||||
|
||||
我们从统计学的角度来讲了讲,如何利用最大似然估计法来对一个伯努利分布所代表的点击率的参数进行估计。
|
||||
|
||||
这里面的第一个问题就是刚才我们提到的分子或者分母为0的情况。显然,这种情况下并不能很好地反应这些物品的真实属性。
|
||||
|
||||
**一种解决方案是对分子和分母设置“先验信息”**。就是说,虽然我们现在没有显示这个物品或者这个物品没有被点击,但是,我们“主观”地认为,比如说在显示100次的情况下,会有60次的点击。注意,这些显示次数和点击次数都还没有发生。在这样的先验概率的影响下,点击率的估计,或者说得更加精确一些,点击率的后验概率分布的均值,就成为了实际的点击加上先验的点击,除以实际的显示次数加上先验的显示次数。你可以看到,在有先验分布的情况下,这个比值永远不可能为0。当然,这也就避免了我们之前所说的用最大似然估计所带来的问题。
|
||||
|
||||
**利用先验信息来“平滑”(Smooth)概率的估计,是贝叶斯统计(Bayesian Statistics)中经常使用的方法**。如果用更加精准的数学语言来表述这个过程,我们其实是为这个伯努利分布加上了一个Beta分布的先验概率,并且推导出了后验概率也是一个Beta分布。这个Beta分布参数的均值,就是我们刚才所说的均值。
|
||||
|
||||
在实际操作中,并不是所有的分布都能够找到这样方便的先验分布,使得后验概率有一个解析解的形式。我们在这里就不展开讨论了。
|
||||
|
||||
**另外一个可以扩展的地方就是,到目前为止,我们对于流行度的估计都是针对某一个特定的时段**。很明显,每个时段的估计和前面的时间是有一定关联的。这也就提醒我们是不是可以用之前的点击信息,来更加准确地估计现在这个时段的点击率。
|
||||
|
||||
答案是可以的。当然,这里会有不同的方法。
|
||||
|
||||
一种最简单的方法还是利用我们刚才所说的先验概率的思想。那就是,当前T时刻的点击和显示的先验数值是T-1时刻的某种变换。什么意思呢?比如早上9点到10点,某个物品有40次点击,100次显示。那么10点到11点,我们在还没有显示的情况下,就可以认为这个物品会有20次点击,50次显示。注意,我们把9点到10点的真实数据乘以0.5用于10点到11点的先验数据,这种做法是一种主观的做法。而且是否乘以0.5还是其他数值需要取决于测试。但是这种思想,有时候叫作“**时间折扣**”(Temporal Discount),是一种非常普遍的时序信息处理的手法。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了基于流行度的推荐系统的基本原理。一起来回顾下要点:第一,我们简要介绍了为什么需要基于流行度进行推荐;第二,我们详细介绍了如何对流行度进行估计以及从统计角度看其含义;第三,我们简要地提及了一些更加高级的流行度估计的方法。
|
||||
|
||||
最后,给你留一个思考题,我们介绍了如何使用先验信息来对参数进行平滑,如何能够更加准确地确定先验概率中的数字呢?具体到我们的例子就是,如何来设置先验的点击和显示次数呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
75
极客时间专栏/geek/AI技术内参/推荐系统核心技术/059 | 简单推荐模型之二:基于相似信息的推荐模型.md
Normal file
75
极客时间专栏/geek/AI技术内参/推荐系统核心技术/059 | 简单推荐模型之二:基于相似信息的推荐模型.md
Normal file
@@ -0,0 +1,75 @@
|
||||
<audio id="audio" title="059 | 简单推荐模型之二:基于相似信息的推荐模型" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/5f/14/5f5a98dfda24b8bd9647cae47dce3f14.mp3"></audio>
|
||||
|
||||
这周我们开始讲推荐系统。周一的文章中,我们聊了一个最基本的推荐模型:基于流行度的推荐模型。这是一种简单且实用的推荐系统搭建方式,那就是需要对每一个物品的流行度进行估计。
|
||||
|
||||
今天,我们来看另外一种简单但很有效果的推荐模型:**基于相似信息的推荐模型**。
|
||||
|
||||
## 什么是相似信息的推荐模型
|
||||
|
||||
相似信息的推荐模型又叫**“临近”(Neighborhood)模型**。顾名思义,就是我们希望利用临近、或者相似的数据点来为用户推荐。
|
||||
|
||||
临近模型的内在假设是推荐系统中著名的“**协同过滤**”(Collaborative Filtering)。什么意思呢?就是说,我们认为,**相似的用户可能会有相似的喜好,相似的物品可能会被相似的人所偏好**。于是,如果我们能够定义怎么寻找相似的用户或者相似的物品,那么我们就可以利用这些类别的人群或者物品来给用户进行推荐。
|
||||
|
||||
例如,对于一个电影推荐的场景来说,有一个用户A观看了电影《战狼2》,我们希望根据这个信息来为用户进行推荐。很显然,如果我们仅仅知道用户A观看过《战狼2》,这个信息是非常有限的。但是,假设有一个用户B也观看过《战狼2》,并且最近还观看过《红海行动》。那么, 我们可以根据B的信息来对A进行推荐,也就是说,我们认为用户A也有可能喜欢《红海行动》。
|
||||
|
||||
这里面,我们其实经历了这么两个步骤。
|
||||
|
||||
第一,联系用户A和用户B的是他们都看过《战狼2》。这就帮助我们定义了A和B是相似用户。
|
||||
|
||||
第二,我们的假定是,相似的用户有相似的观影偏好,于是我们就直接把B的另外一个观看过的电影《红海行动》拿来推荐给了A。
|
||||
|
||||
这两个步骤其实就很好地解释了“协同过滤”中“协同”的概念,意思就是相似的用户互相协同,互相过滤信息。
|
||||
|
||||
**“协同过滤”从统计模型的意义上来讲,其实就是“借用数据”,在数据稀缺的情况下帮助建模**。掌握这个思路是非常重要的建模手段。
|
||||
|
||||
在用户A数据不足的情况下,我们挖掘到可以借鉴用户B的数据。因此,我们其实是把用户A和用户B“聚类”到了一起,认为他们代表了一个类型的用户。当我们把对单个用户的建模抽象上升到某一个类型的用户的时候,这就把更多的数据放到了一起。
|
||||
|
||||
## 基于相似用户的协同过滤
|
||||
|
||||
刚才我们简单聊了聊什么是基于相似信息的推荐系统。相信到现在,你已经对这个概念有了一个最基本的认识。
|
||||
|
||||
那么,如何才能够比较系统地定义这样的流程呢?
|
||||
|
||||
首先,问题被抽象为我们需要估计用户I针对一个没有“触碰过”(这里指点击、购买、或者评分等行为)的物品J的偏好。
|
||||
|
||||
第一步,我们需要构建一个用户集合,这个用户集合得满足两个标准:第一,这些用户需要已经触碰过物品J,这是与用户I的一大区别;第二,这些用户在其他的行为方面需要与用户I类似。
|
||||
|
||||
现在我们假设这个集合已经构造好了。那么,接下来的一个步骤,就是根据这个相似的用户集,我们可以对物品J进行一个打分。这个打分的逻辑是这样的。首先,我们已经得到了所有和I相似的用户对J的打分。那么,一种办法就是,直接用这些打分的平均值来预估J的评分。也就是说,如果我们认为这个相似集合都是和用户I相似的用户,那么他们对J的偏好,我们就认为是I的偏好。显然这是一个很粗糙的做法。
|
||||
|
||||
我们可以针对这个直接平均的做法进行两个改动。
|
||||
|
||||
第一,采用加权平均的做法。也就是说,和用户I越相似的用户,我们越倚重这些人对J的偏好。
|
||||
|
||||
第二,我们也需要对整个评分进行一个修正。虽然这个相似集合的人都对J进行过触碰,但是每个人的喜好毕竟还是不一样的。比如有的用户可能习惯性地会对很多物品有很强的偏好。因此,仅仅是借鉴每个人的偏好,而忽略了这些用户的偏差,这显然是不够的。所以,我们需要对这些评分做这样的修正,那就是减去这些相似用户对所有东西的平均打分,也就是说,我们需要把这些用户本人的偏差给去除掉。
|
||||
|
||||
综合刚才说的两个因素,可以得到一个更加合适的打分算法,那就是,用户I对物品J的打分来自两个部分:一部分是I的平均打分,另外一部分是I对于J的一个在平均打分之上的补充打分。这个补充打分来自于刚才我们建立的相似用户集,是这个相似用户集里每个用户对于J的补充打分的一个加权平均。权重依赖于这个用户和I的相似度。每个用户对于J的补充打分是他们对于J的直接打分减去他们自己的平均打分。
|
||||
|
||||
## 相似信息的构建
|
||||
|
||||
我们刚才讲了一下相似用户协同过滤的一个基本思路。那么,这里面有几个要素需要确定。
|
||||
|
||||
**第一,我们怎么来定义两个用户是相似的?**一种最简单的办法,就是计算两个用户对于他们都偏好物品的“**皮尔森相关度**”(Pearson Correlation)。这里当然可以换做是其他相关信息的计算。
|
||||
|
||||
具体来说,皮尔森相关度是针对每一个“两个用户”都同时偏好过的物品,看他们的偏好是否相似,这里的相似是用乘积的形式出现的。当两个偏好的值都比较大的时候,乘积也就比较大;而只有其中一个比较大的时候,乘积就会比较小。然后,皮尔森相关度对所有的乘积结果进行“加和”并且“归一化”。
|
||||
|
||||
**第二,当有了用户之间的相关度信息后,我们可以设定一些“阈值”来筛选刚才所说的相关用户集合**。对于每个目标用户,我们可以设置最多达到前K个相似用户(比如K等于100或者200),这也是有效构造相似集合的办法。
|
||||
|
||||
**最后,我们来谈一下刚才所说的加权平均里面的权重问题**。一种权重,就是直接使用两个用户的相似度,也就是我们刚计算的皮尔森相关度。当然,这里有一个问题,如果直接使用,我们可能会过分“相信”有一些相关度高但自身数据也不多的用户。什么意思呢?比如有一个用户M,可能和目标用户I很相似,但是M自己可能也就偏好过一两件物品,因此我们可能还需要对相关度进行一个“**重新加权**”(Re-Weighting)的过程。具体来说,我们可以把皮尔森相关度乘以一个系数,这个系数是根据自身的偏好数量来定的。
|
||||
|
||||
## 基于相似物品的协同过滤
|
||||
|
||||
在协同过滤的历史上,人们很快就意识到在进行构建推荐的过程中,用户和物品的“对称性”。什么意思?也就是说,我们刚才对于用户的讨论其实完全可以变换到物品中。
|
||||
|
||||
具体说来,那就是我们不去构造和用户I相似的用户,而是去构造所有和物品J相似的物品。这些相似物品集合必须要满足两点:第一,和J相似;第二,已经被用户I触碰了。这里的一个基本的假设类似于,虽然我不知道用户I对于《红海行动》的偏好,但我可以去看一看用户过去看的电影里有哪些和《红海行动》是类似的,我们就可以从那些类似的电影中进行加权平均,取得对《红海行动》的预测。
|
||||
|
||||
## 小结
|
||||
|
||||
今天,我为你讲了推荐系统的另外一个基本的形式:基于相似度的协同过滤推荐系统。
|
||||
|
||||
一起来回顾下要点:第一,我们简要介绍了整个基于相似度协同过滤的内涵以及我们这么做的基本假设;第二,我们详细介绍了如何构造一个基于用户相似度的协同过滤系统;第三,我们简要地提及了如何构造物品相似的协同过滤系统。
|
||||
|
||||
最后,给你留一个思考题,协同过滤的一个致命问题是什么?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
77
极客时间专栏/geek/AI技术内参/推荐系统核心技术/060 | 简单推荐模型之三:基于内容信息的推荐模型.md
Normal file
77
极客时间专栏/geek/AI技术内参/推荐系统核心技术/060 | 简单推荐模型之三:基于内容信息的推荐模型.md
Normal file
@@ -0,0 +1,77 @@
|
||||
<audio id="audio" title="060 | 简单推荐模型之三:基于内容信息的推荐模型" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/bf/e6/bf64f78caf37ec68cf2385b27049e9e6.mp3"></audio>
|
||||
|
||||
周一的文章中,我们聊了一个最基本的基于流行度的推荐模型。周三我们讨论了基于相似信息的推荐模型。基于相似信息的推荐模型,其核心就是协同过滤的思想,希望能够通过相似的用户或者相似的物品来对当前的场景进行推荐。
|
||||
|
||||
然而,不管是基于流行度的推荐,还是协同过滤,这些方法都有一些根本的问题。比如,对于基于流行度预测的推荐来说,推荐结果不是个性化的。因为流行度预测是一种全局的预测,每个人得到的推荐结果是一样的。而协同过滤的问题是强烈依赖相似用户以及相似物品的定义,而且对于新用户或者新物品来说有数据稀缺的问题。因此,在实际应用中,往往不能在整个系统中单独使用协同过滤。
|
||||
|
||||
今天,我们来分享一个更加普遍的方法,那就是**基于内容信息的推荐系统**。这种系统在实践中往往更能适应各种不同的推荐场景。
|
||||
|
||||
## 什么是基于内容信息的推荐系统
|
||||
|
||||
所谓基于内容信息的推荐系统,其实就是**用特征(Feature)来表示用户、物品以及用户和物品的交互,从而能够把推荐问题转换成为监督学习任务**。
|
||||
|
||||
把推荐系统完全定义为监督学习任务,需要有这么几个步骤。
|
||||
|
||||
第一,就是我们已经提到的,需要把所有用户、物品的各种信号用特征来表示。这里面往往牵涉非常复杂和繁琐的**特征工程**,也就是看如何能够把不同的信息通过特征表达出来。
|
||||
|
||||
第二,就是每一个监督任务都需要面临的问题,如何构造一个**目标函数**,来描述当前的场景。可以说,这是最难的一个部分,也是和基于流行度和基于相似度的推荐系统的最大区别。
|
||||
|
||||
## 内容信息的各类特性
|
||||
|
||||
那么,对于物品特性来说,有哪些是比较重要的呢?这里我们肯定没法提供一个完备的列表,那我就来谈一些主要的特性,起到一个抛砖引玉的作用。
|
||||
|
||||
第一,**物品的文本信息**。比如商品的名字和描述。这些文字信息可以使用很多文本挖掘(Text Mining)的方式来组成有效的特征。
|
||||
|
||||
我们在讲搜索模块的时候,其实就已经提到了一些,比如用TF-IDF的方法来形成文本向量。当然,因为文本信息的噪声相对比较大,并且数据维度也比较大(维度等于文本所对应语言的词汇量),很多时候我们都寻求降低这部分数据的维度,降低到一个固定的维度。这种时候,很多所谓“降维”的工具就很有必要了。
|
||||
|
||||
传统上,有用“**话题模型**”(Topic Model)对文本进行降维的。也就是说,我们针对每一个文字描述都可以学习到一个话题的分布,这个分布向量可能是50维、100维等等,但是肯定要比原始的词汇向量要小。
|
||||
|
||||
近些年,很多人又开始使用各种“**词嵌入向量**”(Word Embedding)的方法来为文字信息降维,从而能够使用一个固定的维度来表达文字信息。
|
||||
|
||||
第二,**物品的类别信息(或者物品的知识信息)**。对于新闻文章来说,类别信息是新闻的话题类别,像娱乐新闻、财经新闻或者时政新闻等。而对于商品来说,类别信息是商品的品类,像电器、床上用品或者生活用品等。这些类别信息往往能够非常有效地抓住物品的整体属性。通常情况下,这样的属性比直接使用文字信息更加直接。
|
||||
|
||||
如何能够得到这样的类别信息呢?在有些情况下,这些类别信息是在数据输入的时候获取的。比如通过合作渠道取得新闻文章的时候,类别往往是编辑加上去的。再比如,商品的类别很多时候也是卖家在输入商品的时候加上去的。
|
||||
|
||||
当然,也有一些情况,这些类别信息并不是直接获得的;或者是在数据中有很多缺失的情况下,就需要利用机器学习的手段,来构造分类器以获取这些类别信息。我们在这里就不展开讨论这些分类器该如何构建了。
|
||||
|
||||
最后需要说明的一点是,除了最基本的类别信息,最近一段时间比较火热的研发领域,就是**利用知识图谱(Knowledge Graph)来对物品的各种信息进行深入挖掘**。很多信息是通过知识图谱推断出来的。
|
||||
|
||||
举个例子,某一篇新闻文章是关于美国总统特朗普的,于是这篇文章可能就会自动被打上美国总统、美国政治等其他标签。这种通过一些原始的信息来进一步推断更加丰富的知识信息,也是重要的物品类别特征的处理工作。
|
||||
|
||||
最后需要提及的是图像或者其他多媒体的信息。在信息如此丰富的今天,很多物品都有多样的表现形式,比如比较常见的图像、视频等。
|
||||
|
||||
那么,如何从这些媒介中提取信息也是非常关键的物品特征工程。和文字信息正好相反,很多多媒体的信息都是稠密(Dense)的向量,因此需要对这些向量进行特殊处理,比如我们首先学习一个分类器,然后再和其他特征的不同分类器组合。
|
||||
|
||||
前面我们简单谈了谈物品的特征,下面我们再来看看用户的特征。
|
||||
|
||||
对于用户来说,最基础、最首要的肯定是用户的基本特性,包括性别、年龄、地理位置。这三大信息其实可以涵盖用户特性工程中非常大的一块内容。
|
||||
|
||||
这里不仅是最基本的这三个特性的值,还有围绕这三个特性发展出来的三大种类的特性。比如,不同性别在文章点击率上的差异,不同年龄层在商品购买上的差异,不同地理位置对不同影视作品的喜好等,这些都是根据这三个特性发展出来的更多的特性。
|
||||
|
||||
然后,我们可以为用户进行画像(Profiling)。有显式的用户画像,比如用户自己定义的喜好,或者用户自己认为不愿意看到的物品或者类别。
|
||||
|
||||
但是在大多数情况下,用户都不会为我们提供那么精准的回馈信息,甚至完全不会有任何直接的反馈。在这样的情况下,绝大多数的用户画像工作,其实是通过用户的“隐反馈”(Implicit Feedback),来对用户的喜好进行建模。关于如何进行用户画像,我们今天就不在这里展开了。
|
||||
|
||||
## 目标函数
|
||||
|
||||
讨论了物品和用户特征的一些基本情况后,我们再来简单聊聊另外一个话题,那就是**目标函数**。我们前面提到,整个基于内容信息的推荐系统就是把所有的信号都当做特征,然后构建一个监督学习任务。
|
||||
|
||||
监督学习的一个关键的就是目标函数。对于一个推荐系统来说,都有什么样的目标函数呢?
|
||||
|
||||
和纯粹的基于评分(Rating)的协同过滤推荐系统一样,我们可以设置监督学习的目标函数是**拟合评分**。当然,已经有很多学者指出评分并不是推荐系统的真正目标。
|
||||
|
||||
那么,在实际系统中比较常见的目标函数有点击率和购买率,也有一些相对比较复杂的目标函数,比如预测用户在某一个物品上的停留时长。
|
||||
|
||||
对于究竟在哪种场景中使用什么样的目标函数,这依然是当前的一个主要研究方向。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了基于内容信息的推荐系统。通俗地说,就是如何把推荐系统当做监督学习任务来看待。
|
||||
|
||||
一起来回顾下要点:第一,我们简要介绍了整个基于内容推荐的内涵以及我们这么做的基本假设;第二,我们详细介绍了如何构造一个基于内容的推荐系统,特别是如何构造物品和用户的特征;第三,我们简要地介绍了目标函数的重要性。
|
||||
|
||||
最后,给你留一个思考题,如何把我们前面介绍的两种推荐系统模式,也就是基于流行度和协同过滤,也融进基于内容的推荐系统中去呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
69
极客时间专栏/geek/AI技术内参/推荐系统核心技术/061 | 基于隐变量的模型之一:矩阵分解.md
Normal file
69
极客时间专栏/geek/AI技术内参/推荐系统核心技术/061 | 基于隐变量的模型之一:矩阵分解.md
Normal file
@@ -0,0 +1,69 @@
|
||||
<audio id="audio" title="061 | 基于隐变量的模型之一:矩阵分解" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e9/a5/e97afb9a1783511297ea4b67d708fca5.mp3"></audio>
|
||||
|
||||
上周我们聊了三个简单的推荐模型,分别是基于流行度的推荐模型,基于相似信息的推荐模型和基于内容特征的推荐模型。
|
||||
|
||||
这周,我们来看一类非常重要的推荐模型:**基于隐变量的推荐模型**。这类模型的优势是对用户和物品信息中的隐含结构进行建模,从而能够挖掘更加深层次的用户和物品关系。
|
||||
|
||||
## 什么是隐变量
|
||||
|
||||
在解释如何用隐变量来生成推荐结果之前,我们先来说一下什么是隐变量。
|
||||
|
||||
**隐变量**(Latent Variable),顾名思义,就是“隐藏的变量”或者叫“隐藏的参数”,这里主要是指我们假定实际的数据是由一系列的隐含变量产生的。我们通过模型的假设,知道隐变量之间的关系,但暂时并不知道隐变量的取值。因此需要通过“推断”(Inference)过程来确定隐变量的实际取值。当我们知道了这些隐变量的取值之后,就可以根据这些取值来对未来的数据进行预测和分析。
|
||||
|
||||
隐变量往往还带有“统计分布”(Distribution)的假设。什么意思呢?就是隐变量之间,或者隐变量和显式变量之间的关系,我们往往认为是由某种分布产生的。
|
||||
|
||||
举一个最简单的隐变量模型的例子,那就是“**高斯混合模型**”(Mixture of Gaussian)。
|
||||
|
||||
高斯混合模型假设数据是由多个不同的高斯分布产生的,每一个高斯分布有自己的均值和方差。在最简单的两个高斯的情况下,每一个数据点,都有可能是由这两个高斯分布中的一个产生的,但是,究竟是哪一个我们并不知道。于是,对于每一个数据点,我们就有一个隐含的变量,来表达当前这个数据点究竟来自哪一个高斯分布。
|
||||
|
||||
很明显,这个隐含变量的取值事先并不知道。除了这个隐含变量我们不知道以外,两个高斯分布的均值和方法其实也不知道。于是,对于高斯混合模型来说,整个学习的过程就需要估计每个数据点的来源以及多个高斯分布的均值和方差。**高斯混合模型,几乎是最简单的隐变量模型,但也给我们了展示了使用隐变量模型对数据建模的灵活性以及训练的复杂性**。
|
||||
|
||||
## 矩阵分解作为隐变量模型
|
||||
|
||||
了解了隐变量模型的基本的概念以后,我们还是回到推荐的场景。
|
||||
|
||||
在推荐系统中,有一种最普遍的数据表达,那就是用户和物品的交互,比如评分、点击等等。这里我们用评分作为一般性的讨论。对于每一个用户,如果我们用一个向量来表达其对所有可能物品的评分,那么把所有用户的向量堆积起来,就可以得到一个矩阵。这个矩阵的每一行代表一个用户,每一列代表一个物品,每一个交叉的元素代表某一个用户对于某一个商品的评分。
|
||||
|
||||
那么这个矩阵有什么特点呢?最大的特点就是,这个矩阵的数据其实非常稀少。因为在一个现实的系统中,一个用户不可能对所有的物品都进行评分。实际上,一个用户仅仅对非常少的物品进行过评分,而对绝大多数物品并不会评分,甚至连评分的打算都没有。因此,这个矩阵的绝大多数元素其实是0。当然,实际上这些元素也不是0,而是未知,因为用户并不是觉得这些物品的评分是0,而是压根没有对这些物品进行打分,也就是说评分信息不完备。
|
||||
|
||||
对于这样一个矩阵,我们的任务其实就是根据有评分的用户物品交互,对那些还没有评分信息的物品进行预测。如果我们能够“补全”(Complete)整个矩阵里的其他元素,那么就可以根据预测的评分从大到小给用户进行推荐。
|
||||
|
||||
怎么来补全这个矩阵的信息呢?
|
||||
|
||||
这里,我们假设,矩阵的每一个元素都是经过这样一个过程产生的。
|
||||
|
||||
首先,我们假设每一个用户和每一个物品都对应一个隐向量(Latent Factor)。比如,我们用100维的向量来表达一个用户,用另外一个100维的向量来表达一个物品。如果我们有1百万个用户和1万个物品,那么我们就需要1百万个100维的用户向量,和1万个100维的物品向量。
|
||||
|
||||
然后,我们假设矩阵的每一个元素是由所对应的用户和物品的隐向量点积得到的。也就是说,矩阵里的每一个元素,都是一个100维的用户向量和一个100维的物品向量对应元素相乘相加而得。
|
||||
|
||||
在这样的一个假设下,一个原本1百万乘以1万的矩阵就可以被分解为1百万乘以100的用户矩阵和100乘以1万的物品矩阵的乘积。这也就是为什么在这样的模型下,我们会称这个方法为“**矩阵分解**”(Matrix Factorization)的原因。
|
||||
|
||||
在矩阵分解这个假设下,我们可以看到,原本是需要对整个矩阵,也就是1百万乘以1万个数据进行建模,而现在缩减到了两个小一些的矩阵1百万乘以100和100乘以1万。对比来看,之前对于每一个用户,我们需要一万个元素来表达用户对于这一万个物品的评分喜好;现在,对每个用于仅仅需要保存100个元素。
|
||||
|
||||
只不过,这一百个元素的数值并不代表任何意义。从这个层面上理解矩阵分解,也就能够帮助我们知道,这个方法其实是一种“**降维**”(Dimension Reduction),也就是把一个比较大的矩阵分解成两个小矩阵来表达。
|
||||
|
||||
我们可以看到,矩阵分解的核心其实就是刚才的假设,用隐向量来表达用户和物品,他们的乘积关系就成为了原始的元素。不同的假设可以得到不同的矩阵分解模型。
|
||||
|
||||
## 学习矩阵分解模型
|
||||
|
||||
很明显,矩阵分解仅仅告诉了我们这个模型的表达,但并没有告诉我们怎么去获得整个模型的最核心内容,那就是用户矩阵和物品矩阵里每一个元素的数值。也就是我们所说的,用户隐向量和物品隐向量都是事先不知道的。
|
||||
|
||||
那有什么办法能够得到这些向量的取值呢?
|
||||
|
||||
这里介绍一种常用的方法,就是利用**最小二乘法**的原理(Least Square)来拟合求解这些隐向量。
|
||||
|
||||
前面讲到,矩阵里的每一个元素来自于两个隐向量的点积,我们就可以利用这一点来构造一个目标函数。这个目标函数其实就是说,这两个隐向量的点积一定要与我们观测到的矩阵数值相近。这里的“相近”是用这两个数值的误差,在这里也就是**平方差**(Square Error)来衡量的。误差越小,说明数据拟合得越好,隐向量也就更能表达用户和物品。
|
||||
|
||||
构造好了这个目标函数以后,我们就可以利用**优化算法**来求解这个目标函数。因为两个未知数点积的原因,这个目标函数没有一个全局的最优解,但是我们可以通过“**梯度下降**”(Gradient Descent)的方法找到一个不错的局部解(Local Minima)。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了推荐系统的一个重要分支,隐变量模型。我们讲了其中最重要的一个基本模型,矩阵分解。
|
||||
|
||||
一起来回顾下要点:第一,我们简要介绍了隐变量模型的基本原理;第二,我们详细介绍了矩阵分解作为隐变量模型的假设和原理;第三,我们简要地讨论了如何求解矩阵分解里的隐变量。
|
||||
|
||||
最后,给你留一个思考题,矩阵分解模型最大的问题是什么?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
57
极客时间专栏/geek/AI技术内参/推荐系统核心技术/062 | 基于隐变量的模型之二:基于回归的矩阵分解.md
Normal file
57
极客时间专栏/geek/AI技术内参/推荐系统核心技术/062 | 基于隐变量的模型之二:基于回归的矩阵分解.md
Normal file
@@ -0,0 +1,57 @@
|
||||
<audio id="audio" title="062 | 基于隐变量的模型之二:基于回归的矩阵分解" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f4/b5/f4457d173a7a8f0713663d04c9643bb5.mp3"></audio>
|
||||
|
||||
本周我们主要来分享“矩阵分解”的点点滴滴,这是过去10年里推荐系统中最流行的一类模型。周一我们讨论了这类方法中最基础的基于隐变量的矩阵分解。这类模型的优势是显式地对用户和物品信息中的隐含结构进行建模,从而能够挖掘更加深层次的用户和物品关系。矩阵分解的流行起源于10年前的Netflix大赛,当时各类矩阵分解模型都在实际数据中起到了很好的效果。
|
||||
|
||||
今天我们要分享的模型,叫作“**基于回归的隐变量模型**”(Regression-based Latent Factor Model)。这是在基本矩阵分解的基础上衍生出来的一类模型。
|
||||
|
||||
## 基本矩阵分解的问题
|
||||
|
||||
我们先来看看基本矩阵分解模型的潜在问题。
|
||||
|
||||
首先,我们来回顾一下矩阵分解的基本表达。假设我们在对用户和物品的评分进行建模。对于每一个用户,用一个向量来表达其对于所有可能物品的评分,把所有用户的向量堆积起来,就可以得到一个矩阵。这个矩阵的每一行代表一个用户,每一列代表一个物品,每一个交叉的元素代表某一个用户对于某一个商品的评分。对于每一个用户和物品的隐向量都要少于原有的物品数目,因此,我们也说矩阵分解的模型实现了“降维”(降低建模维度)的目的。
|
||||
|
||||
虽然矩阵分解的模型对于挖掘用户和物品的内在联系有比较强的作用,但是这类模型的劣势也十分明显。
|
||||
|
||||
**第一,矩阵分解的矩阵仅仅是对用户和物品的喜好进行了“编码”**(Encode)。我们之前在解释基于内容的推荐系统时说过,对于一个复杂的工业级推荐系统来说,有很多灵感或者直觉,都很难仅仅依赖用户和物品的喜好来捕捉到。有大量的信号,无法很好地被融合到这个矩阵分解的模式里。因此,矩阵分解虽然是不错的“独立”模型(Standalone),但在融合多种不同的推荐元素方面,表现却很一般。
|
||||
|
||||
**第二,矩阵分解的核心是学习用户的隐向量和物品的隐向量**。原则上,这两类隐向量的学习仅能通过训练过程获得。
|
||||
|
||||
什么意思呢?就是说,如果在训练集合中有100个用户,200个物品,那么通过训练,我们可以学习到这100个用户和200个物品对应的隐向量,用于以后的预测或者排序。但我们无法获得新来用户或者新来物品的隐向量了,因为这些用户和物品并不在训练集里。
|
||||
|
||||
在推荐系统中,这种情况就叫作不能处理“冷启动”(Cold Start)问题,也就是不能处理“冷”用户和“冷”物品。这个特点是好是坏取决于具体的应用。但是,在有些应用的场景下,这是灾难性的一种特性。比如,新闻网站推荐文章,一般来说新闻文章滚动得都很快,随时随地都可能有新文章涌入,每过几天,整个网站的文章可能都被换掉,在这样的场景下,直接使用矩阵分解就会有问题。
|
||||
|
||||
矩阵分解的基本模型存在这两个问题,那有没有什么办法可以扩展矩阵分解的形式,改善在这两种情况下的处理呢?
|
||||
|
||||
## 基于回归的矩阵分解
|
||||
|
||||
基于回归的矩阵分解,其核心思路其实非常简单直观。矩阵分解不过是定义了一种从用户隐变量和物品隐变量到可以观测到的评分,这一显变量的产生过程。如果我们掌握了这么一个思路,那么,基于回归的矩阵分解就很容易理解了。
|
||||
|
||||
**首先,有一组用户特性和物品特性来表述每一个用户和物品**。这些特性不是隐变量,是显式表达的特性。用户特性比如用户的年龄、性别、经常出现的地区、已经表达了喜好的类别等;物品特性比如物品的种类、描述等等。这两组显式的特性就是为了解决我们刚才说的第一个问题,矩阵分解无法抓住更多的信号。而在这里,我们明确定义这两组信号,一组来自于用户,一组来自于物品,希望能够通过这些信号抓住更多有价值的信息。
|
||||
|
||||
解决了这一步后,现在我们有两个独立的,看上去不相关的部分。一个是基于矩阵分解的部分,这一部分是分解一个已知的评分矩阵,从而学习到用户和物品的隐向量。另外一个部分,就是用户特性和物品特性,暂时还不知道如何与矩阵分解关联上。
|
||||
|
||||
基于回归的矩阵分解假定,用户的隐向量,其实是从用户的显式特性变换而来的。同理,物品的隐向量,其实是从物品的显式特性变换而来的。而这两种变换,本质上就是两个回归模型(Regression Model)。就是说,**我们建立一个从显式特性到隐向量的回归模型,使得隐向量受到两方面的制约:从评分矩阵的分解得来的信息和从显式特性回归得来的信息**。这样,我们就把这两部分信息嫁接到了一起。
|
||||
|
||||
**把这两部分信息嫁接到一起的好处就是,我们不再怕“冷启动”了**。或者说,在有一部分“冷启动”的情况下,这样的模型可以处理得更好。原因就是我们使用了显示特性来回归隐向量。对于新用户和新物品而言,我们虽然没有直接得到他们的隐向量,但是有这些用户或者物品的显式特性,而这些显式特性可以帮助我们估计到新用户和新物品的隐向量,即使我们并没有它们的交互信息。这就是基于回归的矩阵分解的强大之处。
|
||||
|
||||
**我们还可以从贝叶斯的角度来理解基于回归的矩阵分解**。把用户的隐向量和物品的隐向量看作是两个随机变量。我们可以认为这些随机变量加上了先验概率分布。只不过,这个先验概率分布的均值不是我们经常使用的0,而是一个以回归函数的结果为均值的高斯分布,这个回归函数就是我们由显式特性得到的。本质上,我们认为显示特性的某种变换成为了隐向量的先验信息。
|
||||
|
||||
## 学习基于回归的矩阵分解
|
||||
|
||||
基于回归的矩阵分解,其实就相当于我们定义了“**层次的贝叶斯模型**”(Hierarchical Bayesian Model)。模型的求解就变得更加复杂。
|
||||
|
||||
有一种学习这个模型的简单思路。第一,针对已知的用户和物品,先通过简单的矩阵分解学习到用户和物品的隐变量。在这个部分里,用户的显式信息并不参与学习。第二,学习好了这部分变量以后,再来学习从显式信息到隐变量的回归部分。这部分基本上可以当作线性回归。当然,用这种两个阶段的学习流程,并不能保证学习到的参数是最优的,这仅仅是一种简化的学习方法。
|
||||
|
||||
如果走比较正统的学习过程,这样的模型需要采用“**期望最大化**”(Expectation Maximization)的流程。也就是说,我们先用一组随机的参数来决定回归的部分,学习到最佳的隐向量,然后再根据隐向量更新回归部分的参数。因篇幅的原因我们就不展开细节了。不过,即便如此,我们也仅仅能够学习到一个局部解。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了隐变量模型中基于回归的矩阵分解。
|
||||
|
||||
一起来回顾下要点:第一,我们简要介绍了矩阵分解的一些问题;第二,我们详细介绍了基于回归的矩阵分解的基本思路,以及这样的模型如何解决了传统矩阵分解关于“冷启动”的难题;第三,我们简要地讲解了如何求解基于回归的矩阵分解里的参数。
|
||||
|
||||
最后,给你留一个思考题,基于回归的矩阵分解的短板是什么?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
61
极客时间专栏/geek/AI技术内参/推荐系统核心技术/063 | 基于隐变量的模型之三:分解机.md
Normal file
61
极客时间专栏/geek/AI技术内参/推荐系统核心技术/063 | 基于隐变量的模型之三:分解机.md
Normal file
@@ -0,0 +1,61 @@
|
||||
<audio id="audio" title="063 | 基于隐变量的模型之三:分解机" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d3/20/d3fcdf64984f62fddd245a515fc97120.mp3"></audio>
|
||||
|
||||
周三我们分享了“基于回归的隐变量模型”,这是在基本的矩阵分解基础上衍生出来的一类模型。这种模型把显式特性和隐变量结合起来,对解决“冷启动”问题有一定作用。
|
||||
|
||||
今天,我们来介绍一种叫作“**分解机**”(Factorization Machines)的推荐技术。这个模型是从基于回归的隐变量模型中衍生出来的,已成为了主流的推荐模型。
|
||||
|
||||
## 矩阵分解和基于回归的隐变量模型存在哪些问题?
|
||||
|
||||
在介绍分解机的基本原理之前,我们先来回顾一下从“矩阵分解”到“基于回归的隐变量模型”的一个发展脉络。
|
||||
|
||||
首先,矩阵分解主要解决了两个问题,那就是从一个大矩阵降维到两个小矩阵,并且寄希望这两个小矩阵能够抓住用户和物品的相关度。
|
||||
|
||||
然而,单纯的矩阵分解无法融入很多用户和物品的特性,这就引导我们开发出了基于回归的矩阵分解。所谓的回归部分,也就是从显式特性出发,建立从显式特性到隐变量之间关系的流程,从而使我们能够把更多的信号放进模型中。
|
||||
|
||||
在一定程度上,基于回归的隐变量模型实现了把显式变量和隐变量结合的目的,但是这类模型的学习过程非常麻烦。实际上,因为这类模型复杂的训练流程,其在实际应用中并不常见。
|
||||
|
||||
那么,有没有其他思路来统一显式变量和隐变量的处理方式呢?
|
||||
|
||||
## 分解机的基本原理
|
||||
|
||||
分解机[1]是学者斯特芬·润顿(Steffen Rendle)在德国康斯坦扎大学任教期间开发出来的推荐模型。斯特芬后来加入谷歌,分解机是他的代表作品。
|
||||
|
||||
分解机结合了“基于内容的推荐系统”和“基于回归的隐变量模型”的一些基本思想。
|
||||
|
||||
基于内容的推荐系统,其核心就是认为需要预测的变量(这里我们依然讨论评分)是所有显式变量的一个回归结果。分解机直接借鉴了这一点,也就是说,分解机的输入是所有的显式变量。
|
||||
|
||||
实际上,分解机在对待显式变量的手法上更进了一步,那就是不仅直接对显式变量进行建模,还对显示变量的两两关系进行建模。当然,在原始的论文中,分解机其实还可以对更加高维的关系进行建模,我们这里局限在两两关系上。
|
||||
|
||||
什么意思呢?比如说我们有一个用户特性,是用户的年龄;我们有一个物品特性,是物品的种类。那么,普通的回归模型,就是把用户的年龄和物品的种类直接当作特性输入到模型中。而对于分解机来说,这只是第一步。
|
||||
|
||||
**第二步,分解机是把这两个特性的数值进行乘积,当作一个新的特性,然后进一步处理这种两两配对的关系**。把原始特性进行两两配对是构建模型的一种重要的方法,特别是对于非深度学习模型,需要自己做特征工程的模型。
|
||||
|
||||
两两配对的特征有什么好处呢?好处就是可以对两种特性的交互信息进行建模。举个例子,如果我们特别在意某个年龄段的用户在某种商品类别中的评分,那么,把这两个特性相乘,从而抓取到这个交互信息,是一个非常有效的手段。
|
||||
|
||||
但是,两两配对存在什么问题吗?一个问题就是**特性空间会急速增长**。如果我们有一个100维的用户特性向量,然后有一个100维的物品特性向量,那对于两两配对的特征,就是100乘100这个数量级的。另一个更严重的问题就是,如果我们的单独特性中,有一些是“类别特性”(Categorical Feature),那么在两两配对之后就会产生大量的0,从而变成一个巨大的稀疏矩阵。
|
||||
|
||||
如何解决这个问题呢?**分解机利用了矩阵分解的降维思路**。就是说,我们不对一个稀疏矩阵直接建模,而是把这个稀疏矩阵分解之后再进行建模。具体到上面这个例子,就是先假定,所有特性都对应一个隐变量向量,两个显式特性的乘积是两个特性的隐变量的点积。也就是说,我们把两个显式特性的乘积分解为了两个向量的乘积。这样,我们就不需要直接表示原来的稀疏矩阵。
|
||||
|
||||
在这样的思路下,分解机成功地把隐变量和显式变量结合到了一起。当我们的显式特性仅仅是用户ID和物品ID的时候,分解机的表达退回了最原始的矩阵分解。也就是说,矩阵分解其实可以表达成为特性的两两作用矩阵的分解。
|
||||
|
||||
在原始的论文中,作者还用分解机模拟了好几种流行的模型,我们这里就不复述了。
|
||||
|
||||
虽然也是为了建立从显式特性到隐变量的关系,但是对比基于回归的矩阵分解而言,分解机的训练过程大大简化了。在实际应用中,我们经常使用“**随机梯度下降**”(SGD, Stochastic Gradient Descent)来对分解机直接进行求解。
|
||||
|
||||
在最近几年的Kaggle比赛中以及一些工业级的应用中,分解机凭借其简单易用的特点,成为了很多产品的核心算法。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了隐变量模型中分解机的基本原理。
|
||||
|
||||
一起来回顾下要点:第一,我们简要介绍了矩阵分解的一些问题;第二,我们详细介绍了分解机的基本原理;第三,我们简要讲了如何求解分解机。
|
||||
|
||||
最后,给你留一个思考题,分解机能够解决“冷启动”的问题吗?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
**参考文献**
|
||||
|
||||
1. Steffen Rendle. Factorization Machines with libFM. ACM Trans. Intell. Syst. Technol. 3, 3, Article 57 (May 2012), 22 pages, 2012.
|
||||
|
||||
|
||||
79
极客时间专栏/geek/AI技术内参/推荐系统核心技术/064 | 高级推荐模型之一:张量分解模型.md
Normal file
79
极客时间专栏/geek/AI技术内参/推荐系统核心技术/064 | 高级推荐模型之一:张量分解模型.md
Normal file
@@ -0,0 +1,79 @@
|
||||
<audio id="audio" title="064 | 高级推荐模型之一:张量分解模型" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/1f/72/1f752c5dfc8749c80e2eab2e1f657c72.mp3"></audio>
|
||||
|
||||
上周我们分享了推荐系统中矩阵分解的点点滴滴,简单复习一下讨论过的三个模型。
|
||||
|
||||
第一,“基于隐变量的矩阵分解”,其优势是显式地对用户和物品信息中的隐含结构进行建模,从而能够挖掘更加深层次的用户和物品关系。
|
||||
|
||||
第二,“基于回归的隐变量模型”,这是在基本的矩阵分解基础上衍生出来的一类模型。这种基于回归的矩阵分解模型把显式特性和隐变量结合起来,对解决“冷启动”问题有一定作用。
|
||||
|
||||
第三,“分解机”是由基于回归的隐变量模型衍生出来的,并且吸纳了基于信息的推荐系统的一些观点,成为了一种可以融合多种信息的强有力的工具。
|
||||
|
||||
这周,我们跟随着这个脚步,进一步来讨论一些比较高级的模型,看这些模型如何抓住更多的用户和物品之间的关系。
|
||||
|
||||
今天,我们先来聊一种叫作“**张量分解**”(Tensor Factorization)的模型。
|
||||
|
||||
## 为什么需要张量分解
|
||||
|
||||
在我们探讨张量分解的一些基本思想之前,先来看一看,推荐系统在什么场景下需要张量分解。
|
||||
|
||||
我们还是要从矩阵分解说起。矩阵分解的核心思想,是用矩阵这种数据结构来表达用户和物品的相互关系。这里,我们一般谈论的都是一些最简单的关系,例如评分、点击、购买等(本文我们依然只是讨论评分)。在这种二元的模式下,矩阵就是最好的表达用户和物品之间关系的数据结构。
|
||||
|
||||
然而,在真实的场景中,用户和物品的关系以及产生这种关系的周围环境是复杂的。一个矩阵并不能完全描述所有的变量。例如,用户对于某个物品的评分是发生在某个地点、某个时间段内的。这种所谓的“上下文关系”(Context)往往会对评分产生很大影响。遗憾的是,一个矩阵无法捕捉这样的上下文关系。
|
||||
|
||||
我们之前讨论过的“基于回归的矩阵分解”和“分解机”,本质上都是在某种程度上绕开这个问题。采用的方法就是,依然用矩阵来表达二元关系,但是把其他信息放进隐变量中,或者是采用基于信息的推荐系统的思路来得到相关信息的建模。
|
||||
|
||||
除了这种思路,还有没有别的方法,可以把上下文关系融入到对用户和物品的建模中去呢?
|
||||
|
||||
这时“张量”就该上场了。
|
||||
|
||||
从本质上来说,**张量就是矩阵的推广**。我们可以这么理解,**矩阵是对二维关系建模的一种工具;而张量,就是对N维关系的一种建模**。在二维关系中,用户和物品的评分是唯一能够被建模的变量;而到了N维关系中,理论上,我们可以对任意多种上下文关系进行建模。
|
||||
|
||||
比如,我们刚才提到的时间,就可以组成一个三维的张量,分别为用户、物品和时间。然后,在这个三维的张量中,每一个单元代表着某一个用户对于某一个物品在某一个时间段的评分。
|
||||
|
||||
## 基于张量分解的推荐模型
|
||||
|
||||
我们已经讲了张量的作用。那么,如何使用张量来进行推荐模型的建模呢?
|
||||
|
||||
我们还是用刚才所说的“用户、物品和时间”作为例子。在这个三维的张量里,每一个元素代表的是用户对于物品在某个时间段上的评分。那么,根据矩阵分解的思路,我们怎么来对这个张量进行分解呢?
|
||||
|
||||
遗憾的是,张量的分解要比矩阵分解更为复杂。与矩阵分解不同,张量分解至少有两种不同的形式,这两种形式会引导出不同的分解模型和算法。
|
||||
|
||||
**第一种分解模式叫 CP分解**(CANDECOMP/PARAFAC)。
|
||||
|
||||
拿我们刚才所说的三维张量来讲,CP分解是把一个三维张量分解为三个矩阵。具体来说,比如我们的三维张量是N维用户乘以M维的物品乘以R维的时间段。那么,分解出来的三个矩阵就分别为N维乘以K维的用户矩阵,M维乘以K维的物品矩阵,以及R维乘以K维的时间矩阵。这三个矩阵中的每一个向量都代表某一个用户、某一个物品和某一个时间段。K在这里是一个参数,类似于矩阵分解中的隐变量的维度,我们也就可以把这个K理解成为隐变量的维度。
|
||||
|
||||
那么在原始的三维张量中,某一个元素就是这三个矩阵的某三个向量对应元素乘积相加的结果。CP分解的一大好处就是,分解出来的三个矩阵的隐变量维度是一样的,这也就减少了需要调整的参数的个数。
|
||||
|
||||
**第二种分解模式叫作 HOSVD分解**(High Order Singular Value decomposition)。
|
||||
|
||||
这种分解和CP分解最大的不同就是分解出来的三个矩阵的维度不再一样。也就是说,在我们之前的例子中,用户矩阵的维度可以是N乘以A,物品矩阵的维度是M乘以B,时间段矩阵的维度是R乘以C。当然,这样就无法还原之前的N乘以M乘以R的三维张量了。
|
||||
|
||||
于是在技术上,还需要乘以一个A乘以B乘以C的小张量才能对原始数据进行复原。所以,通俗地讲,HOSVD分解就是把一个三维的张量,分解成为三个矩阵和一个更小的张量的乘积。
|
||||
|
||||
那HOSVD相比CP分解有什么好处呢?好处自然就是给不同的数据以不同的自由度,因为不再限制用户、物品和时间段都必须有一样的维度。但同时也带来了难点,那就是有了更多的“超参数”需要调整。
|
||||
|
||||
值得一提的是,我们仅仅是讲了讲张量分解的一个基本思路。在实际的运作中,还有一个重要的步骤,那就是**设计目标函数**,或者说是**定义损失函数**。在一般的分解过程中,我们可以定义“**平方差**”(Squared Loss),也就是原始数值和预测数值之间的平方差来作为损失函数,当然也可以使用其他的损失函数,这一点和矩阵分解是一样的。
|
||||
|
||||
## 求解张量分解
|
||||
|
||||
虽然张量是对矩阵的自然延伸,张量分解是矩阵分解的某种延伸,但是求解张量分解则是一个相对比较难的问题。
|
||||
|
||||
一种比较简单的模式依然是使用“**随机梯度下降**”法(SGD, Stochastic Gradient Descent),也就是把张量的分解问题看作是一个一般的优化问题。关于这种方法的细节我在这里不详细讲解了,感兴趣的话,建议阅读参考文献[1],这是一篇很经典的论文,是第一次把张量分解使用在推荐系统中。
|
||||
|
||||
另外一种方法,也是在矩阵分解中可以使用的,叫作 **ALS**(Alternating Least Square)方法。这种方法则是在优化每一轮的时候,按住所有其他的矩阵变量不动,单独优化一个变量。举例来说,如果我们要优化用户矩阵,那么我们就按住物品矩阵和时间段矩阵不动,不去更新里面的参数,而仅仅更新用户矩阵里面的参数。同理,在下一轮的优化中,可以仅仅更新物品矩阵里的参数。这种方法也是行之有效的一种优化方法。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了推荐系统的一个高级模型:张量分解。张量分解模型主要用来对上下文的信息进行建模。
|
||||
|
||||
一起来回顾下要点:第一,我们简要介绍了为什么需要张量分解;第二,我们详细介绍了张量分解的基本原理;第三,我们简要地讨论了如果求解张量分解。
|
||||
|
||||
最后,给你留一个思考题,从概念上来看,用张量分解对上下文信息进行建模的最大问题是什么?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
**参考文献**
|
||||
|
||||
1. Alexandros Karatzoglou, Xavier Amatriain, Linas Baltrunas, and Nuria Oliver. [Multiverse recommendation: n-dimensional tensor factorization for context-aware collaborative filtering](https://xamat.github.io/pubs/karatzoglu-recsys-2010.pdf). Proceedings of the fourth ACM conference on Recommender systems (RecSys '10). ACM, New York, NY, USA, 79-86, 2010.
|
||||
|
||||
|
||||
73
极客时间专栏/geek/AI技术内参/推荐系统核心技术/065 | 高级推荐模型之二:协同矩阵分解.md
Normal file
73
极客时间专栏/geek/AI技术内参/推荐系统核心技术/065 | 高级推荐模型之二:协同矩阵分解.md
Normal file
@@ -0,0 +1,73 @@
|
||||
<audio id="audio" title="065 | 高级推荐模型之二:协同矩阵分解" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b2/a1/b2070dd3af5c7450b50db496b92237a1.mp3"></audio>
|
||||
|
||||
周一我们讨论了“张量分解”模型。这种模型的特点是能够把不同的上下文当作新的维度,放进一个张量中进行建模。虽然张量分解是矩阵分解在概念上的一种直觉扩展,但其在现实建模的过程中有很大难度,最大的问题就是张量分解的求解过程相对比较复杂,不同的分解方法又带来不同的建模选择。
|
||||
|
||||
今天,我们来看另外一种思路,来解决融合多种渠道信息的问题,这就是**协同矩阵分解**(Collective Matrix Factorization)。
|
||||
|
||||
## 为什么需要协同矩阵分解
|
||||
|
||||
在解释什么是协同矩阵分解之前,我们先来看一看为什么需要这样一种思路。我们还是需要回到矩阵分解本身。
|
||||
|
||||
矩阵分解的核心就是通过矩阵,这个二维的数据结构,来对用户和物品的交互信息进行建模。因为其二维的属性,矩阵往往只能对用户的某一种交互信息直接进行建模,这就带来很大的局限性。
|
||||
|
||||
在之前的讨论中,我们看到了一系列不同的思路来对这样的基本结构进行扩展。
|
||||
|
||||
**思路一**,就是通过建立显式变量和隐变量之间的回归关系,从而让矩阵分解的核心结构可以获得更多信息的帮助。
|
||||
|
||||
**思路二**,则是采用分解机这样的集大成模型,从而把所有的特性,都融入到一个统一的模型中去。
|
||||
|
||||
**思路三**,就是我们这周已经讲到的,利用张量,把二维的信息扩展到N维进行建模。
|
||||
|
||||
这些已有的思路都各有利弊,需要针对具体的情况来分析究竟什么样的模型最有效果。
|
||||
|
||||
然而在有一些应用中,除了用户和物品这样很明显的二元关系以外,还有其他也很明显的二元关系,如何把这些二元关系有效地组织起来,就变成了一个有挑战的任务。
|
||||
|
||||
什么意思呢?比如,我们是一个社交媒体的网站,既有用户对于物品(比如帖子)的交互信息,又有用户之间的互相连接信息(谁与谁是好友等)。那么,如何来显式地表达这两类不同的二元关系呢?
|
||||
|
||||
在前面的思路里面可以看到,我们似乎需要选择一个主要的关系来作为这个模型的基础框架,然后把其他的信息作为补充。在这样两类关系中,选择哪一个作为主要关系,哪一个作为补充关系,就显得有一点困难了。
|
||||
|
||||
更进一步说,对于用户与用户之间的建模,以及用户与物品之间的建模,我们其实会有不同的模型去构造。例如,用户与物品之间的评分,往往用整数来代表评分的数值,或者是用实数来代表喜好度。而用户与用户之间的友好关系,则往往是0或者1,象征是否有连接。因此,我们可能需要不同的模型对这些不同的数值进行建模。
|
||||
|
||||
这也就让研究人员想出了协同矩阵分解的思路。
|
||||
|
||||
## 协同矩阵分解的基本思路
|
||||
|
||||
协同矩阵分解的基本思路其实非常直观,那就是**有多少种二元关系,就用多少个矩阵分解去建模这些关系**。
|
||||
|
||||
用我们刚才所说的社交媒体的例子。如果我们有用户与用户的关系,用户与物品的关系,那我们就组织两个矩阵分解,分别来对这两种关系进行建模。最早对这个思想进行得比较完整的表述,我在文末列出了参考文献[1]。
|
||||
|
||||
这里的一个核心就是,如果两个没有关系的矩阵,各自做矩阵分解,那么分解出来的信息,一般来说,是没有任何关联的。
|
||||
|
||||
再来看刚才的例子,如果有一个用户与用户的矩阵需要分解,然后有一个用户与物品的矩阵需要分解。那从这两个矩阵分解中,我们分别可以得到至少两组不同的**用户隐变量**。一组是从用户与用户的关系而来,一组是从用户与物品的关系而来。这两组用户的隐变量是不一样的。同时,因为两个矩阵没有关联,所以无法达到我们希望这两种关系互相影响的效果。
|
||||
|
||||
要想在两个矩阵分解之间建立联系,我们必须有其他的**假设**。这里的其他假设就是,两组不同的用户隐变量其实是一样的。也就是说,我们假设,或者认定,**用户隐变量在用户与用户的关系中,以及在用户与物品的关系中,是同一组用户隐变量在起作用**。
|
||||
|
||||
这样,虽然表面上还是两个矩阵分解,但其实我们限定了其中某一部分参数的取值范围。说得直白一些,我们认定从两个矩阵分解出来的两组来自同一个因素(这里是用户)的隐变量是完全一样的。用更加学术的语言来说,这就是**将两组矩阵分别投影到了相同的用户空间和物品空间**。
|
||||
|
||||
这样做的好处,自然就是对于多种不同的关系来说,我们使用“**相同隐变量**”这样的假设,可以把这些关系都串联起来,然后减少了总的变量数目,同时也让各种关系互相影响。
|
||||
|
||||
那么,这样的假设有没有潜在的问题呢?
|
||||
|
||||
一个比较大的潜在问题就是,使用同样的一组隐变量去表达所有的同类关系,这样的假设存在一定的局限性。比如上面的例子,用同样一组用户隐变量去解释用户和用户之间的关系,同时也需要去解释用户和物品之间的关系,能够找到这样一组用户隐变量其实是有一定难度的。
|
||||
|
||||
而在实际应用中,不同关系的数据量会有很大的差距。比如,用户和物品关系的数据总量可能要比用户与用户的多。所以,由于用户和物品关系的数据多,两个矩阵分解用的同一组用户隐变量,很可能会更多地解释用户和物品的部分,从而造成了学到的隐变量未必能够真正表达所有的关系。
|
||||
|
||||
对于这样的情况,自然已经有一些学者想到了对策,我们今天就不在这里展开了。
|
||||
|
||||
最后,需要提一下,在协同矩阵分解的场景中,学习各个隐变量的参数的过程,和一般的单个矩阵分解相比,没有太多本质性的变化。最简单的学习过程,依然是利用**随机梯度下降法**(SGD, Stochastic Gradient Descent)去学习。只不过,每一个隐变量会存在于多个矩阵分解中,这在更新变量时增加了所需的计算量。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了推荐系统的另一个高级模型,协同矩阵分解,用来对不同类型的二元信息进行建模。
|
||||
|
||||
一起来回顾下要点:第一,我们简要介绍了为什么需要协同矩阵分解;第二,我们详细介绍了协同矩阵分解的原理、潜在问题和解法。
|
||||
|
||||
最后,给你留一个思考题,从概念上来看,协同矩阵分解和张量分解之间有怎样的关系?是不是所有的张量分解都可以化为多个协同矩阵分解呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
**参考文献**
|
||||
|
||||
1. Ajit P. Singh and Geoffrey J. Gordon. [Relational learning via collective matrix factorization](http://www.cs.cmu.edu/~ggordon/singh-gordon-kdd-factorization.pdf). Proceedings of the 14th ACM SIGKDD international conference on Knowledge discovery and data mining (KDD '08). ACM, New York, NY, USA, 650-658, 2008.
|
||||
|
||||
|
||||
67
极客时间专栏/geek/AI技术内参/推荐系统核心技术/066 | 高级推荐模型之三:优化复杂目标函数.md
Normal file
67
极客时间专栏/geek/AI技术内参/推荐系统核心技术/066 | 高级推荐模型之三:优化复杂目标函数.md
Normal file
@@ -0,0 +1,67 @@
|
||||
<audio id="audio" title="066 | 高级推荐模型之三:优化复杂目标函数" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/cb/0a/cbd82303c866d9cea8024adff69fae0a.mp3"></audio>
|
||||
|
||||
周三我们讨论了协同矩阵分解,其主要思想就是解决多个两两关系的矩阵分解,并且希望能够建立隐变量之间的共享。
|
||||
|
||||
今天,我们来看一个稍微不一样的话题,那就是**如何优化更加复杂的目标函数**。
|
||||
|
||||
## 为什么需要复杂的目标函数
|
||||
|
||||
在介绍更复杂的目标函数之前,我们首先来回想一下,在之前的分享中,都接触到了哪些目标函数。
|
||||
|
||||
对于基于流行度或者相似度的推荐系统来说,其实并没有真正的目标函数的概念。这些推荐模型都是某种直观的“翻译”,这也导致了这些推荐系统很难直接使用在真实的应用中,往往是被当作特性用在其他模型中。
|
||||
|
||||
基于信息的推荐系统,本质上就是监督学习在推荐系统中的应用。因为是监督学习,那自然就需要目标函数。这里,经常是对点击率或者购买率进行建模,也就是说,经常使用**二分分类的目标函数**。
|
||||
|
||||
当我们使用矩阵分解的架构来对用户和物品的关系进行建模时,绝大多数情况下我们是在讨论**评分**。对于评分信息,常用的其实是**线性回归**(Linear Regression),也有学者使用**泊松回归**,因为泊松回归对于整数变量的建模要好于线性回归。当然了,矩阵分解也可以扩展到对点击率或者购买率的建模。
|
||||
|
||||
当年Netflix竞赛之后,Netflix公司把获奖的矩阵分解拿来进行实现,放入线上系统中,结果发现并没有本质性地提高推荐效果,这其实就和目标函数有关。虽然Netflix竞赛造就了矩阵分解等类似模型的流行,但是逐渐地,研究人员和工业界从业人员也意识到,**用户对物品的评分,并不是推荐系统需要优化的目标,也就是说目标函数“选错了”**。
|
||||
|
||||
那么,我们需要什么样的目标函数呢?
|
||||
|
||||
## 高级目标函数
|
||||
|
||||
直接对评分进行建模的最大问题,就是这和真实的推荐场景并不相符。不管是电商平台,还是新闻系统,我们并不是只在意用户对于某一些物品的评分。
|
||||
|
||||
真实的应用场景往往是这样的,用户打开应用,然后浏览一系列物品,由上往下进行翻阅,然后从中找到喜欢的物品。
|
||||
|
||||
这是不是很像我们在讨论搜索的时候,用户对于搜索结果的浏览?回忆一下,在搜索的场景中,我们首先输入关键字,然后搜索算法会返回一系列的结果。大多数情况下,我们会对返回的结果逐一检查。
|
||||
|
||||
在推荐场景下,我们虽然没有搜索关键词,但是整个从上往下的场景是类似的。
|
||||
|
||||
于是,我们就可以从搜索排序中得到启发,尝试对推荐结果进行排序。换句话说,我们并不在意用户的真实评分,或者我们是否能对用户和物品的喜好度进行完美估计,我们在意的是,**能否把用户可能喜欢的物品排到前面去**。
|
||||
|
||||
**把搜索系统中的排序思想利用到推荐系统中,是推荐系统的一个重大进步,这也让推荐系统和真实场景逐渐挂钩。**
|
||||
|
||||
那么,很直观的,要想更改推荐系统的行为,从评分的预测到排序学习,我们需要更改目标函数。
|
||||
|
||||
参考文献[1]中提出了一种叫**BPR**的方法,是把**配对法**引入到推荐系统中的一个重要工作。我们快速回忆一下已经在搜索系统中介绍过的“配对排序学习”。简单说来,配对法就是希望,对于某一个查询关键词来说,学习到每一对文档之间的关系,然后通过把所有的两两关系都预测正确,从而建立一个完整的排序结果。
|
||||
|
||||
很明显,在推荐系统的场景下,没有查询关键词,但是我们依然可以通过构造“**会话**”(Session)来学习排序。
|
||||
|
||||
简单来说,我们针对用户来到应用后产生的会话,对用户交互过的物品进行建模训练。我们期望能把有“正交互信息”的物品排到“负交互信息”的物品之前。
|
||||
|
||||
值得注意的是,和搜索不一样,推荐系统往往没有明确的反馈信息。意思就是,在搜索系统中,我们有已知的标签信息,也就是哪一个文档是“相关”的,哪一个是“不相关”的。然而,在推荐系统中我们并没有这样的信息。
|
||||
|
||||
因此,所有用户和物品的交互都是“**隐回馈**”(Implicit Feedback)。我们必须**依靠假设来找到相关的物品**。在这里,我们假定有正交互信息的物品是比其他物品更加相关。于是,正交互的物品的预测值要高。这里的“正交互”可以是点击、购买或者其他信息。这就是BPR的基本思路。
|
||||
|
||||
需要强调的一点是,BPR仅仅是一种思路框架,我们可以应用到矩阵分解中,以及基于信息的推荐系统等不同的模型中。我们可以把矩阵分解中的对于评分的目标函数换成基于BPR的目标函数,也就是进行配对法训练,得到的推荐系统能够更好地对物品进行排序。
|
||||
|
||||
有了这个思路,我们就可以打开一系列的想法了。比如,我们在前面的搜索模块中讲过,其实还可以直接优化类似NDCG、MAP这样的指标。那能不能把这些想法也搬运到推荐系统中去呢?
|
||||
|
||||
简单的回答是,能。但是这个流程也不是那么显然易见的,毕竟我们没有直接的标签信息,而且一般来说,这些目标函数本身就已经很难优化了,我们还要嫁接到矩阵分解或者是分解机等模型上,这就会让优化的难度继续攀升。今天我们就不展开讨论这部分内容了。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了推荐系统的另外一个问题,那就是目标函数。
|
||||
|
||||
一起来回顾下要点:第一,我们分析了为什么要关注目标函数,以评分为基础的目标函数的问题;第二,我们详细介绍了BPR这种非常经典的配对法的目标函数。
|
||||
|
||||
最后,给你留一个思考题,如果我们能够对所有物品的喜好度进行精准预测,是不是就不需要BPR了呢?学习排序和对物品喜好度的预测是完全不同的两件事,还是相互之间有联系呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
**参考文献**
|
||||
|
||||
1. Steffen Rendle, Christoph Freudenthaler, Zeno Gantner, and Lars Schmidt-Thieme. BPR: Bayesian personalized ranking from implicit feedback. Proceedings of the Twenty-Fifth Conference on Uncertainty in Artificial Intelligence (UAI '09). AUAI Press, Arlington, Virginia, United States, 452-461, 2009.
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<audio id="audio" title="067 | 推荐的Exploit和Explore算法之一:EE算法综述" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/9c/7c/9cc947a1e462f800b5ceba270f7ea57c.mp3"></audio>
|
||||
|
||||
上周,我们聊了一些比较高级的模型,包括张量分解和协同矩阵分解,讨论这些模型如何能够抓住更多的用户和物品之间的关系。最后,我们还讨论了如何优化更加复杂的目标函数。
|
||||
|
||||
这周,我们来看一个完全不同的话题,那就是 Exploitation(利用)和 Exploration(探索)的策略,俗称“**EE策略**”。
|
||||
|
||||
一个推荐系统,如果片面优化用户的喜好,很可能导致千篇一律的推荐结果。其实,EE策略是推荐系统里很有意思,但也非常有争议的一个话题。一方面,大家都明白这类算法的目的,每年有很多相关论文发表。但另一方面,工业界对于部署这类算法非常谨慎,有的产品经理甚至视之为“洪水猛兽”。我们今天就来分析一下导致这个现象的一些因素。
|
||||
|
||||
## 走一步看一步的策略
|
||||
|
||||
这里再简单阐述一下什么是EE。简单来说,就是我们在优化某些目标函数的时候,从一个时间维度来看,当信息不足或者决策不确定性(Uncertainty)很大的时候,我们需要平衡两类决策:
|
||||
|
||||
- 选择现在可能是最佳的方案;
|
||||
- 选择现在不确定,但未来可能会有高收益的方案。
|
||||
|
||||
在做这两类决策的过程中,我们也逐渐更新对所有决策不确定性的认识。最终,从时间的维度上来看,我们在不确定性的干扰下,依然能够去优化目标函数。
|
||||
|
||||
也就是说,**EE可以看作是一个优化过程,需要多次迭代才能找到比较好的方案**。
|
||||
|
||||
## EE的应用历史
|
||||
|
||||
早期把EE应用于新闻推荐系统的文章,主要关注在雅虎的今日新闻(Today Module)这一产品上,这也基本上是EE最早在互联网应用的尝试,目的是为了优化点击率(CTR)。而更早的一些奠基性的文章,则是在广告的数据集上展示实验结果。
|
||||
|
||||
雅虎的今日新闻其实为EE提供了一些被很多学者和工业界人士忽视了的条件和成功因素。如果不考虑这些因素,鲁莽地在其他场景中使用这些文献中相似的算法,很可能会产生相当差的效果。那么是哪些因素呢?主要有两点。
|
||||
|
||||
<li>
|
||||
**相对少量的优质资源**。今日新闻每天的内容池(Content Pool)其实并不大。这里面都是网站编辑精选了的大概100篇文章。这些文章原本的质量就非常高,无论是这里面的任何一组,用户体验都没有明显变差。内容池每天都人为更换。
|
||||
</li>
|
||||
<li>
|
||||
**非常大的用户量**。有亿万级的用户,最终可能是从算法随机产生的文章排序中选择了阅读的文章。因为用户数量巨大,所以算法就相对比较容易收敛(Converge)到稳定的方案,也就是前面讲的,优化CTR的状态。
|
||||
</li>
|
||||
|
||||
正因为有了以上两个因素,在这个模块上,工程师和科学家们享受了后来学者们所无法想象的“奢侈”,比如运行Epsilon-Greedy这种简单粗暴的EE算法;甚至是完全随机显示新闻,收集到了大量无偏(Unbiased)的数据,都为很多学术工作奠定了数据基础。时至今日,依然有不少后续学者,在今日新闻随机数据的基础上进行算法改进。
|
||||
|
||||
如果没有了这两条因素,最早的解决方案可能都没法在当时的雅虎施行。原因很简单,如果资源良莠不齐,资源数量非常大,那么在仅有的几个展示位置,优质资源显示的可能性在短期内就会比较小(因为系统对于大多数的资源还有很高的不确定性,需要Explore)。
|
||||
|
||||
由于优质资源显示得少了,用户就会明显感受到体验下降,最直接的可能就是倾向于不点击甚至放弃使用产品。用户不和系统交互这样的行为,又进一步减缓了系统学习资源不确定性的速度。这时,也许亿万级用户数都没法满足学习所有资源的用户数量(毕竟所有用户只有一部分会落入Exploration)。
|
||||
|
||||
关于这个解决方案有一个很有意思的点值得一提,在雅虎的研究人员跳槽到了LinkedIn以后,LinkedIn也推了相似的方案。为了模拟雅虎今日新闻的这些条件,就对用户内容流里的数据进行了大规模的过滤。这样就有少数的信息符合高质量的要求,并且能够在用户数允许的情况下探索到合适的解决方案。
|
||||
|
||||
## EE的产品部署难点
|
||||
|
||||
我们来讲一下EE的产品部署难点,这些难点普遍高于具体的EE算法选择(比如选某一个UCB或者某一个Thompson Sampling)在产品工程解决方案上的抉择。
|
||||
|
||||
为了便于讨论,我们把所有EE算法整体叫作“Random”,简称“**R算法**”,而把不做EE的算法叫作“Deterministic”,简称“**D算法**”。这里面的假设是,D算法比较静态,能够产生高质量、一致性的内容。这里的一致性是指用户在短时间内的体验比较稳定,不会有大幅度的界面和内容变化。相反,整体来说,R算法的不确定性比较大,用户体验和产生的内容可能会有比较大的波动。
|
||||
|
||||
**第一个难点是如何上线测试**。这看上去不应该是难点,但实际上需要格外小心。传统EE文献,只是把问题抽象为每一次访问需要做一个决策的选择。然而,文献却没有说,这些访问是否来自同一个用户。
|
||||
|
||||
那么,理论上,EE应该对所有的访问不加区别,不管其是否来自同一个用户。用我们这篇文章的术语来说,就是所有的流量都做R算法。虽然从理论上讲这样没有问题,但实际上,用户体验会有很大的差别。特别是一些推荐网站,用户希望自己前后两次对网站的访问保持一致性。如果不加区分地做R,对于同一个用户来说,很可能两次看见的内容完全迥异。这对用户熟悉产品界面,寻找喜爱的内容会产生非常大的障碍。
|
||||
|
||||
那么,我们对绝大部分用户做D,对另外一小部分用户做R,这样会好一些吗?这其实就是“牺牲”少部分用户体验,来换取绝大多数用户体验的一致性。这样实现也是最直观的,因为很多在线系统的A/B测试系统是根据用户来进行逻辑分割的。也就是说,某一部分用户会进入一个Bucket,而另一批用户会进入另外一个Bucket。按用户来做D & R可以很容易和Bucket System一致起来,方便部署。当然,这样做也是有潜在风险的。那就是,这部分老做R的用户,在当了别人的小白鼠以后,很可能永远放弃使用产品。
|
||||
|
||||
**另外一个难点就是如何平衡产品**。EE几乎是一定会导致用户对产品的体验下降,至少是在短期内会这样。如何弥补这一点,技术上其实比较困难。比如做过滤是一种思路,那就是只在优质内容里探索。当然,有人会说,这样其实也没有多大的意义。然而,一旦把质量的闸门打开了,那就会对用户体验带来很大的影响。
|
||||
|
||||
这也是很多产品经理对于EE非常谨慎的原因,能不做就不做。而且,牺牲了用户体验后,EE所带来的好处其实是很难评测的,这主要是由线上产品的评测机制和评测原理决定的。目前还没有比较统一的解决方案。
|
||||
|
||||
如何能够做到“用户友好型”的EE呢?这里面可以有两种思路。
|
||||
|
||||
**思路一,不是所有人群的所有访问都适合做R**。和传统EE不同的是,做“**反向EE**”。也就是说,我们只针对常用产品的用户做探索,而并不是针对新用户或者是还没有那么熟悉系统的人群。这个思路和EE完全相反,但是更加人性化。
|
||||
|
||||
**思路二,夹带“私货”**。也就是更改EE的算法,使得高质量的内容和低质量的内容能够相伴产生,并且高质量的内容更有几率排在前面。这样用户体验的损失是可控的。
|
||||
|
||||
其实,EE和产品的结合点应该是工程和研究的重点,但遗憾的是,碍于数据和其他方面的因素,这方面的研究工作几乎没有。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了推荐系统的一个重要的问题,就是如何持续挖掘用户可能的喜好,也就是做EE。
|
||||
|
||||
一起来回顾下要点:第一,我们讲解了什么是EE;第二,我们介绍了EE的一些简要历史;第三,我们讨论了EE的部署难点。
|
||||
|
||||
最后,给你留一个思考题,EE策略是不是一定会导致用户看到多样不同的东西呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<audio id="audio" title="068 | 推荐的Exploit和Explore算法之二:UCB算法" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e2/73/e27338edc5d25951b6eda7419dddc773.mp3"></audio>
|
||||
|
||||
这周,我们来讨论EE策略,周一介绍了EE的综合情况。今天来看一种最基本的思路,叫作 **UCB(Upper Confidence Bound)算法**。
|
||||
|
||||
## EG算法
|
||||
|
||||
在介绍UCB算法之前,我们先来看一种更加简单的EE算法,叫 **EG(Epsilon-Greedy)算法**。
|
||||
|
||||
我们先来回顾一下EE的主要目的。EE的核心思想是说,我们对当前物品的估计往往是有限的、不准确的,需要不断尝试来增强对整个环境的了解,进而能够更加准确地对每个物品进行估计。
|
||||
|
||||
可以说,**EG算法是最简单也是最基本的EE算法**。EG算法的基本思路是这样的:既然我们当前对所有物品的估计是不完整的,那就可以随机地显示所有物品来获取数据。假设我们现在有一千个物品,我们对每个物品都需要估计一个数值,比如点击率。很显然,这个点击率的估计受以下两个因素的影响:已经显示了什么样的物品和显示的次数。那么,要想进一步提高这个估计值的准确度,EG算法认为我们必须对所有物品进行“探索”(Explore)。
|
||||
|
||||
具体来说,**EG算法的流程是这样的:对于所有的物品,在概率P的情况下,按照当前的估计值来显示物品**。回到刚才点击率的例子,那就是在概率P的情况下,谁的点击率高就显示谁。然后在概率1-P的情况下,随机地在所有物品中选择显示对象。如果我们从所有用户的角度来看,也就是说,P%的用户看到的是根据点击率排序的物品,而(1-P)%的用户看到的是随机的物品。
|
||||
|
||||
EG的想法是,虽然在最开始的时候,这种随机性可能会带来用户体验的下降,也就是那(1-P)%的用户会持续看到随机的内容,但是在牺牲这部分用户体验的情况下,随着时间的推移,慢慢地从整体上来看,对所有物品的估计会更加准确,P%的那部分用户的体验会增加。这也就是一种牺牲小部分用户体验来换取大部分用户体验的思路。
|
||||
|
||||
## UCB算法的核心思路
|
||||
|
||||
我们刚才讲了EG算法的基本思路。很显然,**EG有一个很大的问题,那就是有一个固定百分比的用户持续看到的都是随机的内容,这就太过于局限**。
|
||||
|
||||
那么,我们能不能根据对物品的估计,来动态地调整显示物品的可能性呢?
|
||||
|
||||
回到我们刚才说的物品点击率预测的例子。一般来说,我们可以根据每个物品的显示记录来预测点击率。这个数值,其实是一个估计的“均值”。然而,这个估计可能是很不准确的,或者说,估计的置信度不高。
|
||||
|
||||
那么,**如何来衡量一个物品的置信度呢**?在统计中,一个比较好的方法,就是利用“**标准差**”(Standard Deviation)。从感性上来理解,标准差描述了数据的离散程度,也就是说,标准差其实是量化了数据在均值周围的分布情况。标准差小说明我们对这个数值的估计比较有信心,而标准差大则说明了不确定性大。
|
||||
|
||||
有了标准差的思路之后,我们再回到最初的问题,怎样才能动态地调整显示物品的可能性呢?我们沿着这个思路再稍微展开一下。很显然,我们需要考虑物品的当前估计,但同时也需要考虑这个估计的置信度。这个置信度告诉我们是不是需要更多地去“探索”这个物品。那么,很自然地,**我们就可以同时用均值和标准差来表达对一个物品的整体估计**,然后根据这个估计来排序显示物品。因为标准差已经表达了这种不确定因素,因此,我们的结果里面,不确定性特别大的物品,会被显示到前面来。
|
||||
|
||||
具体来说,**UCB采用的数值是均值加上两倍的标准差来作为最终排序的实用数值**。当然,不同类型的UCB算法在最终的数值上会有所偏差,但是大体思路基本相同。在这样的思路下,每一轮计算,我们都根据当前的数据计算出物品点击率的均值和当前的标准差,然后根据UCB的计算,我们再基于物品的数值,也就是刚才提到的均值加上两倍的标准差来排序。
|
||||
|
||||
在这样的一个机制下,经过多轮显示,当某个物品的数据越来越多的时候,标准差也会慢慢减小,最终UCB的数值会收敛到均值上。因此,**这个算法本身其实是同时考虑了物品现在的情况以及在这种情况下的置信度,并且寄希望通过多次迭代来达到减小标准差,提高置信度的目的。**
|
||||
|
||||
## UCB算法的讨论
|
||||
|
||||
UCB的方法一经提出,因为它的简单,并且有数学基础,马上备受学术界的关注。另外从概念上来说,UCB的确要比EG要好。EG有一个固定的群体需要忍受“探索”的不确定性结果;而UCB,这部分“牺牲”消失了。不仅如此,我们之前提到EG中有一个概率P,这个参数在UCB中也完全消失了。这个概率P是一个需要调整的参数,而且没人知道这个参数该怎么设置才是最优的。而在UCB中,每一个物品的“随机度”是不一样的,并没有一个全局的类似P这样的参数。
|
||||
|
||||
那是不是UCB就没有问题了呢?
|
||||
|
||||
**UCB的最大问题在于其对物品打分的机制,也就是均值加上两倍的标准差**。这个机制听上去很合理,但在实际中,比如一些大型网站,会有上百上千甚至几百万的物品,那么,在没有任何特殊处理的情况下,对绝大多数物品的打分数值是相同的。什么意思?比如,很多物品从来没有被显示过,估计的均值就可能是0,或者是一个默认的初始值,在这样的情况下,物品的标准差自然也是一样的。那对于所有这些一样的物品,UCB本身并没有设计任何机制来加以区分。
|
||||
|
||||
这其实说明了一个问题,UCB算法本质上还是“确定性”(Deterministic)算法,也就是说并没有随机性。表面上通过标准差引入的不确定性其实是一种假象,这个算法从根本上还并不能真正做到随机探索。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我们继续讨论推荐系统的一个重要问题,EE策略。我们介绍了一个很重要的算法,UCB算法。
|
||||
|
||||
一起来回顾下要点:第一,我们首先介绍了比UCB算法更加简单的EG算法;第二,我们介绍了UCB的核心思想;第三,我们讨论了UCB存在的一些问题。
|
||||
|
||||
最后,给你留一个思考题,如果有一大堆物品的UCB打分值是一样的,我们该如何解决这个问题呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<audio id="audio" title="069 | 推荐的Exploit和Explore算法之三:汤普森采样算法" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f5/df/f50c7d754e25bfe9f95f6e115d33c7df.mp3"></audio>
|
||||
|
||||
周三的分享里,我们讨论了一种叫作UCB(Upper Confidence Bound)的算法。这种算法的核心是使用均值和标准差组成对物品的估计,并且利用这种估计达到EE的效果。同时,我们也提到,UCB的最大问题就是并没有真正达到随机的效果。
|
||||
|
||||
今天,我们来看一种不太一样的算法,叫“**汤普森采样**”(Thompson Sampling)。
|
||||
|
||||
## 为什么需要随机采样?
|
||||
|
||||
在讨论汤普森采样之前,我们先来看一看什么是**随机采样**。随机采样的技术和概率分布密不可分,也和计算机产生随机数有很大的联系。
|
||||
|
||||
我们这里主要是关心如何从一个概率分布中产生一个随机变量的样本。因为是随机变量的样本,因此不可能每一次产生的结果都一样。然而,对于大量的样本来说,其均值往往是对概率分布均值的一个比较好的估计。因此,样本其实可以用来刻画一个概率分布。
|
||||
|
||||
比如,我们用参数是0.5的伯努利分布来表达抛硬币这个事件。那么,从这个伯努利分布中产生的样本,也就是0和1,象征了硬币是正面还是反面这两个事件。很显然,因为是随机样本,所以如果我们的抽样次数足够多,每个事件发生的概率会趋向于0.5。
|
||||
|
||||
然而,有一点需要注意,并不是所有的分布都能够这样容易地抽取样本。实际上,即便是伯努利分布,也是因为有一定的程序,才能够确定从中抽样。而能够抽样的,往往是标准的分布,诸如伯努利分布、高斯分布或者其他简单分布。从抽样的角度来说,对于绝大多数的模型,从中抽取样本都不是一件完全直观自然的事情。
|
||||
|
||||
回到我们讨论的场景。在进行EE策略中,为什么需要引入随机采样呢?
|
||||
|
||||
我们之前介绍过EG算法。EG算法在实施过程中,P%的人群看到按照点击率排序的物品。这一部分,是没有随机性的。也就是说这些人会“确定性”地看见按照点击率排序的物品,每一次都会看见一模一样的东西。而在(1-P)%的人群中,每一次看到的又完全是随机的内容,一点都没有规律。很明显,EG算法的缺点是,有一部分过于确定,而有一部分过于随机。
|
||||
|
||||
再来说一说我们上一次分享的UCB算法。这个算法最大的问题在于它是一个“确定”的算法。也就是说,在参数已经确定了的情况下,UCB展示给用户看的内容也是一样的。
|
||||
|
||||
这里面的一个核心问题是,如果展示给用户的内容是一样的,也就是我们说的确定性算法,那么,也就丧失了“探索”(Explore)的机会。试想,一个用户在同一天内访问一个网站多次,看到的结果都是一样的,而用户一定不希望每次访问都看到同样的内容。这对于用户体验来说很不友好。
|
||||
|
||||
那怎么才能带来随机性呢?
|
||||
|
||||
我们刚才谈了抛硬币的例子,很显然,如果能够通过采样来对物品进行排序或者展示,那就能够解决随机性的问题,也就能够每次都给用户不一样的体验。
|
||||
|
||||
## 汤普森采样基本原理
|
||||
|
||||
有了希望通过采样来获得结果这个思路以后,下面的事情就变得慢慢清晰起来。
|
||||
|
||||
首先,我们提到了,采样需要对应的概率分布。因此,**第一步就是要构建场景的概率分布,来描绘我们的应用**。
|
||||
|
||||
回到物品点击率的场景下,和抛硬币类似,物品的点击其实可以用**伯努利分布**来进行建模。这里需要注意的是,我们究竟应该从什么分布中去采样呢?汤普森采样的原理是,从模型的**后验分布**中去采样。什么意思?这其实是借用了贝叶斯统计的思路,也就是说,我们希望对参数的后验概率分布进行建模。关于贝叶斯统计的思路,这里限于篇幅不做展开。大体上来说,后验概率分布是在已经有了数据的情况下,结合我们的先验概率,对参数的一种估计。
|
||||
|
||||
再回到用伯努利分布来对点击进行建模的例子中,如果我们希望得到后验概率分布,需要设置怎样的先验概率分布呢?如果我们希望后验概率分布是一个相对比较简单的分布,那我们可以设置所谓的“**共轭先验**”(Conjugate Prior)。对于伯努利分布来说,共轭先验就是**Beta分布**。在设置了Beta分布这个先验之后,我们其实就可以解析得到后验概率的分布,也是一个Beta分布,只不过后验概率分布的参数与先验的参数不同。
|
||||
|
||||
**在构造好后验概率分布之后,我们就可以选择从中进行抽样了**。注意,在当前的情况下,已经不是从伯努利分布中抽样,而是从Beta分布中抽样了。关于如何从Beta分布中抽样,这不在今天讨论的范畴。很多通用的数值计算库,比如MATLAB、NumPy等都有这方面的过程可以直接使用。
|
||||
|
||||
汤普森采样的流程是这样的,从后验分布中抽取一个参数的样本,然后选取所有物品中参数数值最大的那个,进行展示。
|
||||
|
||||
我们来分析一下汤普森采样的整体情况。
|
||||
|
||||
<li>
|
||||
每一轮,汤普森采样都有一个**参数采样**的动作。这个流程决定了汤普森采样本质上是一个随机的流程,不是一个确定的流程。
|
||||
</li>
|
||||
<li>
|
||||
汤普森是从后验概率分布中进行抽样的。这有什么好处呢?后验概率分布中抽样,当样本数足够大的时候,样本的均值也是趋近于分布的均值的。什么意思?如果某一个物品的点击率高,那么其后验概率的均值也就大,反复从中抽样,平均下来,基本上还是在这个点击率的数值范围周边,不会偏离很远。也就是说,我们从后验概率分布中抽样的结果,当样本比较多的时候,是会尊重点击率的数值大小的。这其实就是EG中P%的用户,以及UCB中为什么要使用均值这些步骤的核心所在。我们并不希望让物品最后显示的结果与真正的估计值偏离太远。
|
||||
</li>
|
||||
<li>
|
||||
汤普森采样因为使用了贝叶斯统计,我们对参数有先验的设置,因此针对当前点击率估计还不准确甚至还没有数据的物品来说,有天然的优势。
|
||||
</li>
|
||||
<li>
|
||||
因为是采样,即便是在参数一样的情况下,两个物品的采样数值都有很大可能是不一样的,一举解决了我们之前提到的UCB的问题。
|
||||
</li>
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你介绍了一个很重要的算法叫作汤普森采样,可以解决UCB的“确定性”问题,真正实现随机的效果。结束了我们今天的分享,EE这个话题也就告一段落了。
|
||||
|
||||
一起来回顾下要点:第一,我们聊了聊为什么需要引入采样的机制;第二,我们介绍了汤普森采样的基本原理。
|
||||
|
||||
最后,给你留一个思考题,汤普森采样有没有什么问题,或者说有没有什么劣势呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
69
极客时间专栏/geek/AI技术内参/推荐系统核心技术/070 | 推荐系统评测之一:传统线下评测.md
Normal file
69
极客时间专栏/geek/AI技术内参/推荐系统核心技术/070 | 推荐系统评测之一:传统线下评测.md
Normal file
@@ -0,0 +1,69 @@
|
||||
<audio id="audio" title="070 | 推荐系统评测之一:传统线下评测" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a2/13/a2dee6b57e2198db99342fa29fc78513.mp3"></audio>
|
||||
|
||||
上周我们讨论了EE算法,介绍了UCB(Upper Confidence Bound)算法和“汤普森采样”(Thompson Sampling)。
|
||||
|
||||
这周,我们回归到一个更加传统的话题,那就是**如何评测推荐系统**。这个话题非常重要,牵涉到如何持续对一个推荐系统进行评价,从而能够提高推荐系统的精度。
|
||||
|
||||
今天,我们先来看一看**推荐系统的线下评测**。
|
||||
|
||||
## 基于评分的线下评测
|
||||
|
||||
在过去10年里,随着Netflix大奖赛的举行,很多研究人员和工程人员往往把推荐系统的模型学习简化为对用户评分的一种估计。同时,在模型上面来说,对用户物品评分矩阵进行分解成为了一种主流的方法。
|
||||
|
||||
在这样的场景下,如何对模型进行评测呢?
|
||||
|
||||
一种简单且直观的办法,就是**衡量评分的准确性**,换句话说,也就是看我们预测的评分和真实评分之间有多大的差距。
|
||||
|
||||
那么,有哪些方法可以用来衡量两个数值之间的差异呢?
|
||||
|
||||
在机器学习中,一个经常使用的测度叫“**均方差**”(Mean Square Error),或**MSE**。有时候,我们也会使用它的根号后的结果,叫作“**方差**”(Rooted Mean Square Error),或**RMSE**。
|
||||
|
||||
MSE是这么定义的。首先,如果我们知道一个用户i和物品j的真实评分,假设叫$ Y_{ij} $ ,那么我们的一个估计值是$ Z_{ij} $,MSE计算的就是$ Y_{ij} $ 和$ Z_{ij} $的差值,然后取平方。平方以后的结果肯定是一个正数,也就是说这样做的好处是整个计算不会出现负数,我们的估计值比真实值小了或者大了,MSE都可以处理。当我们对于每一个用户和物品都计算了这个差值以后,再对所有的差值的平方取一个平均值,就得到了我们所要的MSE。
|
||||
|
||||
从计算上来讲,RMSE就是在MSE的基础上再取一个根号。我们在很多实际应用中,往往使用RMSE来汇报模型的评测结果。同时,RMSE也经常用在大多数的学术论文中,但这个评测有没有什么问题呢?
|
||||
|
||||
答案是,RMSE其实存在很多问题。
|
||||
|
||||
首先,我们从刚才描述的计算过程中就可以看到,RMSE需要取一个平均值。这是对所有用户在所有物品上评分误差的估计的平均。那么,如果一个用户在数据集里面对很多物品进行了评分,这个用户误差的贡献就会在最后的平均值里占很大一部分。也就是说,最后的差值大部分都用于描述这些评分比较多的用户了。
|
||||
|
||||
上述情况存在一个弊端,如果我们得到了一个比较好的RMSE数值,往往很可能是牺牲了大部分用户的评分结果,而对于少部分的高频用户的评分结果有提高。说得更加直白一些,**那就是RMSE小的模型,并不代表整个推荐系统的质量得到了提高**。这是RMSE很容易带来困惑的地方。
|
||||
|
||||
**RMSE的另外一个问题就是,这个指标并没有反应真实的应用场景**。什么意思呢?真实的应用场景,我们往往是从一大堆物品中,选择出一个物品,然后进行交互。在这样的流程下,物品单独的评分其实并不是最重要的。更进一步说,就算一个推荐系统能够比较准确地预测评分,也不能证明这个推荐系统能够在真实的场景中表现优异。
|
||||
|
||||
## 基于排序的线下评测
|
||||
|
||||
当研究人员意识到RMSE的问题后,不少人就开始回归到问题的本质,**究竟什么样的评测更能反应推荐系统在真实场景中的表现呢?**
|
||||
|
||||
很多人很自然地就想到了搜索。
|
||||
|
||||
我们来回忆一下,搜索的结果是根据某个查询关键字,然后搜索引擎返回一系列文档结果。在这样的场景中,如果我们来和推荐进行对比,就会发现,这里面最大的区别仅仅是有没有一个查询关键词。
|
||||
|
||||
所以,我们其实**可以把搜索的一些指标“移植”到推荐中来使用**。比如,我们在搜索中讲过的**基于二元相关度的指标**。下面简单回顾一下这个指标。
|
||||
|
||||
什么叫“二元相关度”呢?简单说来,就是指针对某一个查询关键字而言,整个测试集里的每一个文档都有一个要么“相关”,要么“不相关”的标签。在这样的情况下,不存在百分比的相关度。而每个文档针对不同的关键字,有不同的相关信息。假定某个系统针对某个关键字,从测试数据集中提取一定量的文档而不是返回所有文档,我们就可以根据这个提取的文档子集来定义一系列的指标。
|
||||
|
||||
有两个定义在“二元相关度”上的指标,成为了很多其他重要指标的基石。一个叫“**精度**”(Precision),也就是说,在提取了的文档中,究竟有多少是相关的。另一个叫“**召回**”(Recall),也就是说, 在所有相关的文档中,有多少是提取出来了的。
|
||||
|
||||
“精度”和“召回”的相同点在于,分子都是“既被提取出来又相关的文档数目”。这两个指标的不同之处则是他们的分母。“精度”的分母是所有提取了的文档数目,而“召回”的分母则是所有相关的文档数目。如果我们返回所有的文档,“精度”和“召回”都将成为1(也就是说,在这样的情况下是没有意义的)。因此,我们注意到,这两个指标其实都假定,提取的文档数目相比于全集而言是相对比较小的子集。
|
||||
|
||||
我们其实就**可以利用“精度”和“召回”来评测推荐系统**。
|
||||
|
||||
然而,这有一个问题,那就是对于搜索而言,相关度大多数时候是通过人工标注的,但这个对于推荐系统来说是不可能的。因为推荐的结果对于每个人来说都是不一样的,所以,没法针对所有人来进行统一的人工标注。
|
||||
|
||||
一种折中的办法,就是使用用户的回馈信息。在这里,因为我们需要二元信息,所以可以使用像用户的点击信息或者购买信息来作为二元的相关度。也就是说,如果用户点击了某个物品,那我们就认为是相关的,反之则是不相关。
|
||||
|
||||
顺着这个思路下去,其实我们就可以计算类似于**NDCG**等更加复杂的指标,只不过我们需要自己去定义相关信息。
|
||||
|
||||
**利用排序的思路来评测推荐系统,已经成为了目前推荐系统线下评测的一个标准指标**。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了如何评测推荐系统的好坏,今天的重点是线下评测的两类指标。
|
||||
|
||||
一起来回顾下要点:第一,我们聊了聊非常通用的RMSE的评测方法,并且指出这类方法的缺陷;第二,我们介绍了怎么把搜索里的评测方法给移植到推荐中。
|
||||
|
||||
最后,给你留一个思考题,基于排序的评测有什么致命的问题吗?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
61
极客时间专栏/geek/AI技术内参/推荐系统核心技术/071 | 推荐系统评测之二:线上评测.md
Normal file
61
极客时间专栏/geek/AI技术内参/推荐系统核心技术/071 | 推荐系统评测之二:线上评测.md
Normal file
@@ -0,0 +1,61 @@
|
||||
<audio id="audio" title="071 | 推荐系统评测之二:线上评测" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/04/53/04b9f83dbd3ddc782540c87d26fe8153.mp3"></audio>
|
||||
|
||||
周一,我们聊了推荐系统的线下评测。线下评测是任何系统能够不断演化的最直接的要求。在线下的环境中,我们能够开发出系统的种种改进,并且希望能够通过这些线下评测的手段来选择下一个更好的版本。
|
||||
|
||||
今天,我们来讨论推荐系统的线上评测。任何系统在开发之后最终都要放到线上拿给用户使用。那么,在线上评测的时候需要注意什么呢?
|
||||
|
||||
## 线上评测的基础
|
||||
|
||||
推荐系统线上评测的基础和我们之前讲过的搜索系统有很多类似的地方。
|
||||
|
||||
线上评测的核心就是**在线可控实验**,有时候又称作是在线实验,或者叫作在线A/B实验。我们希望能够利用在线实验来对推荐系统的某一个部分进行检验,看是否对用户和系统的交互产生影响。
|
||||
|
||||
在线可控实验其实是建立“**因果联系**”(Causal Relationship)的重要工具,也可以说是唯一完全可靠的工具。这里面的基础是统计的**假设检验**。
|
||||
|
||||
具体来说,就是我们针对访问网站或者应用的人群,进行某种划分,一般情况下是平均随机划分。50%的用户进入被划定的一个群组,叫作“控制组”(Control Bucket),而另外50%的用户进入另一个群组,叫作“对照组”(Treatment Bucket)。“控制组”和“对照组”的唯一区别在于所面对的系统。
|
||||
|
||||
假设我们有一个推荐系统,想对其中的某个部分进行改进。那么,可以保持住其他的部分,让这个希望得到改进的部分成为唯一的“**独立变量**”(Independent Variable),也就是在整个实验设置中的变量。这样,我们就希望通过在线实验以及假设检验的工具,来认定这个“独立变量”是否会带来系统性能上的提高或是降低。
|
||||
|
||||
这里面还有一个需要提前确定的,就是需要评测的指标,特别是用户指标,比如网站的点击率、搜索的数量等。这些指标我们称之为“**依赖变量**”(Dependent Variable)。说白了,**我们就是希望能够在“独立变量”和“依赖变量”之间通过假设检验建立联系**。今天在这里,我们就不重复假设检验的基础知识了,如果有兴趣深入了解,可以参考任意一本基础的统计教程。
|
||||
|
||||
对于在线可控实验,在概念上很容易理解,但在现实操作中有很多挑战。
|
||||
|
||||
首先,我们可以想一想,虽然理想状态下,我们可以把用户五五平分,进入“控制组”和“对照组”。然而,现实中,经过随机算法分流的用户群,在这两个群组中很可能并不呈现完全一样的状态。什么意思呢?举个通俗的例子,相比于“对照组”而言,“控制组”中可能存在更多的女性用户;或者是“对照组”中,可能存在更多来自北京的用户。
|
||||
|
||||
而在这样的情况下,“依赖变量”,比如网站点击率,在“控制组”和“对照组”的差别,就很难完全解释为“独立变量”之间的差别。也就是说,如果“控制组”下的点击率比“对照组”高,是因为我们更改系统的某部分的差别呢?还是因为这多出来的女性用户呢?还是女性用户和系统某些部分的交互产生一定复杂的综合结果导致的呢?这就比较难说清楚了。
|
||||
|
||||
当然,在现实中,如果说我们依然可以比较容易地通过算法来控制一两个额外的变量,使得在“控制组”和“对照组”里面这些变量的分布相当,那么,面对十几种重要变量(例如,年龄、性别、地域、收入层级等),要想完全做到两边的分布相当,难度很大。
|
||||
|
||||
另外一个难点是,即便能够做到对已知的变量通过随机算法,使得在两个群组中的分布相当,我们依然不能对当前还未知的变量进行上述操作。因此,现实中因为人群特性所带来的对结论的影响,是在线实验的难点之一。
|
||||
|
||||
在线实验的难点之二是,即便刨除刚才所提到的人群的差异以外,我们可能也很难在设想中的某个系统“控制组”和“对照组”中,确定唯一的“独立变量”。
|
||||
|
||||
在现代网站或者应用中,有很多服务、子系统、页面、模块在同时为整个网站服务。而这些服务、子系统、页面和模块,还有不同的前端系统和后端系统,很可能属于不同的产品以及工程团队。每个部分都希望能够做自己的可控实验,都希望自己改进的部分是唯一变化的“独立变量”。然而,我们从宏观的角度去看,如果每个部分都在做自己的实验,而我们做实验的基本单元依旧是每个用户的话,那这就很难保证用户之间的可比较性。
|
||||
|
||||
举个例子,如果用户U<sub>1</sub>,进入了首页的“控制组”,然后访问了购物篮推荐模块的“对照组”后离开了网站。而用户U<sub>2</sub>,直接访问了帮助页面的“对照组”,然后访问了购物篮推荐模块的“控制组”。那U<sub>1</sub>和U<sub>2</sub>两个用户最终产生的点击率的差别,就很难从他们访问网站页面的过程中得出结论。即便是在有大量数据的情况下,我们也很难真正去平衡用户在所有这些页面组别之间的关系。
|
||||
|
||||
实际上,如何能够有效地进行在线实验,包括实验设计、实验的评测等,都是非常前沿的研究课题。
|
||||
|
||||
## 推荐系统线上评测
|
||||
|
||||
在上次的分享中,我讲了过去比较流行的推荐系统线下评测的方法,比如利用MSE以及在此之上衍生出的RMSE。然后,我又讲了如何从排序的角度来对一个推荐系统进行衡量。
|
||||
|
||||
到线上评测以后,很明显,RMSE以及排序的一些相关指标,都不能完全反映用户是否对一个推荐系统产生好感。我这里讲几个通用的指标。
|
||||
|
||||
**第一,用户的驻留或者停留时间(Dwell Time)**。这个指标主要是衡量用户在某一个物品上的停留时间。用户总的停留时间往往和用户对网站的黏稠度有很强的关系。总体说来,如果用户会长期反复访问网站,用户在网站平均驻留时间往往是比较多的。
|
||||
|
||||
**第二,用户在相邻两次访问中的间隔时间,有时叫作“空缺时间”(Absence Time)**。这个指标是越短越好。当用户反复访问你的网站,并且空缺时间越来越短,证明用户越来越依赖你网站提供的服务。
|
||||
|
||||
停留时间和空缺时间都是很好的推荐系统线上评测的指标。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了推荐系统评测的线上评测。
|
||||
|
||||
一起来回顾下要点:第一,我们聊了聊推荐系统的在线实验;第二,我们介绍了几个推荐系统线上评测的通用指标。
|
||||
|
||||
最后,给你留一个思考题,如何知道用户对于推荐的内容已经越来越不满意了呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
59
极客时间专栏/geek/AI技术内参/推荐系统核心技术/072 | 推荐系统评测之三:无偏差估计.md
Normal file
59
极客时间专栏/geek/AI技术内参/推荐系统核心技术/072 | 推荐系统评测之三:无偏差估计.md
Normal file
@@ -0,0 +1,59 @@
|
||||
<audio id="audio" title="072 | 推荐系统评测之三:无偏差估计" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/90/47/90e3696f8ba81093266e6add39711147.mp3"></audio>
|
||||
|
||||
周三,我讲了推荐系统的线上评测,我们讨论了如何做在线评测,以及推荐系统在线评测可能遇到的一系列问题。
|
||||
|
||||
今天,我们来看一个比较高级的话题,那就是如何做到推荐系统的无偏差估计。
|
||||
|
||||
## 推荐系统的偏差性
|
||||
|
||||
在理解为什么需要无偏差估计之前,我们先来看一看现在系统为什么会存在偏差性,以及这种偏差性会对推荐系统的学习造成什么样的影响。
|
||||
|
||||
先假定我们讨论的是一个新闻推荐系统。为了方便,假设我们的系统中仅有两类文章,体育新闻和财经新闻。我们先来看一个极端情况,假设系统因为种种原因,只给用户推荐体育新闻,会出现什么样的情况呢?
|
||||
|
||||
很明显,如果我们只给用户看体育新闻,那么,用户只可能在这些体育新闻里面选择点击,压根不知道财经新闻的存在。因为用户只在体育新闻里面通过点击浏览表达了喜好,任何一个机器学习系统,只能在这些新闻里面学习到用户的喜好。
|
||||
|
||||
具体来说,用户已点击的新闻可以认为是正例,没有点击的可以认为是负例。这样可以对用户在体育新闻上面的喜好加以建模。但是很明显,系统在用户对财经新闻喜好的学习上是一筹莫展的,因为我们根本没有任何用户对于财经新闻的回馈数据。
|
||||
|
||||
这就是系统的偏差性。在这样的设置下,系统存在的偏差是无法修正的。通俗地讲,我们压根没有给财经新闻任何机会,所以没有数据可以供系统学习。
|
||||
|
||||
其实还有更加严重的情况。因为我们当前的系统仅仅学习到了用户对于体育新闻的喜好,然后如果把这个系统部署到生产中,系统又会进一步选择体育新闻给用户看,如此循环下去。这其实就是说,系统的偏差性会随着机器学习系统而反复循环,甚至有逐渐放大的可能性。
|
||||
|
||||
当然在现实的应用中,我们不可能有这么极端的情况。但可能面临更加复杂的情况,比如,我们压根不知道系统存在什么样的偏差,或者说,我们该如何面对各种不同的偏差。
|
||||
|
||||
在有偏差的系统中,先通过数据学习得到模型,然后再部署到系统中去,这个流程其实严重阻碍了我们对用户真实喜好的检测。因此,这也是线下表现和线上表现不一致的一个原因。长期以来,偏差性都是困扰研究者的一个非常重要的问题。
|
||||
|
||||
## 无偏差估计
|
||||
|
||||
当我们知道系统有偏差以后,怎么来解决这个问题呢?
|
||||
|
||||
一个很容易想到的策略是,如果我们知道系统的某种偏差,那能不能在后面的评测过程中矫正这种偏差呢?
|
||||
|
||||
这就涉及“**矫正**”的思路。回到我们所说的体育新闻和财经新闻的例子。假设我们的系统在80%的情况下会显示体育新闻,20%的情况下显示财经新闻。那么,当用户面对一篇体育新闻点击浏览,或者面对一篇财经新闻点击浏览,我们的系统该如何应对呢?
|
||||
|
||||
在我们已经提到过的传统评测手段中,例如计算MAP或者NDCG的时候,这两种点击是一样的。或者说,权重是一样的。然而,在这样的情况下,机器学习系统其实还是会更加偏重于学习到用户对于体育新闻的偏好,因为毕竟80%的情况下都是体育新闻。相对于财经新闻而言,这种情况就是处于劣势的,可能我们没有给财经新闻足够的机会。
|
||||
|
||||
所以,从矫正的角度来说,我们认为如果用户点击浏览了原本出现概率较低的文章,这个时候,我们反要给这类文章更大的权重。什么意思呢?也就是说,我们认为财经新闻出现的概率比较低,如果在这种情况下,用户点击浏览了财经新闻,那应该是真正的偏好。而相同的情况下,因为80%的新闻都是体育新闻,因此用户点击了其中的一篇也就不足为奇。
|
||||
|
||||
把这种思维放入到一种数学的表达中,也就是,我们希望用户的回馈按照出现的概率进行**反比矫正**,出现概率越大的物品,正样本权重越小;反之,出现概率越小的物品,正样本权重越大。具体来说,也就是正样本除以出现的概率,然后我们计算平均的加权点击率。这样加权平均后的结果,就是矫正后无偏差的点击率的计算结果。
|
||||
|
||||
很明显,无偏差估计是有一定假设的。首先,我们就需要假设收集的数据涵盖了整个数据集。什么意思?就是刚才我们说的极端情况,比如我们只显示体育新闻而压根一点都不显示财经新闻,这种情况是无法进行矫正的,因为在这种情况下,财经新闻的概率是0。也就是说,无论什么类别的新闻,都需要有非零的概率出现。这是进行无偏差估计的一个基本假设和要求。
|
||||
|
||||
遗憾的是,虽然这个要求看似容易,但其实在现实中很难真正做到。
|
||||
|
||||
试想一个有百万文章量的新闻网站,要确保所有的新闻都有一定概率显示给用户是有挑战的。在实际的应用中,大量的新闻质量是呈指数下降的。也就是说,虽然有百万甚至更多的文章量,但是很有可能只有几百几千的文章相对比较有质量,而剩下的大量文章是低质量的文章。
|
||||
|
||||
然而,我们并不能完全确定哪些是低质量文章。如果我们真的需要做无偏差的估计,就需要针对所有的文章进行显示,也就是说,我们需要冒着给用户显示低质量文章的风险,显然这并不是很好的策略。
|
||||
|
||||
在如何收集数据这一方面,无偏差估计其实和我们之前提到过的EE策略又结合在了一起。也就是说,如何既能够让我们尽可能地把所有数据都呈现给用户,使得我们可以进行无偏差估计,又能够照顾到用户的体验,这是目前非常热门的研究领域。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你重点讲了什么是系统的偏差以及如何处理偏差的思路。
|
||||
|
||||
一起来回顾下要点:第一,我们聊了聊在线系统的偏差出现的场景以及机器学习为什么会让这样的情况恶化;第二,我介绍了如何进行无偏差估计以及无偏差估计所需的条件。
|
||||
|
||||
最后,给你留一个思考题,假如一个系统,你不知道每一种新闻出现的概率,你该如何做无偏差估计呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<audio id="audio" title="073 | 现代推荐架构剖析之一:基于线下离线计算的推荐架构" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ed/c9/ed9de7f1c336b565d335fcfcedc227c9.mp3"></audio>
|
||||
|
||||
上周,我们讨论了推荐系统的评测,聊了推荐系统的线下评测、线上评测和无偏差估计。至此,我们已经聊了推荐系统的一些基本技术和评测体系,相信你已对推荐系统有了一个基本的认识。
|
||||
|
||||
那么,到底该如何搭建一个工业级的推荐系统呢?这周,我们就来谈一谈**现代推荐系统的架构体系**,帮助你从宏观上对推荐系统的构建有一个更加完整的认识。
|
||||
|
||||
今天,我们先来看一看,**基于线下离线计算的推荐架构**。
|
||||
|
||||
## 推荐架构需要解决的问题
|
||||
|
||||
在讨论任何一种架构之前,我们首先来看一下这个架构需要解决什么样的问题。然后在这些问题的指引下,我们就可以来分析不同架构在解决这些问题上的优劣。
|
||||
|
||||
那么,对于一个推荐架构来说,我们需要解决什么样的问题呢?
|
||||
|
||||
首先,从大的角度来说,一个用户来到我们的网站或者服务,**推荐系统最重要的一个任务就是,能够在一两百毫秒内给用户提供当前的推荐结果**。也就是说,从用户的角度来看,**推荐结果的呈现必须是实时的**。这一条就是把工业级应用和学术模型区分开的一个重要指标。
|
||||
|
||||
在过去十多年里,学术界的推荐系统,或者是Kaggle竞赛的推荐系统,往往是一个使用了很多不同模型的**集成模型**(Ensemble Model),这种方式虽然在比赛和论文发表中能够取得较高的精度,但是在现实的系统中,如果不加修改直接使用,必然无法在规定的时间内,也就是一两百毫秒内产生所有的推荐结果。同样的,很多非常复杂的深度学习模型,也无法在规定的时间内产生所有的推荐结果。由此可见,很多推荐架构的核心就是在解决这些问题。
|
||||
|
||||
其次,**推荐系统架构需要对用户和系统的交互结果做出响应**。什么意思呢?如果用户看了推荐结果,并且点击了一些推荐结果,或者明确表达了对推荐结果的不喜爱,那么推荐模块需要对这些互动的结果给予回馈。试想,如果一个用户已经明确表示了对某些结果的不喜欢,然后在下一次访问的时候,用户又看到同样的推荐,那一定是一个非常不好的体验。
|
||||
|
||||
最后,**推荐系统架构需要考虑用户群体的覆盖率的问题**。如果一个系统架构只能为部分用户服务,这想必无法真正做到对一个网站或者服务产生影响力。因此,在模型以及其他的技术选择上面,如何能够做到“为更广阔的用户群体服务”,就是一个非常关键的因素。
|
||||
|
||||
## 基于线下离线计算的架构
|
||||
|
||||
刚才我们简单讨论了一个现代推荐系统架构需要满足的一些需求。那么,在这些需求的驱动下,一种简单易行的架构就诞生了,那就是“**基于线下离线计算的架构**”。
|
||||
|
||||
什么叫基于线下离线计算的架构呢?
|
||||
|
||||
试想一下,我们有一个推荐模块,是在一个网站首页为用户推荐新闻。现在假设,我们有M个用户,N个新闻文章。M的数量级可能是几千万,N的数量级可能是几百万。那么,理想状态下,需要用我们的模型,对每一个用户,以及每一个新闻进行打分。具体地,对于某一个用户来说,当这个用户访问网站的那一瞬间,我们需要对几百万的新闻进行打分,并且在一两百毫秒内返回结果,这很有可能是不现实的。
|
||||
|
||||
既然我们无法**实时**对所有的新闻打分,那么,退一步讲,我们能不能事先把这些打分的工作都做了,然后当用户来到网站的时候,我们仅仅是显示结果呢?答案是,可以的,并且**这就是线下离线计算的核心思想**。
|
||||
|
||||
通俗地说,**线下离线计算的一个主要想法**就是:把计算中复杂的步骤尽量提前做好,然后当用户来到网站需要呈现结果的时候,我们要么已经完成了所有的计算,要么还剩非常少的步骤,可以在很快的时间内,也就是所说的一两百毫秒内完成剩下的计算。
|
||||
|
||||
回到我们刚才的新闻推荐的例子。我们可以把针对每一个用户的所有新闻的打分,在线下都提前计算好,然后存放在一个数据库或者数据存储的地方,当用户来到网站的时候,我们只需要展示已经完全计算好的推荐结果。
|
||||
|
||||
完全线下离线计算的最大好处就是,当用户来临的时候,基本没有任何的计算成本。系统唯一需要做的就是从一个数据存储的地方直接取得当前的推荐结果。
|
||||
|
||||
也就是说,线下离线计算的最大好处,就是解决我们刚才说的在规定的时间内计算出推荐结果的需求。然而,线下离线计算对其他两个需求则无法很好地处理。
|
||||
|
||||
第一,因为我们是完全提前计算好了所有的结果,并且存储在数据库中。那么,假设用户和推荐结果进行了交互,希望更新推荐结果,离线计算的模式就无法支持这样的操作,或者是非常困难。
|
||||
|
||||
我们可以试想一下,如果一个用户不喜欢某一个新闻推荐结果,那么在当前的框架下,我们应该如何应对呢?首先,我们需要启用线下的计算流程,重新计算这个用户所有的推荐结果,然后把这个推荐结果存储到刚才说的数据库里,这样用户下一次来到网站的时候,就会看到更新的结果了。
|
||||
|
||||
因为刚才我们已经假设模型的复杂度导致无法很快地进行运算,因此,这个更新的流程可能会比较耗时。同时,这只是一个用户的情况,如果我们要针对大量用户进行这样的处理,那最省力的就是隔一段时间,比如说几个小时就针对那些和系统有交互的用户重新计算一次结果,然后再把更新的结果存入数据库。很明显,在这几个小时的间隙里,用户看到的依然是旧的推荐结果。
|
||||
|
||||
第二,完全提前计算好所有结果的情况下,针对新的用户,新的新闻文章就无法进行推荐了。针对这些新用户和新文章来说,完全离线计算这种架构就有一个致命的缺陷。当然,我们也可以依照刚才的思路,也就是说隔一段时间,比如几个小时,就针对当前所有用户和所有新闻,重新计算结果,然后把结果存放到数据库中,但是很明显,这也会导致在这个间歇期内,我们无法对新用户和新文章进行推荐。
|
||||
|
||||
**完全离线计算的推荐架构适用于一些简单的场景和一些应用的初期架构**。很明显,在复杂的网站需求下,单靠提前把所有结果都计算好是不能满足动态的用户需求的。
|
||||
|
||||
然而,理解离线计算的需求对于构建复杂架构很有帮助。**我们在设计一个更加复杂的架构时,依然会依靠很多离线计算,用线下时间来换取线上时间。这个思路是现代推荐系统架构中非常重要的一个想法。**
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了一种简单的现代推荐系统的构建思路,那就是基于线下离线计算的推荐架构。
|
||||
|
||||
一起来回顾下要点:第一,我们聊了聊推荐架构的需求;第二,我们介绍了什么是离线计算架构,以及这种架构的优缺点是什么。
|
||||
|
||||
最后,给你留一个思考题,如果我们的用户数量和物品数量实在是太大,线下计算无法满足每天全部更新一次推荐,这种情况下,我们又该怎么办呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<audio id="audio" title="074 | 现代推荐架构剖析之二:基于多层搜索架构的推荐系统" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b1/f0/b1fd6890599c0c0b94a7435de333bef0.mp3"></audio>
|
||||
|
||||
周一,我们讨论了基于线下离线计算的推荐架构,这也是最简单的一种推荐架构。我们了解了这种架构的优劣势,以及能够做的一些方案。
|
||||
|
||||
今天,我们来看另外一种也很常见的推荐系统架构,那就是**基于多层搜索架构的推荐系统**。
|
||||
|
||||
## 推荐架构需要解决的问题
|
||||
|
||||
周一我们详细讨论了推荐架构需要解决的问题,今天做一个简单的回顾。
|
||||
|
||||
推荐系统解决三个需求。
|
||||
|
||||
第一,推荐系统架构能够在一两百毫秒内给用户提供当前的推荐结果,即实时呈现推荐结果。
|
||||
|
||||
第二,推荐系统架构需要对用户和系统的交互结果做出响应。
|
||||
|
||||
第三,推荐系统架构需要考虑用户群体的覆盖率问题。
|
||||
|
||||
我们周一次讲到的基于离线计算的推荐架构,可以很好地解决第一个问题。解决思路就是先计算好所有的结果,然后存在某种存储空间里,当用户来到网站的时候,再直接显示事先已经计算好的结果。然而,这样的架构在第二和第三个需求面前,就显得有些捉襟见肘了。
|
||||
|
||||
## 基于多层搜索架构的推荐系统
|
||||
|
||||
我们前面在介绍搜索系统的时候,多次提到了**多层搜索架构**。一起来回顾一下这种架构。
|
||||
|
||||
首先,我们有一个索引,能够根据某些特性(比如关键字)来把所有的文档存储到里面,方便随时检索。
|
||||
|
||||
第一层或者叫第一轮打分,是发生在索引这个层面,我们通过一些简单的流程或者函数,往往是**线性函数**或者**布尔值函数**,来获取最相关的几百最多几千个文档。
|
||||
|
||||
紧接着,第二层或者叫第二轮打分,就是一个重排序的过程。这个时候,我们往往只需要针对几百个文档进行打分,所以可以使用相对比较复杂的函数,比如**基于决策树的模型**或者**深度模型**,以得到最终的结果。
|
||||
|
||||
有些时候,在第二轮打分之后,还有后面的轮数,主要是针对一些不同的商业规则,比如结果的多样性等等。
|
||||
|
||||
多层搜索架构可以支持搜索结果,自然地,对第一个需求,也就是在规定的时间内返回结果,有很好的支持。在搜索里面,用户输入查询关键词以后,大多数情况都希望能够快速得到结果。一般来说,我们把在所有文档里查找相关信息分解为两个步骤,先查找一个大概相关的集合,然后再在这个集合里进行重排序。特别是第一个步骤,往往是在索引上并行进行的,因此速度也相对比较快。
|
||||
|
||||
那么,多层搜索架构如何来解决第二和第三个需求呢?
|
||||
|
||||
我们先来看第二个需求,也就是说如何针对用户的反馈对结果进行更新。所谓进行更新,其实就是说,给用户的推荐结果,需要有一些不一样的地方。但是,如果我们仔细想一下这个需求,就会发现,第二个需求的核心是**需要对用户的反馈进行更新**,但也不能走向另外一个极端,那就是用户点击或者浏览了一两个物品后,整个推荐结果就全部发生了改变。因此,如果我们在这种**需要变化但又不是大变的假设**之下,多层搜索架构就能相对容易地解决这个问题。
|
||||
|
||||
例如,我们可以根据索引返回用户可能喜欢的一千个物品。假定用户的喜好不会在每一天内发生巨大变化。这个索引本身可以每天更新,但不需要更新得特别频繁。因为用户点击了一些物品,之后需要产生的更新变化,我们可以寄希望在重排序这个环节发生。也就是说,**我们在每一天中,从索引中提取出来的内容都可以是一模一样的,但是我们可以根据重排序的部分产生不一样的结果,这样也就满足了用户的需求。**
|
||||
|
||||
具体来说,在重排序的阶段,有两种方法可以根据用户的反馈进行更新。
|
||||
|
||||
**一种方法,就是更新重排序阶段的模型**。如果重排序阶段是一个决策树模型,那我们就对这个决策树进行重新训练。这里主要取决于重排序阶段是一个什么样的模型。如果这个模型需要所有用户的信息,那重新训练的计算量,无疑是非常大的,而且往往还无法在线完成。在这样的情况下,重新训练可能并不是最优的解决方案。
|
||||
|
||||
**另外一种方法,就是更新重排序的模型的某些特性**。如果重排序模型使用了一些特性,其中包含记录了用户的一些行为。那么,我们其实可以在不更改模型的情况下,通过更新特性的数值来达到更新结果的目的。比如,可能有这么一个特性,记录用户在某个物品上点击了多少次,那么我们单单刷新这个特性的数值就可以了。
|
||||
|
||||
对于第三个需求,也就是说如何针对新用户和新物品进行支持。可以说,**搜索架构对于新用户是天然支持的**。因为索引里面是物品,而并不是特定的用户信息,所以新老用户对于这个以索引为基础的架构来说是一样的。不太相同的自然是新老用户的特性值是不一样的,因此取决于重排序的模型,很有可能是针对老用户有比较强的效果,而针对新用户则可能会有一些捉襟见肘。
|
||||
|
||||
相对来说,**搜索架构的短板在于对新物品的支持**。因为整个索引机制是基于物品的,因此当我们已经建立了一个当前的索引后,新的物品不在索引里面,因而无法在提取阶段被取出来。一个比较直接的方法自然是重新建立索引,然而如果我们有上百万的物品,重建索引并不是一个简单容易的步骤。关于如何支持这样一个功能,我们留到下一次分享中探讨。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了基于多层搜索架构的推荐系统。
|
||||
|
||||
一起来回顾下要点:第一,我们回顾了推荐架构的需求;第二,我们介绍了什么是多层搜索架构,以及这个架构是如何利用到推荐场景的,同时还聊了聊这种架构的优缺点是什么。
|
||||
|
||||
最后,给你留一个思考题,我们谈到了用索引来帮助推荐系统的构建,那么在搜索里面索引可以根据关键字来建立,在推荐系统中,我们怎么构建索引呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
55
极客时间专栏/geek/AI技术内参/推荐系统核心技术/075 | 现代推荐架构剖析之三:复杂现代推荐架构漫谈.md
Normal file
55
极客时间专栏/geek/AI技术内参/推荐系统核心技术/075 | 现代推荐架构剖析之三:复杂现代推荐架构漫谈.md
Normal file
@@ -0,0 +1,55 @@
|
||||
<audio id="audio" title="075 | 现代推荐架构剖析之三:复杂现代推荐架构漫谈" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/90/c5/90f82b7f1c60b571280c6783b21814c5.mp3"></audio>
|
||||
|
||||
本周我们讨论现代推荐系统的架构体系。周一我们看了最简单的基于线下离线计算的推荐架构,周三我们聊了基于多层搜索架构的推荐系统。
|
||||
|
||||
今天,我们来谈一谈如何从这两种架构的思路出发,来满足更加复杂多变的实际情况。
|
||||
|
||||
## 推荐架构需要解决的问题
|
||||
|
||||
这周我反复强调推荐系统的几个基本需求点。第一,能够在一两百毫秒内给用户提供当前的推荐结果;第二,需要对用户和系统的交互结果做出响应;第三,需要考虑用户群体的覆盖率问题。
|
||||
|
||||
接下来我们就聊一些经常考虑的场景,起到一个抛砖引玉的作用,供你参考。
|
||||
|
||||
## 新用户的问题
|
||||
|
||||
如果你要搭建的系统面临的情况是新用户多,比如一个新上线的快速增长的产品,那么我们需要怎么考虑架构呢?
|
||||
|
||||
这里面有**两个基本思路**。第一,我们要更加快速地抓住这些新用户和系统的交互信息,从而更好地为他们推荐信息。第二,在我们还没有足够多的信息的时候,如何为这些用户提供推荐结果。
|
||||
|
||||
我们先从第一点说起,如果希望能够更加快速地抓住用户的交互信息,从而很好地为他们推荐内容,有两种做法:要么能够快速更新模型从而更新推荐结果,要么快速更新特性从而更新推荐结果。
|
||||
|
||||
如果我们整个产品只有一个全局的排序模型的话,不管是基于线下的静态架构还是基于搜索的架构,基本上都不可能很快地去更新这个全局模型。因此,在这种情况下就需要去思考如何更新特性。
|
||||
|
||||
对于搜索的框架,也许我们可以通过更新特性,从而达到在重排序的这个阶段,因特性改变而带来不同的结果。但是对于线下的静态架构,因为所有推荐结果都是事先处理好的,因此改变特性也不能改变结果,除非针对这个用户,对所有的推荐结果重新进行线下计算。这样做是可行的,但是计算成本还是相对比较高。因此,综合来看,如果在新用户比较多的情况下,并且我们还希望抓住用户的交互,静态架构可能就会显得有一些心有余而力不足了。
|
||||
|
||||
第二点则是新用户的交互信息一开始会比较少,如何处理冷启动呢?我们前面提到过,其实冷启动可以利用一些用户的其他信息,比如年龄、性别、地理信息来产生推荐结果。我们可以为用户显示当前比较流行的在某个年龄段、某个性别、某个地理区域的信息。
|
||||
|
||||
一个简单的思路是,这些年龄、性别、地域的信息,可以每个小时或者每天更新一次,单独存放在一个数据库里。当用户来网站的时候,我们可以尝试从搜索的架构里提取信息,也从这个单独的数据库里提取信息,然后在这个基础上进行全部重新排序。这样我们就能够保证架构的统一性,同时也解决了冷启动的问题。
|
||||
|
||||
## 新物品的问题
|
||||
|
||||
和大量新用户问题不同的是,大量新物品的问题则更加棘手一些。
|
||||
|
||||
在静态框架下,新物品意味着对于所有的用户,我们之前都没有考虑过这些物品,因此如果不进行特殊处理,我们是绝对没法把这些物品展示给用户看的。
|
||||
|
||||
这里有两种思路。**一种思路**,就是把新物品加入到内容池里,对于所有用户,全部重新生成推荐结果。这当然是最简单的想法,但是很显然,这样做是非常耗时的。**另外一种思路**,我们把当天产生的新物品单独存储在一个数据库,针对这些物品给出一些预估计的分数。这里当然可以针对物品的特性打分,也可以随机给定一些分数。然后我们在显示推荐的时候,可以混合之前线下已经产生的推荐结果和当天的新物品结果,这样从用户的角度来看,我们是可以对新物品进行推荐的。
|
||||
|
||||
在搜索的架构下,也有**两个类似的思路**。第一,那就是我们对索引进行重索引,但这个过程相对比较耗时。第二,那就是对新物品构建一个临时索引或者数据库,最后的结果是从索引和当天的临时存储中共同获取,然后进行重新排序。
|
||||
|
||||
在新物品比较多,并且很快就会过时的情况下,另外一个需要注意的棘手问题就是,推荐的模型一定不能仅仅抓住用户喜爱的某一个物品。比如新闻推荐,用户喜欢某一个新闻,但是这个新闻很快就会过时。这就和商品推荐有很大不同,对于商品来说,用户可以反复购买同一件日用品。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我为你讲了利用推荐系统的一个重要问题,就是如何构架一个现代推荐系统。我们聊了两个场景下的一些更加细致的取舍,分别是新用户多的情况和新物品多的情况。
|
||||
|
||||
其实,所有的这些思路都不是“死规矩”,但是有一些基本的规则你可以去琢磨。
|
||||
|
||||
**比如,我们尽可能把复杂的运算放在线下,因为毕竟需要在规定的时间内返回结果。在一切有可能的情况下,尽可能使用搜索引擎来减少需要对大量物品进行打分的步骤。再比如,对于活跃的用户,我们可以使用多层搜索架构;但是对于不活跃用户,我们可以依赖线下,提前产生所有的推荐结果。**
|
||||
|
||||
一起来回顾下要点:第一,我们再次回顾了推荐架构的需求;第二,我们通过两个场景,新用户多和新物品多,分析了架构里面的一些取舍。
|
||||
|
||||
最后,给你留一个思考题,假设我们的推荐系统需要给一个手机客户端的产品进行推荐,有什么和桌面端不一样的,需要在架构上额外注意的地方呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
|
||||
67
极客时间专栏/geek/AI技术内参/推荐系统核心技术/076 | 基于深度学习的推荐模型之一:受限波兹曼机.md
Normal file
67
极客时间专栏/geek/AI技术内参/推荐系统核心技术/076 | 基于深度学习的推荐模型之一:受限波兹曼机.md
Normal file
@@ -0,0 +1,67 @@
|
||||
<audio id="audio" title="076 | 基于深度学习的推荐模型之一:受限波兹曼机" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b5/f5/b5d1ca12f67fc04ba2e4e32429e103f5.mp3"></audio>
|
||||
|
||||
这几周我们进入专栏里一个比较大的模块,那就是推荐系统。
|
||||
|
||||
上周,我们谈了现代推荐系统的架构体系,帮助你在宏观上对推荐系统的构建有一个更加完整的认识。这周,我们主要来看在推荐系统研究领域里一个比较前沿的话题,那就是**如何利用深度学习来提升推荐系统的精度**。
|
||||
|
||||
今天,我们首先来看一篇经典的文章《受限波兹曼机进行协同过滤》([Restricted Boltzmann machines for collaborative filtering](https://www.cs.toronto.edu/~rsalakhu/papers/rbmcf.pdf))[1],这篇文章尝试使用**受限波兹曼机**(Restricted Boltzmann Machines),简称 **RBM**,来对推荐系统进行建模。这应该是最早把深度学习应用到推荐建模的典范。
|
||||
|
||||
## 受限波兹曼机(RBM)
|
||||
|
||||
从严格意义上讲,RBM自身并不是深度模型,在早期对于RBM的使用上,也并没有将其“累加”到很多层从而形成“深度RBM”(Deep RBM)。但是从建模思路上来说,由一层RBM到多层RBM的扩展其实是非常直接的,因此了解RBM的基本思路,对后面理解推荐系统中如何利用深度学习模型进行建模是很有帮助的。
|
||||
|
||||
今天我们要介绍的文章发表于2007年的ICML(International Conference on Machine Learning,国际机器学习大会)上。作者群是鲁斯兰·萨拉胡特蒂诺夫(Ruslan Salakhutdinov)、安德烈·尼哈( Andriy Mnih)以及杰弗里·辛顿(Geoffrey Hinton)。
|
||||
|
||||
辛顿在近日常常被称作深度学习之父。他不仅算是波兹曼机(Boltzmann Machines)的重要发明人和推动者之一,也和其学生一起把RBM应用到各类数据上,比如RBM在推荐领域的尝试。
|
||||
|
||||
2007年的时候,Netflix大赛如火如荼,很多学者都希望把各种模型和思路应用到这个比赛中。而在这个大赛中,有三个重要的思想脱颖而出,影响了后来推荐系统的研究发展。这三个思想分别是:
|
||||
|
||||
<li>
|
||||
基于矩阵分解的模型;
|
||||
</li>
|
||||
<li>
|
||||
基于RBM的模型;
|
||||
</li>
|
||||
<li>
|
||||
利用集成学习(Ensemble Learning)把大量不同的模型整合起来。
|
||||
</li>
|
||||
|
||||
由此可见,RBM对于推荐系统的尝试在当时是非常有新意的。
|
||||
|
||||
第一作者鲁斯兰当时在多伦多大学攻读计算机博士,跟随辛顿研究深度学习模型。另外一篇他当时做的工作,是把贝叶斯矩阵分解利用到Netflix大赛中,和我们今天讨论的这篇论文一起,都是他在博士阶段对于推荐系统这个领域所做的重要贡献。目前鲁斯兰在卡内基梅隆大学任教,并兼任苹果公司的人工智能总监一职。
|
||||
|
||||
那什么是RBM呢?简单说来,RBM就是由一层**隐单元**(Hidden Unit)和一层**显单元**(Visible Unit)组成的神经网络结构。通常情况下,显单元和隐单元这两层之间是完全连通的。也就是说,对于每一个显单元来说,它都和所有的隐单元联系到一起。
|
||||
|
||||
**每个隐单元和显单元自身都有一个权重(Weight),并且在每对隐单元和显单元之间的连接上还有一个权重**。所有这些权重都是需要通过训练学习的未知参数。举例来说,如果我们有3个显单元(用于描述3个数据点),5个隐单元。那么我们就有3个权重对应3个显单元,有5个权重对应5个隐单元,然后有15(3*5)个连接权重,这样算下来一共是23个权重。RBM可以针对高斯信号,也就是实数信息,以及伯努利或者二项分布(Binomial Distribution)信号,也就是离散信息,进行建模。
|
||||
|
||||
## 受限波兹曼机在推荐上的应用
|
||||
|
||||
当我们对RBM有了一个基本的了解之后,我们来看RBM是怎么应用到推荐系统上的。为了讲解方便,我们这里使用Netflix的例子,也就是对“用户为电影打分”进行建模。
|
||||
|
||||
首先,对于每一个用户,我们使用一个单独的RBM来对这个用户进行建模,只不过,每一个RBM都有一样的隐单元数量。在建模的时候,每一个RBM仅仅对当前这个用户曾经打过分的数据进行建模。也就是说,每一个RBM需要建模的数据是不一样的,有的用户对三个电影打过分,有的对十个电影打过分。你可以设想一下,在这样的情况下,整个模型是什么意思。
|
||||
|
||||
每个用户有一个独立的RBM,这个RBM负责对这个用户的电影集合进行建模。很显然,这些RBM互相没有关联。那怎么把每个用户的RBM给联系起来呢?作者们做了这样的假设,也就是每个RBM的隐单元是不一样的,这其实可以代表学习到的“用户的偏好”。但是,如果两个用户都对同一个电影打过分,那么,针对这个电影,两个不同的RBM会共享一样的权重。这就是联系两个RBM的核心思想,也就是说,**利用RBM对用户电影推荐的核心是“共享相同电影的权重”**。
|
||||
|
||||
具体说来,每一个显单元都是用户对于某个电影的评价。这里每个显单元都是一个K维的数组,其中只有一个元素是1,其他都是0。这种**二元的数组表达**,帮助模型来对“用户对于有K种可能的输出”进行建模。隐单元在这篇论文中,也是二元的,只不过,我们事先并不知道隐单元的取值。和刚才介绍的一样,在这样的模型里,需要学习的参数包括显单元的权重、隐单元的权重以及他们之间关系的权重,同一个电影的权重是共享的。
|
||||
|
||||
每一个用户都有一个单独的RBM,并且我们在RBM里只对已经评过分的电影进行了建模,因此这个模型并不能直接对未知的电影评分进行预测。需要预测的时候,我们其实是先拿到这个电影的权重,然后看,我们把那个K维的评分数组设置成哪种情况的时候,产生的概率是最大的。也就是说,我们尝试把对于未知的电影评分设置成不同情况,取出现可能性最大的那种评分作为预测结果。很明显,这样做的计算效率并不高。文章中也介绍了如何加速,我们这里就不复述了。
|
||||
|
||||
**RBM对于推荐系统的建模看上去很简单,但是难点却是如何学习这些未知的权重**。总体说来,RBM无法直接使用类似“最大似然法”或者“递归下降”的方法来对参数进行学习。这其实也是阻碍这类方法广泛使用的一个重要障碍。在最初的论文里,作者们提出了一种CD(Contrastive Divergence,对比散度)方法,这种方法其实是一种简化的MCMC(Markov chain Monte Carlo,马尔科夫蒙特卡洛)方法,用于对RBM进行采样。CD方法具体是如何实现的,我们这里就不展开了。
|
||||
|
||||
在Netflix的数据集上,RBM展现了惊人的效果,不仅能够很轻松地击败Netflix自身的算法基线,还比当时提出的单纯的矩阵分解方法要更加优秀。基于此,后来就有了很多RBM的扩展工作。
|
||||
|
||||
## 小结
|
||||
|
||||
这周我来为你讲解利用推荐系统的一个重要的问题,就是如何利用深度学习模型来对推荐系统进行建模。今天我们聊了一个最基本的深度学习模型,受限波兹曼机,讨论了如何将其应用在推荐系统中。
|
||||
|
||||
一起来回顾下要点:第一,我们介绍了什么是受限波兹曼机;第二,我们讨论了如何把受限波兹曼机应用到推荐场景中。
|
||||
|
||||
最后,给你留一个思考题,如果希望在受限波兹曼机里增加其他信息,比如各种用户信息或者电影信息,我们该如何做呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
**参考文献**
|
||||
|
||||
1. Ruslan Salakhutdinov, Andriy Mnih, and Geoffrey Hinton. **Restricted Boltzmann machines for collaborative filtering**. Proceedings of the 24th international conference on Machine learning (ICML '07), Zoubin Ghahramani (Ed.). ACM, New York, NY, USA, 791-798, 2007.
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<audio id="audio" title="077 | 基于深度学习的推荐模型之二:基于RNN的推荐系统" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/71/bc/71486b5621aa731a60fdccac3a5e71bc.mp3"></audio>
|
||||
|
||||
周一我们看了一篇经典的文章,那就是尝试使用受限波兹曼机(RBM)来对推荐系统建模。这应该是最早把深度学习应用到推荐建模的典范。当然,RBM虽然算是相对比较早的深度学习模型,但其本质上并没有很多后来提出的深度模型的特质,也没有真正发挥出深度学习模型的特有优势。
|
||||
|
||||
今天,我们结合几篇论文来看一类深度学习模型,那就是“**递归神经网络**”(Recurrent Neural Network),简称 **RNN**,在推荐系统中的应用。这类模型可以解决传统推荐模型中难以对时序信息进行建模的问题,扩宽了推荐系统的应用边界。
|
||||
|
||||
## 时序信息建模
|
||||
|
||||
要想说清楚RNN对于推荐系统的贡献,我们首先要来看一看为什么需要对时序信息进行建模。
|
||||
|
||||
在我们前面介绍的诸多推荐模型中,不管是矩阵分解,还是简单的基于流行度的推荐模型,或是其他更加复杂的张量分解等模型,其实都没有内置“时间”这个概念。
|
||||
|
||||
比方说,我们通过矩阵分解来对用户和物品的评分进行建模。在这个建模的场景里,用户物品评分矩阵是针对所有数据的,不管是用户昨天对某个物品进行评分还是今天,甚至是一年以前,所有数据都是在唯一一个矩阵里面加以表示。这么做的好处是,极大地简化了真实情况,不好的地方则是完全忽略了所有评分在时间上的发展。
|
||||
|
||||
其实早在Netflix大赛中,一些学者就在Netflix公布的数据集上发现,用户对于电影的喜爱程度,或者说评分数值,有非常明显的随时间变化而变化的趋势。文末我列的参考文献[1],这篇论文就是充分挖掘了时间信息从而带来了性能上的提升,如果你有兴趣的话,建议读一读这篇文章。
|
||||
|
||||
在深度学习模型,特别是RNN之前,如果我们希望对时间进行建模,从模型工具的角度上来说,我们都有哪些选择呢?
|
||||
|
||||
**一种办法是可以尝试使用传统的“时序模型”(Time Series Models)**。这一类模型在统计领域已经使用了较长时间,然而最大的问题就是,很多工具很难直接和我们提到的这些推荐模型进行嫁接。另外一个难点是在嫁接之后,模型的训练算法往往会变得异常复杂,这也给模型的普及和使用带来了很多障碍。
|
||||
|
||||
**另外一种办法,就是尝试在现有的模型里通过特性(Feature)或者其他的方法,来让当前的模型能够对时间信息进行建模**。这个思路其实是对矩阵分解进行了修改。这样做的好处就是可以根据自己的需要在某一个模型上进行必要的更改,然而这么做的先天性缺陷就在于提出来的修改往往只能针对某一个模型,而没有办法扩展到其他模型。
|
||||
|
||||
**第三种做法是可以利用张量分解(Tensor Factorization)**。我们直接把时间作为一个新的维度,因此可以对用户在某一个时间段对某个物品的评分进行建模,有一些工作是基于这个假设的。
|
||||
|
||||
不过,直接利用张量分解的最大问题是,张量本身并不是时序模型,利用张量对时序信息进行建模仅仅是因为时序信息大多时候可以被表达成为离散的数据,因此张量才在这里有了用武之地。然而,因为张量无法直接对离散时序的两位数据点之间进行约束建模,比如时间点“昨天”和时间点“今天”可能在张量中占据两个不同的数据点,但是张量本身并不能把这两个数据点联系起来。也就是说,张量在“语义”(Semantics)上其实并不支持时序数据。
|
||||
|
||||
基于以上这些原因,我们需要有新的工具来对时序信息进行比较直接的建模,同时也能有相对容易的学习算法。
|
||||
|
||||
## 基于RNN的推荐模型
|
||||
|
||||
RNN作为深度学习中有力的时序信息建模工具,随着深度学习的火热,被越来越多的学者用来解决我们刚才所说的这些问题。我们一起来看两篇论文,可以说这两篇文章是RNN在推荐领域应用的重要参考。
|
||||
|
||||
除了从工具的角度来讲为什么需要RNN以外,还有一个是从实际的场景出发,也就是在同一个“**会话**”(Session)中的推荐结果,这是一个比较突出的需要时序信息的场景,且传统的方法无法很好地解决。
|
||||
|
||||
在这方面比较早的尝试,来自于在ICLR2016上发表的一篇论文《使用递归神经网络的基于会话的推荐》(Session-based recommendations with recurrent neural networks)[2]。这里面的基本思路其实很直观,就是在推荐系统中使用某种RNN模型,在这篇论文里使用的是 **GRU**(Gated Recurrent Unit)。我们在这里不展开RNN或者GRU的定义细节以及这些模型里面的特征。我们从比较高的维度来讲一讲RNN的建模思路。
|
||||
|
||||
RNN的输入是当前的一个物品,然后RNN需要输出的是对于下一个物品的预测,同时为了能够对这些在时间序列上的物品进行建模,RNN内部也要维持一个隐含的状态序列,这个状态序列会随着时间的变化而变化。不同的RNN模型在以下内容的实现上有所不同,包括如何实现这个隐含的状态序列,以及如何对从状态序列到输入和输出物品的建模。
|
||||
|
||||
总的来说,这篇论文就是直接把目前在自然语言处理中经常使用的GRU拿到了推荐领域,并且做了一些微小的修改。从实验结果来看,如果我们对会话进行建模的话,效果要明显好于没有对会话进行建模。
|
||||
|
||||
再介绍一个比单对会话进行建模更进一步的工作,是发表于WSDM2017上的一篇论文《递归推荐网络》(Recurrent Recommender Networks)[3]。我们前面提到了,矩阵分解的最大问题就是学习到的用户以及物品向量无法囊括时间的信息。在这篇论文里,作者们假定用户的隐向量,物品的隐向量都会随着时间的变化而变化,而在某一个时刻的物品评分仅仅是那一个时刻的用户隐向量和物品隐向量的一个结合。在传统的模型里,要描述这种隐向量随着时间的变化而变化的思路就会充满难度。
|
||||
|
||||
在这篇论文里,一个重要的贡献就是使用了一种叫 **LSTM**(Long Short-Term Memory)的RNN模型,来对这些用户的隐变量随着时间的变化而变化进行建模。我们在这里也不展开LSTM的基本定义。总体来说,LSTM也是对某一组输入变量和输出变量在时间上的关系进行建模,同时利用内部隐状态序列来对输入和输出变量进行建模。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我们聊了如何利用RNN对推荐系统中的时序信息进行建模。
|
||||
|
||||
一起来回顾下要点:第一,我们讨论了为什么对时序信息建模是非常必要的;第二,我们结合两篇论文,聊了利用RNN对时序信息建模的例子。
|
||||
|
||||
最后,给你留一个思考题,除了会话信息或者用户的喜好是比较明显的时序信息以外,推荐系统中还有哪些时序信息的应用呢?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
**参考文献**
|
||||
|
||||
1. Yehuda Koren. **[Factor in the neighbors: Scalable and accurate collaborative filtering](http://courses.ischool.berkeley.edu/i290-dm/s11/SECURE/a1-koren.pdf)**. ACM Trans. Knowl. Discov. Data 4, 1, Article 1 (January 2010), 24 pages, 2010.
|
||||
|
||||
2. Bal´azs Hidasi, Alexandros Karatzoglou, Linas Baltrunas, and Domonkos Tikk. **[Session-based recommendations with recurrent neural networks](https://arxiv.org/pdf/1511.06939.pdf)**. International Conference on Learning Representations (2016), 2016.
|
||||
|
||||
3. Chao-Yuan Wu, Amr Ahmed, Alex Beutel, Alexander J. Smola, and How Jing. **[Recurrent Recommender Networks](http://alexbeutel.com/papers/rrn_wsdm2017.pdf)**. Proceedings of the Tenth ACM International Conference on Web Search and Data Mining (WSDM '17). ACM, New York, NY, USA, 495-503, 2017.
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<audio id="audio" title="078 | 基于深度学习的推荐模型之三:利用深度学习来扩展推荐系统" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/72/93/726fa0de909fd8cfb1994fb0a01ec993.mp3"></audio>
|
||||
|
||||
这周,我们主要讨论如何利用深度学习来提升推荐系统的精度。我们分别介绍了使用RBM(Restricted Boltzmann Machines,受限波兹曼机)来对推荐系统建模,和RNN(Recurrent Neural Network,递归神经网络)在推荐系统中的应用。
|
||||
|
||||
今天,我们最后再来看一看,还有哪些深度学习的思潮在影响着推荐系统。这些思想都是一些值得关注和学习的方向,虽然这些方法能否在短时间内成为主流还有待检验。
|
||||
|
||||
## 多层神经网络
|
||||
|
||||
深度学习开始从计算机视觉这一人工智能子领域慢慢向其他领域扩展,在这个大背景下,很多学者和实践者总结出了深度学习获得成功的一大法宝,那就是**能够从众多的信息中学习到高维度的特性**(Feature)。比如,在计算机视觉里,通过多层神经网络建立的深度学习模型往往能够识别出类似“边”、“角”、“形状”等视觉概念。于是,大家就形成了这样一个普遍认识:**多层神经网络是一种提取特性的利器**。
|
||||
|
||||
和很多其他领域的思路一样,在推荐领域的学者也开始尝试利用多层神经网络对用户和物品的信息进行提取。这里面比较经典的思路是:直接利用**多层神经网络**,来尝试我们之前已经讲过的基于矩阵分解的推荐模型。
|
||||
|
||||
在矩阵分解的例子里,我们学习到的是用户的隐变量和物品的隐变量。这两者的点积成为评分的预测结果。在这个模型框架里可以认为,用户的隐变量和物品的隐变量是我们从数据中提取的特性信息。只不过,这种特性的提取是一种**线性变换**,而深度学习模型寻求的是**多层次的非线性变换**。
|
||||
|
||||
利用多层神经网络提取用户和物品特性的基本思路是这样的。
|
||||
|
||||
首先,我们的输入信息是用户的ID以及物品的ID。这里我们可以认为 **ID是高维的离散输入**。那么,根据这个输入信息,我们分别对用户和物品构建多层神经网络。这里比较常见的是至少有一层的神经网络,可以把离散的输入转换成为**连续的数据层**。
|
||||
|
||||
通常我们把这一层叫作“**嵌入层**”(Embedding)。嵌入层的基本思想是希望能够把离散信息转换成为连续信息,并且这些连续信息携带着“语义”(Semantic)上面的相似。什么意思呢?就是说如果两个用户是相似的,或者两个物品是相似的,那么我们就会寄希望于他们的嵌入层在数值上相近,这样嵌入层就能够很好地捕捉到用户和物品的相似度。
|
||||
|
||||
当用户和物品两边分别得到了嵌入层以后,输入信息已经完全变成了连续数据信息,通常的做法是把两边的嵌入层拼接在一起(也有把两个嵌入层取加权平均的做法),形成一个大的嵌入层。这个新的拼接层就成为连结了用户信息和物品信息的输入。
|
||||
|
||||
然后,接下来要做的,就是对这个新的输入进行多层的神经网络变换,最后输出我们对评分的预测。
|
||||
|
||||
总而言之,**直接利用多层神经网络对用户和物品的建模可以简单归纳为两步**:首先,把离散的ID信息转换成为连续的信息,形成嵌入层;然后,利用多层神经网络对嵌入层进行变换,并最后输出预测结果。
|
||||
|
||||
虽然利用多层神经网络在推荐系统上可以算是非常直观,然而在实际的效果中,我们其实并没有发现利用多层神经网络比矩阵分解要更好。如何能够更加有效地利用多层神经网络目前还是一个研究方向。
|
||||
|
||||
## 其他深度学习模型
|
||||
|
||||
除了直接利用多层神经网络来对推荐系统进行建模以外,最近也有不少把深度学习中其他思潮应用到推荐系统中的尝试。这里我也简单提及一些。
|
||||
|
||||
首先,在深度学习领域有一个技术叫作“**自动编码器**”(Autoencoder)。这个方法的核心思想就是希望能够无监督化地学习到某种信号的编码后的信息,并且编码后的信息能够再次通过解码尽可能地还原最初的信号。如果我们能够找到这样完美的过程,那么,在这个方法的假设里,我们就获取了更有价值的特性信息。
|
||||
|
||||
于是,把自动编码器思想应用到推荐系统的尝试,主要就是对用户以及物品进行编码。需要指出的是,我们刚才提到的直接使用多层神经网络的方法,其实也是某种意义上的编码,但我们这里提到的自动编码器的思想,还强调能够从学习到的隐含信息中还原最初的信息,也就是尽可能保持学习到的隐含变量的**可还原性**。这一点是多层神经网络所不具备的。
|
||||
|
||||
另外一个就是 **CNN(卷积神经网络)**的应用,学者和工程人员希望借助CNN来对用户和物品进行建模,从而扩展推荐系统的表现力。目前CNN在计算机视觉领域占据着举足轻重的地位,因此,很多人都希望能够直接把CNN的成功借鉴到推荐系统中。
|
||||
|
||||
和刚才我们介绍的直接使用多层神经网络建模的思路非常类似。一种常见的做法也是**直接利用CNN来提取用户和物品的信息**。通常的做法就是在我们刚才所说的嵌入层之后,不直接使用多层神经网络了,而是使用CNN来对嵌入层之后的信息进行变换。这里其实并没有太多创新的地方,基本上就是把视觉里面的模型拿来直接使用。
|
||||
|
||||
关于其他深度学习模型我们就说到这里,不做太多的介绍。原因是从总体上来看,深度学习在推荐系统上的应用,还是技术大于实际效果,目前并没有在太多的应用上有真正令人说服的成功案例。大多数情况是技术人员希望尝鲜,然后把一些成功的模型照搬到推荐任务上,虽然效果也不差,但从大的贡献来说,并没有太大的创新。
|
||||
|
||||
## 小结
|
||||
|
||||
今天我们继续讨论了如何利用深度学习模型来对推荐系统进行建模,我们聊了如何把深度学习的思路嫁接到推荐系统的开发中来。
|
||||
|
||||
一起来回顾下要点:第一,我们聊了一种最简单的应用,就是直接利用多层神经网络来对推荐系统进行扩展;第二,我们聊了一些其他的深度学习的思路,包括自动编码器和CNN,简单讨论了如何把这些深度学习模型应用到推荐系统中。
|
||||
|
||||
最后,给你留一个思考题,深度学习模型在推荐领域应用的最大问题,或者说最大挑战是什么?
|
||||
|
||||
欢迎你给我留言,和我一起讨论。
|
||||
|
||||
**推荐阅读**
|
||||
|
||||
- [深度学习 | 空竹里的秘密:自编码器](https://time.geekbang.org/column/article/3287)
|
||||
|
||||
|
||||
82
极客时间专栏/geek/AI技术内参/推荐系统核心技术/复盘 2 | 推荐系统核心技术模块.md
Normal file
82
极客时间专栏/geek/AI技术内参/推荐系统核心技术/复盘 2 | 推荐系统核心技术模块.md
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
到目前为止,我们讲完了人工智能核心技术的第二个模块——推荐系统。
|
||||
|
||||
整个模块共**21期**,**7大主题**,希望通过这些内容,能让你对推荐系统核心技术有一个全面系统的认识和理解,为自己进一步学习和提升打下基础。今天我准备了21张知识卡,和你一起来对这一模块的内容做一个复盘。
|
||||
|
||||
提示:点击知识卡跳转到你最想看的那篇文章,温故而知新。如不能正常跳转,请先将App更新到最新版本。
|
||||
|
||||
## 现代推荐架构剖析
|
||||
|
||||
推荐架构需要解决的问题:
|
||||
|
||||
- 能够在一两百毫秒内给用户提供当前的推荐结果;
|
||||
- 对用户和系统的交互结果做出响应;
|
||||
- 考虑用户群体的覆盖率的问题。
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/e0/c1/e02b1934236066a97ae36aef92c3bdc1.png" alt="" />](https://time.geekbang.org/column/article/5434)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/80/a7/807324f8294f096b4a65ae70186286a7.png" alt="" />](https://time.geekbang.org/column/article/5519)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/3e/ce/3e34f33d9a47d4038806f0c8bd701fce.png" alt="" />](https://time.geekbang.org/column/article/5571)
|
||||
|
||||
## 简单推荐模型
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/37/2e/374e49076df0afa906a16e9f1a358b2e.png" alt="" />](https://time.geekbang.org/column/article/4090)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/98/86/98450431d48596f62cc1c60d3ee46c86.png" alt="" />](https://time.geekbang.org/column/article/4212)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/1b/e0/1b653031c07f82369df5d908d0f283e0.png" alt="" />](https://time.geekbang.org/column/article/4278)
|
||||
|
||||
## 基于隐变量的模型
|
||||
|
||||
我们通过模型的假设,知道隐变量之间的关系,但暂时并不知道隐变量的取值。因此需要通过“推断”过程来确定隐变量的实际取值。当我们知道了这些隐变量的取值之后,就可以根据这些取值来对未来的数据进行预测和分析。
|
||||
|
||||
隐变量往往还带有“统计分布”的假设。最简单的隐变量模型是高斯混合模型。
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/56/24/569b83b19411ec553caab72f0345ea24.png" alt="" />](https://time.geekbang.org/column/article/4421)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/d2/20/d2a7fe56f96a98d3d5273eb6bdb81a20.png" alt="" />](https://time.geekbang.org/column/article/4484)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/5f/a3/5fb61d3a9985ad47cf788b1e8e9527a3.png" alt="" />](https://time.geekbang.org/column/article/4569)
|
||||
|
||||
## 高阶推荐模型
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/d5/d4/d533bf563525a8fc26bdb961f77e29d4.png" alt="" />](https://time.geekbang.org/column/article/4680)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/90/86/90272a06f9d37b463bbe82ff8d857986.png" alt="" />](https://time.geekbang.org/column/article/4764)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/9f/0d/9fedf4ca01b38e5b3ca3e0f7c0e6e60d.png" alt="" />](https://time.geekbang.org/column/article/4784)
|
||||
|
||||
## 推荐的Exploit和Explore算法
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/22/e0/2250834bcf534dc767c780b8a891cae0.png" alt="" />](https://time.geekbang.org/column/article/4881)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/27/6c/27273671a15d93715327d8a20845e06c.png" alt="" />](https://time.geekbang.org/column/article/4903)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/c2/c7/c288afc7d0e523ca292b9ba99b565ec7.png" alt="" />](https://time.geekbang.org/column/article/4915)
|
||||
|
||||
## 基于深度学习的推荐模型
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/ef/83/ef58f8151d6e56e3b21fcc0405d24683.png" alt="" />](https://time.geekbang.org/column/article/5624)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/33/45/3348cdce4fe739403ff5b35fbc9da345.png" alt="" />](https://time.geekbang.org/column/article/5646)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/cc/51/cc0b8806fa5afd1cb7d4c36b25586951.png" alt="" />](https://time.geekbang.org/column/article/5709)
|
||||
|
||||
## 推荐系统的评价
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/f2/76/f24271c6d95c4281e8ee67c79a46ec76.png" alt="" />](https://time.geekbang.org/column/article/5075)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/9e/08/9e1d29327ee87f7e45950aafcdcbc908.png" alt="" />](https://time.geekbang.org/column/article/5117)
|
||||
|
||||
[<img src="https://static001.geekbang.org/resource/image/f6/58/f6cf7cb2162520ccd2fb3f092cb37158.png" alt="" />](https://time.geekbang.org/column/article/5221)
|
||||
|
||||
## 积跬步以至千里
|
||||
|
||||
最后,恭喜你在这个模块中已经阅读了**45397字**,听了**138分钟**的音频,获得一张新的**通关卡**,这是一个不小的成就。在人工智能领域的千里之行,我们又往前迈出了一步。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/68/09/68086c922fbc5bd91dafc37811aef009.png" alt="" />
|
||||
|
||||
感谢你在专栏里的每一个留言,给了我很多思考和启发。期待能够听到你更多的声音,我们一起交流讨论。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user