前言

随着信息技术和互联网的发展, 我们已经步入了一个信息过载的时代,这个时代,无论是信息消费者还是信息生产者都遇到了很大的挑战:
信息消费者:如何从大量的信息中找到自己感兴趣的信息?
信息生产者:如何让自己生产的信息脱颖而出, 受到广大用户的关注?
为了解决这个矛盾, 推荐系统应时而生, 并飞速前进,在用户和信息之间架起了一道桥梁,一方面帮助用户发现对自己有价值的信息, 一方面让信息能够展现在对它感兴趣的用户前面。 推荐系统近几年有了深度学习的助推发展之势迅猛, 从前深度学习的传统推荐模型(协同过滤,矩阵分解,LR, FM, FFM, GBDT)到深度学习的浪潮之巅(DNN, Deep Crossing, DIN, DIEN, Wide&Deep, Deep&Cross, DeepFM, AFM, NFM, PNN, FNN, DRN), 现在正无时无刻不影响着大众的生活。

推荐系统通过分析用户的历史行为给用户的兴趣建模, 从而主动给用户推荐给能够满足他们兴趣和需求的信息, 能够真正的“懂你”。 想上网购物的时候, 推荐系统在帮我们挑选商品, 想看资讯的时候, 推荐系统为我们准备了感兴趣的新闻, 想学习充电的时候, 推荐系统为我们提供最合适的课程, 想消遣放松的时候, 推荐系统为我们奉上欲罢不能的短视频…, 所以当我们淹没在信息的海洋时, 推荐系统正在拨开一层层波浪, 为我们追寻多姿多彩的生活!
image.png
所谓协同过滤(Collaborative Filtering)算法, 基本思想是根据用户之前的喜好以及其他兴趣相近的用户的选择来给用户推荐物品(基于对用户历史行为数据的挖掘发现用户的喜好偏向, 并预测用户可能喜好的产品进行推荐), 一般是仅仅基于用户的行为数据(评价、购买、下载等), 而不依赖于项的任何附加信息(物品自身特征)或者用户的任何附加信息(年龄, 性别等)。目前应用比较广泛的协同过滤算法是基于邻域的方法, 而这种方法主要有下面两种算法:

基于用户的协同过滤算法(UserCF): 给用户推荐和他兴趣相似的其他用户喜欢的产品
基于物品的协同过滤算法(ItemCF): 给用户推荐和他之前喜欢的物品相似的物品

基于用户的协同过滤

基于用户的协同过滤(UserCF)可以追溯到1993年, 可以说是非常早的一种算法了, 这种算法的思想其实比较简单, 当一个用户A需要个性化推荐的时候, 我们可以先找到和他有相似兴趣的其他用户, 然后把那些用户喜欢的, 而用户A没有听说过的物品推荐给A
image.png
基于用户协同过滤包括两个步骤:

  1. 找到和目标用户兴趣相似的集合
  2. 找到这个集合中的用户喜欢的, 且目标用户没有听说过的物品推荐给用户。

image.png
其实, 给用户推荐物品的过程可以形象化为一个猜测用户对商品进行打分的任务,上面表格里面是5个用户对于5件物品的一个打分情况,就可以理解为用户对物品的喜欢程度(这里多说一句,这种表格在实际情况中就是根据用户的行为进行统计出来的, 比如用户购买了某个物品, 那直接量化为5分, 用户收藏了某个物品, 量化为4分, 用户看某个物品很久量化为3分等, 通过这样的量化就相当于把每个用户对物品的行为刻画成了向量的形式, 我们就可以计算相似程度了), 我们的任务是判断到底该不该把物品5推荐给用户Alice呢?
如果是基于用户的协同过滤算法, 根据上面的算法步骤, 其实它会这么做:

  1. 首先根据前面的这些打分情况(或者说已有的用户向量)计算一下Alice和用户1, 2, 3, 4的相似程度, 找出与Alice最相似的n个用户
  2. 根据这n个用户对物品5的评分情况和与Alice的相似程度会猜测出Alice对物品5的评分, 如果评分比较高的话, 就把物品5推荐给用户Alice, 否则不推荐。

所以这个过程相信很容易理解了吧, 下面我们就尝试解决这个问题, 但是在解决之前, 还得先补充两个知识点: 第一个就是用户之间的相似性怎么衡量? 第二个就是选出了topn个与Alice最相似的用户来之后, 如果根据他们的相似程度和对物品5的分数计算Alice对物品5的分数?

计算两个向量的相似程度

机器学习中的相似性度量
1、杰卡德(Jaccard)相似系数
这个是衡量两个集合的相似度一种指标。 两个集合A和B的交集元素在A,B的并集中所占的比例,称为两个集合的杰卡德相似系数,用符号J(A,B)表示。
image.png
2、余弦相似度
余弦相似度这个很熟悉了吧, 它衡量了用户向量i ii和j jj之间的向量夹角的大小, 夹角越小, 说明相似度越大, 两个用户越相似。 公式如下:
image.png

  1. from sklearn.metrics.pairwise import cosine_similarity
  2. i = [1, 0, 0, 0]
  3. j = [1, 0.5, 0.5, 0]
  4. consine_similarity([a, b])

cosine相似度还是比较常用的, 一般效果也不会太差, 但是对于评分数据不规范的时候, 也就是说, 存在有的用户喜欢打高分, 有的用户喜欢打低分情况的时候,有的用户喜欢乱打分的情况, 这时候consine相似度算出来的结果可能就不是那么准确了, 比如下面这种情况:
image.png
这时候, 如果用余弦相似度进行计算, 会发现用户d和用户f比较相似, 而实际上, 如果看这个商品喜好的一个趋势的话, 其实d和e比较相近, 只不过e比喜欢打低分, d比较喜欢打高分。 所以对于这种用户评分偏置的情况, 余弦相似度就不是那么好了, 可以考虑使用下面的皮尔逊相关系数。
3、皮尔逊相关系数
这个也是非常常用的一种计算相似度的一种方式, 相比余弦相似度, 皮尔逊相关系数通过使用用户平均分对个独立评分进行修正, 减少了用户评分偏置的影响。简单的说, 其实pearson做的就是把两个向量都减去他们的均值, 然后再计算consine值。 用pearson来计算用户相似进行推荐的话, 效果还是好于consine的。公式如下:
image.png

  1. from scipy.stats import pearsonr
  2. i = [1, 0, 0, 0]
  3. j = [1, 0.5, 0.5, 0]
  4. pearsonr(i, j)

为什么在一些场景中要使用余弦相似度而不是欧式距离呢?
有些时候,我们其实并不关心两个向量的绝对大小,而是关注向量之间的夹角大小,此时就要用余弦相似度。 比如,当一对文本相似度的长度差距很大,但是内容相似时,如果是使用词频或者词向量作为特征,它们在特征空间中的欧式距离非常大,而使用余弦相似度的时候,可能很小,相似度高,这正是我们想要的。 此外,在文本,图像,视频领域,研究对象的特征维度往往很高,余弦相似度在高维情况仍然保持“相同时为1,正交时为0,相反时-1”的性质,而欧式距离的数值则受维度的影响,范围不固定,并且含义也比较模糊。不过,向量的模长归一化了之后,就成了皮尔逊相关系数了,这时候欧式距离与余弦相似度就有着单调关系了。
总体的来说,欧式距离体现数值上的绝对差异,而余弦距离体现方向上的相对差异。具体使用中,看需求决定。

  • 如果要统计两部剧的用户观看行为,用户A的观看向量(0,1), 用户B为(1,0), 此时二者的余弦距离很大,而欧式距离很小。我们分析两个用户对于不同视频的偏好,更关注相对差异,显然应当用余弦距离。
  • 而当我们分析用户活跃度,以登录次数和平均观看时长作为特征时, 余弦距离会认为(1,10)和(10,100)两个用户距离很近,但显然这两个用户活跃度是有着极大差异的。此时我们关注的是数值绝对差异,应当使用欧式距离。

    最终结果的预测

    这里常用的方式之一是利用用户相似度和相似用户的评价加权平均获得用户的评价预测, 用下面式子表示:
    image.png
    还有一种方式如下, 这种方式考虑的更加全面, 依然是用户相似度作为权值, 但后面不单纯的是其他用户对物品的评分, 而是该物品的评分与此用户的所有评分的差值进行加权平均, 这时候考虑到了有的用户内心的评分标准不一的情况, 即有的用户喜欢打高分, 有的用户喜欢打低分的情况。
    image.png

    优缺点

    User-based算法存在两个重大问题:
  1. 数据稀疏性

一个大型的电子商务推荐系统一般有非常多的物品,用户可能买的其中不到1%的物品,不同用户之间买的物品重叠性较低,导致算法无法找到一个用户的邻居,即偏好相似的用户。这导致UserCF不适用于那些正反馈获取较困难的应用场景(如酒店预订, 大件商品购买等低频应用)

  1. 算法扩展性

基于用户的协同过滤需要维护用户相似度矩阵以便快速的找出Topn相似用户, 该矩阵的存储开销非常大,存储空间随着用户数量的增加而增加,不适合用户数据量大的情况使用

基于物品的协同过滤

基于物品的协同过滤(ItemCF)的基本思想是预先根据所有用户的历史偏好数据计算物品之间的相似性,然后把与用户喜欢的物品相类似的物品推荐给用户。比如物品a和c非常相似,因为喜欢a的用户同时也喜欢c,而用户A喜欢a,所以把c推荐给用户A。ItemCF算法并不利用物品的内容属性计算物品之间的相似度, 主要通过分析用户的行为记录计算物品之间的相似度, 该算法认为, 物品a和物品c具有很大的相似度是因为喜欢物品a的用户大都喜欢物品c。
image.png
基于物品的协同过滤算法主要分为两步:

  1. 计算物品之间的相似度
  2. 根据物品的相似度和用户的历史行为给用户生成推荐列表(购买了该商品的用户也经常购买的其他商品)

还是前面的例子,基于物品的协同过滤步骤如下:

  1. 首先计算一下物品5和物品1, 2, 3, 4之间的相似性(它们也是向量的形式, 每一列的值就是它们的向量表示, 因为ItemCF认为物品a和物品c具有很大的相似度是因为喜欢物品a的用户大都喜欢物品c, 所以就可以基于每个用户对该物品的打分或者说喜欢程度来向量化物品)
  2. 找出与物品5最相近的n个物品
  3. 根据Alice对最相近的n个物品的打分去计算对物品5的打分情况

    优缺点分析

    上面说道UserCF存在两个问题, 数据稀疏性和算法扩展性问题, 而ItemCF算法因为物品直接的相似性相对比较固定,所以可以预先在线下计算好不同物品之间的相似度,把结果存在表中,当推荐时进行查表,计算用户可能的打分值,可以同时解决上面两个问题。在Item-to-Item论文中, 作者得出结论:

  4. Item-based算法的预测结果比User-based算法的质量要高一点。

  5. 由于Item-based算法可以预先计算好物品的相似度,所以在线的预测性能要比User-based算法的高。
  6. 用物品的一个小部分子集也可以得到高质量的预测结果。

    应用场景和存在问题分析

    应用场景

  7. UserCF

由于是基于用户相似度进行推荐, 所以具备更强的社交特性, 这样的特点非常适于用户少, 物品多, 时效性较强的场合, 比如新闻推荐场景, 因为新闻本身兴趣点分散, 相比用户对不同新闻的兴趣偏好, 新闻的及时性,热点性往往更加重要, 所以正好适用于发现热点,跟踪热点的趋势。 另外还具有推荐新信息的能力, 更有可能发现惊喜, 因为看的是人与人的相似性, 推出来的结果可能更有惊喜,可以发现用户潜在但自己尚未察觉的兴趣爱好。

  1. ItemCF

这个更适用于兴趣变化较为稳定的应用, 更接近于个性化的推荐, 适合物品少,用户多,用户兴趣固定持久, 物品更新速度不是太快的场合, 比如推荐艺术品, 音乐, 电影。
image.png

问题分析

这里分析一下协同过滤算法存在的共性问题, 协同过滤的特点就是完全没有利用到物品本身或者是用户自身的属性, 仅仅利用了用户与物品的交互信息就可以实现推荐,是一个可解释性很强, 非常直观的模型, 但是也存在一些问题。

  1. 较差的稀疏向量处理能力

第一个问题就是泛化能力弱, 即协同过滤无法将两个物品相似的信息推广到其他物品的相似性上。 导致的问题是热门物品具有很强的头部效应, 容易跟大量物品产生相似, 而尾部物品由于特征向量稀疏, 导致很少被推荐。 比如下面这个例子:
image.png
A, B, C, D是物品, 看右边的物品共现矩阵, 可以发现物品D与A、B、C的相似度比较大, 所以很有可能将D推荐给用过A、B、C的用户。 但是物品D与其他物品相似的原因是因为D是一件热门商品, 系统无法找出A、B、C之间相似性的原因是其特征太稀疏, 缺乏相似性计算的直接数据。 所以这就是协同过滤的天然缺陷:推荐系统头部效应明显, 处理稀疏向量的能力弱。
为了解决这个问题, 同时增加模型的泛化能力,2006年, 矩阵分解技术(Matrix Factorization,MF)被提出, 该方法在协同过滤共现矩阵的基础上, 使用更稠密的隐向量表示用户和物品, 挖掘用户和物品的隐含兴趣和隐含特征, 在一定程度上弥补协同过滤模型处理稀疏矩阵能力不足的问题。 具体细节等后面整理, 这里先铺垫一下。

  1. 无法利用更多的信息

协同过滤的特点就是完全没有利用到物品本身或者是用户自身的属性, 仅仅利用了用户与物品的交互信息就可以实现推荐,比较简单高效, 但这也是它的一个短板所在, 由于无法有效的引入用户年龄, 性别,商品描述,商品分类,当前时间,地点等一系列用户特征、物品特征和上下文特征, 这就造成了有效信息的遗漏,不能充分利用其它特征数据。
为了解决这个问题, 在推荐模型中引用更多的特征, 推荐系统慢慢的从以协同过滤为核心到了以逻辑回归模型为核心, 提出了能够综合不同类型特征的机器学习模型。
演化图左边的时间线梳理完毕:
image.png

总结

这篇文章的主要内容就是围绕着推荐系统比较经典的协同过滤算法进行的展开, 这个算法虽然比较古老了, 但是思想和原理还是值得我们研究研究的, 毕竟这个算法不依赖于任何物品本身或者用户自身的属性, 而仅仅靠用户和物品的交互信息就可以完成推荐任务, 所以还是非常powerful的, 并且后面的很多算法都是基于该算法存在的问题进行的改进, 比如矩阵分解算法, 解决了其泛化能力和稀疏能力弱的问题, LR或者GBDT+LR那些机器学习模型解决了无法利用其它用户属性, 物品属性和上下文属性的问题, 即使近几年的深度学习模型, 也都是在前面的那些模型上进行改进过来的。 如果把推荐系统模型的发展看成一棵树, 协同过滤算法可是当之无愧的根。

协同过滤算法比较常用的是基于邻域的方法, 主要包括UserCF和ItemCF, 这篇文章首先介绍了它们的原理,UserCF的基本思想是如果用户A喜欢物品a,用户B喜欢物品a、b、c,用户C喜欢a和c,那么认为用户A与用户B和C相似,因为他们都喜欢a,而喜欢a的用户同时也喜欢c,所以把c推荐给用户A。该算法用最近邻居(nearest-neighbor)算法找出一个用户的邻居集合,该集合的用户和该用户有相似的喜好,算法根据邻居的偏好对该用户进行预测。而ItemCF的基本思想是如果用户A, 用户B喜欢物品a, 物品c, 用户C喜欢物品a, 那么就认为物品a和物品c相似,因为用户C喜欢物品a, 所以也可以把物品c推荐给C。

然后从一个例子出发进行解释这两种算法,又通过了编程进行实现。 然后分析了它们各自的优缺点和应用场景, UserCF比较适用于实时性强的任务, 偏向于社会化推荐, 容易推进出新事物, 而ItemCF比较适合推荐兴趣比较固定的产品, 偏向于个性化推荐,推荐的大都类似产品。
image.png
协同过滤算法CF.pptx