推荐系统(Recommender systems)

推荐系统(Recommender systems)

​ 这里讨论推荐系统有两个深层原因或者说动机,第一个原因在于它是机器学习的一个重要应用,在过去的几年中在参观硅谷的各种科技类公司中,经常在那些公司里与开发机器学习应用的人交流,谈及什么才是机器学习最重要的应用,或者什么样的机器学习的应用是最想让它的表现得到改进的,最常听到的回答其中之一就是现在硅谷有好多个团队正试图建立更好的推荐系统。比如亚马逊、Netflix、eBay或者苹果公司的iTunes Genius做的事情,有很多网站或者很多系统试图向用户推荐新产品,比如说亚马逊会推荐新书,Netflix推荐新电影等等。这些推荐系统可能会看看你以前购买过什么书或者以前你给哪些电影进行过评分,这些系统贡献了现今亚马逊收入的相当大一部分,而对像Netflix这样的公司,他们向用户推荐的电影占了用户观看的电影的相当大一部分,于是一个推荐系统其表现的一些改进就能带来显著且即刻产生的影响这种影响关系到许多公司的最终业绩。

​ 第二个动机是我们已经在前面章节中看到对于机器学习来说特征量(features)的重要性,所选择的特征对于学习算法的表现有很大影响,在机器学习领域有这么一个宏大的想法就是对于一些问题而言存在一些算法能自动地替代人类学习到一组优良的特征量,即有些情形下能够采用一种算法来学习到使用什么特征量,而推荐系统就是这种情形的一个例子,还有其他很多例子但通过学习推荐系统我们将能够对这种学习特征量的想法有一点理解。

1.预测电影评分

​ 假想有一个影评网站,比方说允许评分在0颗星至5颗星之间,这里有5部电影《爱到最后》、《浪漫永远》、《小爱犬》、《无尽狂飙》还有《剑与空手道》,我们有4位用户名叫Alice,Bob,Carol和Dave。或称他们用户1、2、3和4,比方说Alice她非常喜欢《爱到最后》把它评为5颗星,她还喜欢《浪漫永远》也把它评为5颗星,她没看过《小爱犬》也就没评分这样我们没有这个评分数据,Alice很不喜欢《无尽狂飙》或是《剑与空手道》把它们评为0颗星。其他3位用户的的评价如下:

![1.jpg](http://wx3.sinaimg.cn/mw690/7b8d2108gy1fi15q6ccinj20h105vjry.jpg)
\(n_u\):表示用户的数目
\(n_m\):表示电影的数目
\(r(i,j)=1\):表示用户j对电影i做了评分(否则即为做评分时为零)
\(y^{(i,j)}\):用户j对电影i的评分(前提做了评分)
​ 推荐系统问题就是给定这些数据r(i,j)和y(i,j)数值,然后浏览全部数据,关注所有没有电影评分的地方,并试图预测这些带问号的地方应该是什么数值,在这个例子中电影数量很少用户数量也很少,大多数用户给大多数电影评过分,但在现实情况中网站的用户他们每个人可能只给很少一部分电影评过分,于是我们开发一个推荐系统主要工作就是想出一种学习算法能够帮我们自动地填上这些缺失的数值,这样我们对于用户还没看过哪些电影,然后向用户推荐新电影。

​ 首先介绍第一种构造推荐系统的方法,这种方法叫做“基于内容的推荐”(content-based recommendations)。应该如何预测这些缺少的问号评分值呢?假设对这些电影的每一部,都用一些特征来描述,具体来讲,假设每部电影有两种特征分别用x1和x2代表,x1表示这部电影属于爱情电影的程度,x2表示这部电影是动作电影的程度,因此对于电影《爱到最后》那么这部电影是爱情电影的比率为0.9,但是它属于动作电影的比率为0,《浪漫永远》爱情比率1.0,动作比率0.01,等等如下所示:

![2.jpg](http://wx4.sinaimg.cn/mw690/7b8d2108gy1fi15q6p781j20kt05q3ze.jpg)
​ 所以如果每部电影我们可以用一个特征矩阵表示,对于电影1《爱到最后》,两个特征值分别是0.9和0,这就是特征变量x\_1和x\_2分别对应于0.9和0,这里还是像以前一样加一个额外的特征变量截距x\_0其值为1。把三个特征变量放在一起,这样就有了特征$x^{(1)}$,这个上标括号(1)表示这是第一部电影的特征向量。对电影2《浪漫永远》我们有另外一个特征向量$x^{(2)}$等等,

​ 我们可以把对每个观众打分的预测当成一个独立的线性回归问题,具体来说,比如每一个用户j,我们都学习出一个参数\(\theta^{(j)}\)(这里是一个三维向量),然后要根据参数向量θ与特征\(x^{(i)}\)的内积来预测用户j对电影i的评分即\((\theta^{(j)})^Tx^{(i)}\)

​ 看一个具体的例子,对于用户1即Alice对应的参数向量就应该是\(\theta^{(1)}\),现在假如我们想预测Alice对电影《小爱犬》是如何评价的那么这部电影,有一个参数向量\(x^{(3)}\)等于[1,0.99,0],其中1是截距项,另外两个是特征0.99和0。假如说对于这个例子,已经知道Alice的参数向量\(\theta^{(1)}\)(后面会详细讲到如何获得这个参数)等于[0,5,0]。因此这两个向量的内积就等于5×0.99结果为4.95,故我们预测Alice得评分结果将为4.95。

​ 现在可以把这个问题写成如下更正式一些,用r(i,j)=1来表示用户j对电影i进行了评分,y(i,j)则表示用户j对电影i的评分值,\(\theta^{(j)}\)表示用户j对应的参数向量,\(x^{(i)}\)是某部电影i的特征向量,那么某个用户对某部电影的评分就是\((\theta^{(j)})^Tx^{(i)}\)

​ 现在临时介绍一个额外的表示符号\(m^{(j)}\),用来表示用户j评价过的电影数量,预测评分是一个基本的线性回归问题,因此我们要做的就是选择一个参数向量\(\theta^{(j)}\),使得预测的结果尽可能接近我们在训练集中的观测值。因此我们要关于\(\theta^{(j)}\)最小化下面这个求和值:\(min_{\theta^{(j)}}\left[\frac{1}{2m^{(j)}}\Sigma_{i:r(i,j)=1}((\theta^{(j)})^T(x^{(i)})-y^{(i,j)})^2+\frac{\lambda}{2m^{(j)}}\Sigma_{k=1}^n(\theta_k^{(j)})^2\right]\)

​ 对于推荐系统,这里把符号稍微简化一下,去掉常数项\(m^(j)\),去掉这一项不改变θ(j)的最优化结果,\(min_{\theta^{(j)}}\left[\frac{1}{2}\Sigma_{i:r(i,j)=1}((\theta^{(j)})^T(x^{(i)})-y^{(i,j)})^2+\frac{\lambda}{2}\Sigma_{k=1}^n(\theta_k^{(j)})^2\right]\)

​ 在构建推荐系统的时候我们也不想只对某一个用户学习出参数向量,我们想对所有的用户都学习出θ,因为有\(n_u\)个用户,所以希望学习出所有的参数,那么要做的是将上面这个最优化目标再加上一个求和:\(min_{\theta^{(j)}}\left[\frac{1}{2}\Sigma_{j=1}^{n_u}\Sigma_{i:r(i,j)=1}((\theta^{(j)})^T(x^{(i)})-y^{(i,j)})^2+\frac{\lambda}{2}\Sigma_{j=1}^{n_u}\Sigma_{k=1}^n(\theta_k^{(j)})^2\right]\) ,这里把想要最优化的项称为:\(J(\theta^{(1)},..., \theta^{(n_u)})\),同样地J还是我们要最小化的最优化目标函数。

3.jpg

​ 如果想要用梯度下降来求出这个J的最小值,可能会用到这些式子:

![4.jpg](http://wx3.sinaimg.cn/mw690/7b8d2108gy1fi15q7nqw9j20f9052q3e.jpg)
​ 事实上这里介绍的算法是线性回归的一个变体,用来预测不同用户对不同电影的评分值,这种具体的算法叫“基于内容的推荐”或者“基于内容的方法”。因为我们假设我们有不同电影的特征,比如电影的爱情成分有多少,动作成分有多少等等,我们就是用电影的这些特征来进行预测。

2.协同过滤(collaborative filtering)

​ 协同滤波算法能够自行学习所要使用的特征,在上一小节中的基于内容的推荐中,每一部电影都有明确的浪漫指数是多少,动作指数是多少,但细想可以知道这样做难度很大,花费时间很多,要让每个人看完每一部电影后说出每一部电影有多浪漫多动作是一件不容易的事情,而且通常除这两个特征之外的其他指数有很多。

​ 所以让我们转移一下问题,假如我们有一个数据集,但并不知道特征的值是多少,当我们得到一些不同用户对电影的评分,我们并不知道每部电影到底有多少浪漫的成分,或动作成分,于是把所有的特征都打上问号,如下图所示:

![5.jpg](http://wx3.sinaimg.cn/mw690/7b8d2108gy1fi15q8bwmtj20kt05qwf6.jpg)
​ 假设我们采访了每一位观影观众,而且每一位观众都告诉我们他们是否喜欢爱情电影以及他们是否喜欢动作电影,假如Alice告诉我们她十分喜欢爱情电影,于是Alice的特征x1对应的值就是5,而且她非常不喜欢动作电影,于是这一个特征就是0,类似的我们就是有和关于每个人的观影喜好参数θ如下:
![6.jpg](http://wx2.sinaimg.cn/mw690/7b8d2108gy1fi15q8ss90j20fs0350t4.jpg)
​ 那么现在我们在理论上就能推测出每部电影的特征值x1和x2,具体的,我们来看电影1《爱到最后》,我们已经知道的就是Alice喜欢这部电影,Bob喜欢这部电影,而Carol和Dave不喜欢它,我们从特征向量已经知道了Alice和Bob喜欢爱情电影,因为他们的θ参数说明了他们的爱好,相反Carol和Dave他们不喜欢爱情电影,而喜欢动作电影。考虑截距项部分,则第1部电影的特征向量为:$x^{(1)}=\begin{bmatrix}1\\ ?\\ ?\end{bmatrix}$。我们真正需要的是特征向量$x^{(1)}$应该是什么才能满足:$(\theta^{(1)})^Tx^{(1)}\approx5, (\theta^{(2)})^Tx^{(1)}\approx5, (\theta^{(3)})^Tx^{(1)}\approx0, (\theta^{(4)})^Tx^{(1)}\approx0$,由此可知$x^{(1)}$应该用[1,1.0,0.0]这个向量表示。

​ 更一般的,假设用户告诉了我们的偏好,即已经给我们提供了\(\theta^{(1)}\)\(\theta^{(n_u)}\)的值,而我们想知道电影i的特征向量\(x^{(i)}\),我们可以列出以下的最优化的问题:

![7.jpg](http://wx2.sinaimg.cn/mw690/7b8d2108gy1fi15q8xe2pj20ba01mjrc.jpg)
​ 所以现在要最小化上式(画拉线部分)得平方误差,通过选择特征$x^{(i)}$使我们预测的用户j对该电影i评分的预测值,跟我们从用户j处实际得到的评分值差值不要太大。和之前一样我们可以加上一个正则化项来防止特征的数值变得过大。

​ 我们要做的是学习出所有电影的所有特征,所以现在要做的是在此加上另外的一个求和,即对所有的电影n_m求和,然后最小化整个这个目标函数,针对所有的电影这样就会得到如下的最优化的问题:

![8.jpg](http://wx2.sinaimg.cn/mw690/7b8d2108gy1fi15q9ckzmj20ex01qdfs.jpg)
​ 如果将上式最小化的话就能得到所有电影的一系列合理的特征。

​ 上一小节“基于内容的推荐”算法讲的是,若有对一系列电影的评分,那么根据不同电影的特征\(x^{(1)},..., x^{(n_m)}\),我们可以得到参数θ。本节中我们主要讲的是如果用户愿意提供参数θ,那么可以为不同的电影估计特征。

​ 有点像先有鸡还是先有蛋的问题,如果我们能知道θ就能学习到x,相对的如果我们知道x也会学出θ,所以实际上应该随机猜θ的值,接着基于一开始随机猜测出的θ的值继而学习出不同电影的特征,给出已有的一些电影的原始特征,再运用上一个小节中讨论过的方法,得到对参数θ的更好估计,为用户提供更好的参数θ集,接着继续迭代,不停重复优化θ、x、θ、x、θ。算法将会收敛到一组合理的特征以及一组合理的用户参数的估计。

具体算法实现

​ 如果给出电影的几个特征,我们可以使用这些资料去获得用户的参数数据,如果给出用户的参数数据,那么可以使用这些资料去获得电影的特征,我们将它们合并成协同过滤算法(Collaborative Filtering Algorithm)。即不停地重复下面的式子的计算,随机地初始化这些参数,然后解出θ,解出x,解出θ,解出x...实际上存在一个更有效率的算法,不再需要像这样不停地计算x和θ,而是能够将x和θ同时计算出来。

![9.jpg](http://wx4.sinaimg.cn/mw690/7b8d2108gy1fi15q9xzs7j20kn04qabw.jpg)
​ 我们所要做的是将上式这两个优化目标函数给合为一个。因此,首先要定义新的优化目标函数J,它应该依然是一个代价函数,是关于特征x和参数θ的函数,上式中的第一个求和运算(蓝色圈住内容)是关于所有用户J的总和,意思是对每个用户关于该用户评分的电影的求和,而下面的求和运算(红色圈住内容)只是用相反的顺序来计算关于每部电影i,所有曾经对它评分过的用户j的评分求和,因此这两个式子其实下面黑色方框所圈内容。
![10.jpg](http://wx1.sinaimg.cn/mw690/7b8d2108gy1fi15qay4u6j20qb03tdhb.jpg)
​ 然后这个新的优化目标函数里关于θ的正则化,它有一个很有趣的特性,假设x为常数并关于θ优化的话,反过来也一样,如果把θ作为常量,然后关于x求J的最小值的话那就与第二个式子相等,所以这里是一个将x和θ合并起来的代价函数。

​ 此外,当我们以这样的方法学习特征量时,之前的前提是我们所使用的特征x0(即截距量)等于1,当我们以这种形式去学习特征量时,我们必须要去掉这个截距量,我们这里移除的理由是:我们没有必要去将这个等于一的特征值固定,因为如果算法想要的话,可以将特征值x1设为1,所以没有必要去将1这个特征定死,这样算法有了灵活性去自行学习。

​ 总结一下,首先我们会把\(x^{(1)},...,x^{(n_m)}\)\(\theta^{(1)},...,\theta^{(n_u)}\)初始为小的随机值,接下来我们要用梯度下降或者某些其他的高级优化算法把这个代价函数\(J(x^{(1)},...,x^{(n_m)}, \theta^{(1)},...,\theta^{(n_u)})\)最小化,梯度下降法写出来的更新公式如下:

![11.jpg](http://wx1.sinaimg.cn/mw690/7b8d2108gy1fi15qcncuhj20b803aglr.jpg)
​ 最后,若给你一个用户如果这个用户具有一些参数θ,以及给你一部电影带有已知的特征x,我们可以预测这部电影会被给出怎样的评分:$\theta^Tx$。

3.协同过滤算法的向量化实现

​ 我们有五部电影的数据集(如下图),首先将要做的是将这些用户的电影评分进行分组并存到一个矩阵中,我们共有五部电影以及四位用户,那么这个矩阵Y就是一个5行4列的矩阵,它将这些电影的用户评分数据都存在矩阵里,包括问号标注出的。

![1.jpg](http://wx4.sinaimg.cn/mw690/7b8d2108gy1fi1t8h3zibj20hs051q39.jpg)
​ 具体地,某位用户预测某部电影的评分可以按下面这个公式计算,就是用户j对电影i的预测评分对应(i,j)位置的数据,准确说来其值等于$(\theta^{(j)})^Tx^{(i)}$,故矩阵中的第一个元素是第一位用户对第一部电影的预测分数,第一行第二列的元素的预测评分是第二位用户对第一部电影的打分等等。
![2.jpg](http://wx3.sinaimg.cn/mw690/7b8d2108gy1fi1t8hjzgyj20f104ft9z.jpg)
​ 这里给出一个更简化的向量化的方法,具体来说,定义矩阵X等于$x^{(1)}$转置$x^{(2)}$转置一直到$x^{(n_m)}$的转置,即每一部电影的特征按行堆叠起来,我们要做的是再定义一个大写的Θ矩阵,将每一位用户的参数向量$\theta^{(j)}$也按行堆叠起来,为了能有一个向量化的方法以计算这些矩阵的预测值,我们可以计算X矩阵乘Θ矩阵的转置(即$X\Theta^T$),这就给出了一种更简化的向量化的方法。协同过滤算法还有另外一个名字:**低秩矩阵分解**(Low Rank Matrix Factorization)
![3.jpg](http://wx2.sinaimg.cn/mw690/7b8d2108gy1fi1t8i0gd1j20ep03o3yn.jpg)
​ 协同过滤算法有个很好的应用,假如有一部电影i,你想找到与电影i类似的某部电影j,我么利用协同过滤算法到对特征参数向量进行学习,就会有一个很方便的方法来度量两部电影之间的相似性,例如说电影i有一个特征向量$x^{(i)}$,这时问题关键在于否能找到一部不同的电影j保证两部电影的特征向量之间的距离$x^{(i)}$和$x^{(j)}$很小,即($small||x^{(i)}-x^{(j)}||$),距离越小那就越有力表明电影i和电影j的相似性,至少在某种意义上某些人喜欢电影i或许更有可能也对电影j感兴趣。

​ 本节最后谈一谈均值归一化(Mean Normalization),它可以让协同滤波算法算法运行得更好。

​ 首先我们了解均值归一化这个想法的动机,还是之前的电影评分的例子,考虑一下有一个用户没有给任何电影评分,即第五个用户Eve她没有给任何电影评分,我们来看看协同过滤算法会对这个用户做什么。

![4.jpg](http://wx4.sinaimg.cn/mw690/7b8d2108gy1fi1t8ig1ezj20n004w75l.jpg)

5.jpg

​ 假如n等于2,即我们要学习两个特征变量还要学习出一个参数向量\(\theta^{(5)}​\),任然提醒一下,这个向量是n维的而不是n+1维的,根据优化函数,用户Eve没给任何电影打过分,所以对用户Eve来说没有电影满足r(i,j)=1这个条件,所以优化函数中的第一项(与实际评分差)完全不影响\(\theta^{(5)}​\)的值,所以影响\(\theta^{(5)}​\)值的唯一一项是最后的正则化项,优化的目的是尽可能地让正则化项小,换句话说我们想要最小化\(\frac{\lambda}{2}[(\theta_1^{(5)})^2+(\theta_2^{(5)})^2]​\),所以最终得到的就会是\(\theta^{(5)}​\)=[0;0]。

​ 因为正则化项会让你的参数接近0,如果没有数据能够使得参数远离0,那么就会得到\(\theta^{(5)}\)等于零向量。所以当我们要预测用户5给电影打分结果,有\((\theta^{(5)})^Tx^{(i)}\),易见对任意i结果都会等于0,因此我们根据结果会预测Eve给所有电影的评分都是零星,这个结果我们还是没有任何好方法来把电影推荐给她,因为预测结果是所有这些电影都会被Eve给出一样的评分,没有一部电影拥有高一点儿的预测评分让我们能推荐给她。

​ 均值归一化的想法可以让我们解决这个问题,把所有这些评分全部整合到矩阵Y中,全部是问号的这列对应着Eve没有给任何电影评分。为了实现均值归一化,首先计算每个电影所得评分的均值,把它们存在一个向量µ中,接着重新定义Y矩阵,将Y的每一列减去向量µ重新更新每一列,这样把每个电影都归一化为平均评分为零,当然未打分的这些问号没变。

![6.jpg](http://wx4.sinaimg.cn/mw690/7b8d2108gy1fi1t8jjzgrj20kx03mwfx.jpg)
​ 接下来对这个评分数据集使用协同过滤算法,做电影评分预测,由于预测结果的计算为:$(\theta^{(j)})^Tx^{(i)}$,但是有一点不同,因为之前已经对数据集减去了均值,所以为了给电影i预测评分要把这个均值加回来,即实际预测值应为:$(\theta^{(j)})^Tx^{(i)}+\mu_i$。

​ 因为Eve从来没有给任何电影打分,所以学习到的用户5的参数仍然还是零向量,这样我们预测Eve的评分是\((\theta^{(5)})^Tx^{(i)}+\mu_i\),所以如果学习的等于0的话,对电影i的评分我们最终会预测为µi,即对于电影1我们会预测Eve对它的评分是2.5,对于电影2我们会预测Eve给它2.5星,对于电影3我们会预测Eve给它2星等等。我们就对这个新的观影用户Eve一无所知,我们预测她对每个电影的评分就是这些电影所得的平均评分,就是这些电影所得的平均评分。

posted @ 2017-07-29 23:15  SrtFrmGNU  阅读(2514)  评论(0编辑  收藏  举报