LionKing数据科学专栏

购买普通会员高级会员可以解锁网站精华内容且享受VIP服务的优惠

想要查看更多数据科学相关的内容请关注我们的微信公众号知乎专栏

推荐系统(recommender system)

推荐系统介绍

推荐系统(recommender system; recommendation system)可以预测一个用户(user)对于一个项目(item)的评分(rating)或偏好(preference)。

推荐系统近年来获得了业界的广泛应用,并帮助用户更高效地匹配项目。推荐系统应用在以下场景中:

推荐系统的算法有两类:协同过滤(collaborative filtering)和基于内容的过滤(content-based filtering)。其中协同过滤算法根据用户过去的行为或评分,结合其它用户过去类似的行为或评分,用来预测该用户对新项目的评分。基于内容的过滤算法利用项目的属性元数据(metadata),如项目名字、文字说明、用户评价、项目照片等,寻找相似的其它项目。两者往往结合起来使用。

我们使用一个评分矩阵$R$来表示用户对项目的评分数据,其中$R$的每行代表一个用户,每列代表一个项目,矩阵的元素为缺失值或用户对该项目的评分。推荐算法的目标是填补该剧真的缺失值。

下表为一个评分矩阵的例子:

狮子王 悟空传 寻梦环游记 无人生还
Leo 5 2 ? 4
Jessica 2 ? 5 3
Shango ? 2 4 3
Conan 5 1 ? 3

获得评分数据的方式分为显式(explicit data collection)和隐式(implicit data collection)。

其中显式数据收集意味着数据是直接由用户提供的,例如:

隐式数据收集意味着数据跟用户行为有关,但不是直接由用户提供,而是通过用户行为推测(infer)得来的,例如:

对于推荐系统算法的评估(evaluation),可以使用均方根误差(root mean squared error),即将一部分数据隐藏作为测试数据,对这些测试数据进行预测,并计算预测值$\hat{r}$与真实评分$r$的误差的平方和,取平均并开根号:$$RMSE = \sqrt{\frac{1}{N_{test}}\sum_{i=1}^{N_{test}}(\hat{r}_i - r_i)^2}$$

协同过滤(collaborative filtering)介绍

协同过滤只使用评分矩阵$R$中的评分数据,而不使用用户或项目本身的信息。其核心假设是过去喜好类似的用户未来的喜好也一致;用户在未来仍喜欢与以往喜欢的项目所类似的新项目。

协同过滤的优点是不需要用户或项目本身的信息,因此对于如电影、音乐等复杂项目,协同过滤算法不需要处理这些复杂的数据就能够根据过往的评分数据进行预测。

协同过滤的缺点有:

协同过滤(collaborative filtering)算法

协同过滤的算法主要有基于用户(user-based)、基于项目(item-based)、基于模型(model-based)、混合方法(hybrid)。

基于用户协同过滤(user-based collaborative filtering)算法

基于用户的协同过滤有两个步骤:

  1. 寻找与当前用户喜好相似的其它用户
  2. 根据这些用户对当前项目的评分来预测当前用户对当前项目的评分

对于一个用户,该用户与其它用户的相似度(similarity)打分函数有诸多选择,最常见的有皮尔森相关系数(Pearson correlation similarity)和余弦相似度(cosine similarity)。对于用户$u$和项目$i$,我们选择对项目$i$进行评分的用户中与$u$的相似度最高的$K$个$u_1, \ldots, u_K$,并且通过这$K$个用户对$i$项目的评分$r_{u_1, i}, \ldots, r_{u_K, i}$和与$u$的相似度$s_{u_1, u}, \ldots, s_{u_K, u}$累计得到关于用户$u$对项目$i$的评分的预测。

皮尔森相关系数打分函数定义在两个用户$u, u'$上,假设用户$u$对所有已评分项目的平均评分为$\overline{r_{u, \cdot}}$,用户$u'$对所有已评分项目的平均评分为$\overline{r_{u', \cdot}}$,皮尔森相关系数打分为两个用户在同时评分的项目集合$I$上的评分分别减去各自的平均评分,并计算相关系数:

$$\rho(u, u') = \frac{\sum_{i \in I}(r_{u, i} - \overline{r_{u, \cdot}})(r_{u', i} - \overline{r_{u', \cdot}})}{\sqrt{\sum_{i \in I}(r_{u, i} - \overline{r_{u, \cdot}})^2}\sqrt{\sum_{i \in I}(r_{u', i} - \overline{r_{u', \cdot}})^2}}$$

余弦相似度为两个用户在共同评分的项目$I$上的评分对应向量的夹角余弦值:

$$\cos(u, u') = \frac{\sum_{i \in I}r_{u, i}r_{u', i}}{\sqrt{\sum_{i \in I}r_{u, i}^2}\sqrt{\sum_{i \in I}r_{u', i}^2}}$$

累计预测同样有不同的方法,以下为一些常见的方法:

基于项目协同过滤(item-based collaborative filtering)

基于项目的协同过滤与基于用户的协同过滤完全对称,只需要把用户和项目的角色互换,套用基于用户的协同过滤算法即可。实际数据中,基于项目的协同过滤结果往往好于基于用户的协同过滤结果,一种可能的原因是用户相对于项目更加多元化,因此与一个用户在过往项目上匹配的用户未必会在一个新的项目上匹配;而项目相对来说类型更单一,因此一个用户对于类似项目的喜好程度应当接近。

对于只是对一个用户推荐最可能感兴趣的$K$个项目的应用问题,还可以首先寻找与该用户相似度最高的若干个其它用户,然后对于其它用户喜爱的项目进行关联规则分析并基于其结果为该用户进行推荐。

基于模型协同过滤(model-based collaborative filtering)

基于用户和基于项目的协同过滤统称为基于记忆的协同过滤(memory-based collaborative filtering)在数据比较稀疏时效果较差,此时可以使用基于模型的协同过滤算法。基于模型的协同过滤算法使用机器学习算法对未评分的用户项目对进行预测,常见的方法有贝叶斯网络(Bayesian networks)、聚类(clustering)、隐性语义分析(latent semantic analysis)、马尔可夫决策过程(Markov decision process)。

基于模型的协同过滤算法的另一个好处是无需将大量数据放入内存读取,而只需要一小部分数据就可以进行预测。

例子

对于上文给出的评分数据,我们使用基于用户协同过滤、基于项目协同过滤、基于模型协同过滤分别进行预测。

基于用户协同过滤

我们使用皮尔森相关系数、相似度的加权平均值(按照平均项目评分调整)作为累计预测、选取$K = 2$,可以对4个缺失的评分进行如下预测:

  1. 首先将每个用户减去自己的平均评分得到矩阵为
    狮子王 悟空传 寻梦环游记 无人生还
    Leo 1.33 -1.66 ? 0.33
    Jessica -1.33 ? 1.66 -0.33
    Shango ? -1 1 0
    Conan 2 -2 ? 0
  2. 对于每两个用户计算评分公共部分的相关系数,如Leo和Jessica同时观看过"狮子王"和"无人生还",相关系数为$$\frac{1.33 \times -1.33 + 0.33 \times -0.33}{\sqrt{1.33^2 + 0.33^2}\sqrt{(-1.33)^2 + (-0.33)^2}} = -1$$类似可以计算其它用户之间的皮尔森相关系数如下:
    Leo Jessica Shango Conan
    Leo -1 0.9805 0.9819
    Jessica -1 0.9805 -0.9701
    Shango 0.9805 0.9805 1
    Conan 0.9819 -0.9714 1
  3. 利用以上信息可以预测缺失评分,以Leo和"寻梦环游记"为例,看过寻梦环游记的用户只有Jessica和Shango,两者减去自身平均评分后的评分分别为1.66和1,与Leo的相似度分别为-1和0.9805,因此Leo对"寻梦环游记"评分减去自身平均3.66的预测为$$\frac{1.66 \times (-1) + 1 \times 0.9805}{|-1| + |0.9805|} \approx -0.3464$$Leo对"寻梦环游记"评分的预测为$$3.66 + (-0.3464) \approx 3.3203$$类似也可以得到其它缺失评分的预测,以红色字体显示:
    狮子王 悟空传 寻梦环游记 无人生还
    Leo 5 2
    3.3203
    4
    Jessica 2
    3.8253
    5 3
    Shango
    4.6699
    2 4 3
    Conan 5 1
    2.6869
    3

Python代码如下:

需要购买普通会员高级会员登录后刷新该页面查看

基于项目协同过滤

基于项目协同过滤与基于用户协同过滤完全类似,我们仍使用皮尔森相关系数、相似度的加权平均值(按照平均项目评分调整)作为累计预测、选取$K = 2$,可以对4个缺失的评分进行如下预测:

  1. 首先将每个项目减去自己的平均评分得到矩阵为
    狮子王 悟空传 寻梦环游记 无人生还
    Leo 1 0.33 ? 0.75
    Jessica -2 ? 0.5 -0.25
    Shango ? 0.33 -0.5 -0.25
    Conan 1 -0.66 ? -0.25
  2. 对于每两个项目计算评分公共部分的相关系数,如"狮子王"和"悟空传"被Leo和Conan同时看过,相关系数为$$\frac{1 \times 0.33 + 1 \times (-0.66)}{\sqrt{1^2 + 1^2}\sqrt{0.33^2 + (-0.66)^2}} \approx -0.3162$$类似可以计算其它项目之间的皮尔森相关系数如下:
    狮子王 悟空传 寻梦环游记 无人生还
    狮子王 -0.3162 -1 0.4924
    悟空传 -0.3162 -1 0.4924
    寻梦环游记 -1 -1 0
    无人生还 0.4924 0.4924 0
  3. 利用以上信息可以预测缺失评分,以Leo和"寻梦环游记"为例,Leo还看过的电影有"狮子王"、"悟空传"、"无人生还",和"寻梦环游记"的相似度最高的2个为"无人生还"和"狮子王"("悟空传"并列,这里选择"狮子王"),相似度分别为0和-1,Leo对两者的减去项目自身平均后的评分分别为0.75和1,因此Leo对"寻梦环游记"评分减去"寻梦环游记"自身平均4.5的评分预测为$$\frac{0 \times 0.75 + (-1) \times 1}{|0| + |-1|} = -1$$Leo对"寻梦环游记"评分的预测为$$4.5 + (-1) = 3.5$$类似也可以得到其它缺失评分的预测,以红色字体显示:
    狮子王 悟空传 寻梦环游记 无人生还
    Leo 5 2
    3.5
    4
    Jessica 2
    2.2966
    5 3
    Shango
    3.7174
    2 4 3
    Conan 5 1
    3.5
    3

Python代码如下:

需要购买普通会员高级会员登录后刷新该页面查看

基于内容过滤(content-based filtering)介绍

基于内容过滤可以基于项目的元信息(metadata)和用户过去的行为建立的用户画像(user profile)。此类算法从项目中提取特征,在预测过程中比较新项目的特征和用户的历史项目特征,从而对用户对于新项目的喜好进行预测。

从项目中提取特征的步骤称为项目呈现(item presentation),例如可以使用tf-idf等方法将项目转换为向量(vector)。用户画像需要考虑用户偏好的建模和用户与各个项目的交互(interaction)历史。最简单的建立用户画像的方式为对用户过往喜爱的项目的特征向量取平均。

基于内容过滤算法的局限性是该算法不擅长推荐与之前用户接触过的项目不相似,但是用户可能喜欢的新项目。

常见面试问题

Q:基于记忆的协同过滤算法和基于模型的协同过滤算法相比较有哪些优缺点?

需要购买普通会员高级会员登录后刷新该页面查看

更多推荐系统相关问题见本网站论坛推荐系统版面

更多面试问题见面试真题汇总

想要查看更多数据科学相关的内容请关注我们的微信公众号知乎专栏