【推荐算法】从架构到原理学习推荐(上)

前言

        推荐是算法领域一个比较有趣且自由度很高的玩法,其解决问题的本质是“给什么样的user推荐什么样的item”,因此建模也是往这个思路去走,当然这里的user和item概念可以互换或升华。工业上不同企业所用的推荐系统架构也不尽相同,本文介绍的是一套工业上比较基础的三层式架构:召回+排序+过滤。本文会通俗介绍所有概念,会涉及一些数学知识和算法原理,下一章再讲解代码实战,欢迎各位一起交流并指出不足之处,感谢!

1 推荐的定义

狭义上的推荐: 给用户(User)推荐项目(Item),挖掘用户可能喜欢的项目展示给用户。
广义上的推荐: 将推荐的主体和客体进行升华,主体和客体可以任意选择,如给项目推荐用户,给用户推荐用户等。值得注意的是,用户和项目也可以根据场景里不同的实体进行变换,如给用户集(如包含多个用户的群组)推荐项目等,给用户推荐项目集(如包含多个地点的行程)等

2 推荐的架构

        如前面所提,我们用三层式架构:召回+排序+过滤,流程图如下在这里插入图片描述
        现在我们假设要从9999个商品里面推荐10个给小明,以此场景来帮助理解上述整个每部分的作用:
        1)item全集: 被推荐对象的全体,即9999个商品;
        2)召回算法: 我们知道9999个商品相对是很大的数字,召回算法相当于第一层“漏斗“,能初步筛选出一些较为符合小明的商品,设从9999里面挑出200个;
        3)排序模型(排序算法): 商品规模从召回算法出来就降低到200了,但依然相对较多,那么排序算法相当于第二层”漏斗“,帮我们计算小明购买这200个商品的概率,在本文这个架构里面,所做的特征工程和时序打标签方法构造出来的模型就是解决“什么样的人购买什么样的商品的概率是多少”并从高到低排序;
        4)业务过滤: 理论上排序算法给我们的结果里面从高到低选10个推荐给小明就OK了,但可能这10个最高的商品未必符合实际的业务场景,如这10个商品小明已经购买过5个了,短期内不会再购买,那么我们在短期内不应该推荐重复的商品给他,业务过滤就是为了满足这些业务要求而设置的第三层”漏斗“;
        5)推荐结果: 经过上述过程,就能获得最后的推荐结果了,我们可以进行评价指标的计算,衡量推荐效果,提供算法优化的依据。
        以上是推荐系统架构的大致概括,能初步理解这个过程后,接下来详细介绍各层”漏斗“,包括算法原理,数据的形式变化及流向等。

3 分步理解

        依次解释召回算法,排序算法,业务过滤这三部分内容

3.1 召回算法

        实际上常说的推荐算法通常指的就是召回算法(这里的召回和有监督学习里面的召回是完全不同的概念),仍然回到刚才小明推荐的场景,召回算法解决的是从9999个商品找出200个小明可能喜欢的商品,但是不同的召回算法得出来的200个商品也是不同的,通常这个阶段可以只用一种算法,也可以用多种算法实现多路召回,即多种召回算法的结果组合起来构成这200个商品。本文介绍几种经典的算法来实现召回

3.1.1 基于用户的协同过滤(UserCF)

        相信协同过滤这个词(collaborative filtering)有些朋友也听到烂了,通俗来说它的定义就是:小明喜欢一批商品,那么我会看看有哪些人跟小明一样喜欢这些商品的,认为这些人和小明是具有相同的喜好,再把这些人喜欢过的商品(小明还没喜欢过或接触过的)推荐给小明。程序就是这样的程序,具体的”喜欢“怎么衡量呢?
我们需要这样的数据:
在这里插入图片描述
        这是一个评分矩阵,通常由埋点数据或其他原始数据经过处理而得到,这里以0-5评分制为例,0代表这个人还没点击过这个商品,1-5可以按照从点击到购买成功这个行为路径去划分,5分就是购买成功(当然你也可以用0-10分制),常用的还有0/1制,即只要购买了就是1,其余均为0。这个矩阵就能反映一个人的喜好了,如小明的喜好就是[5,3,0,5,5],小军[5,4,0,4,5],显然这是两个向量,两人的相似度就可以用向量间的夹角来衡量,这样的相似度称为余弦相似度,公式为:
在这里插入图片描述
        还可以用其他方式来计算相似度,如:皮尔逊相关系数,闵氏距离,杰卡德相似系数,曼哈顿距离,汉明距离等,总之,相似度越大,两人的爱好越接近。
        通过上面的评分矩阵和相似度计算公式,是不是可以计算任意两人间的相似度了?再画成一个表格:
在这里插入图片描述
        这个就是相似度矩阵,我就偷懒不一一计算了,省略号就是具体的相似度,每个人与自身的相似度肯定是最大的,我们要置为0。然后按照相似度矩阵可以找到与小明最接近的n个人,假设小红和小军与小明的爱好最接近,商品也足够多的时候,那么就可以从小红、小军中选择4分(自己定)以上且小明对应为0分的商品作为小明的推荐列表了,这个就是UserCF所做的事,回到我们之前的场景中,在9999个商品中就可以给小明召回200个商品,当然一些特殊情况比如小明已经购买过9900个商品了,只有99个0分的,那么可以自行设计解决方案,可以补齐到200个商品,也可以只召回99个等等。

3.1.2 基于物品的协同过滤(ItemCF)

        能理解上面的UserCF,ItemCF就很好理解了,在刚才的评分矩阵中我们是将每一行看作是一个向量的,现在,同样的评分矩阵,我们将每一列看作一个向量:
在这里插入图片描述
        如item1就是[5,5,5,0,0],每个item的向量就衡量出它在人群中的地位了,又到了喜闻乐见的计算相似度环节,计算任意两个item之间的相似度矩阵:
在这里插入图片描述
        这个相似度矩阵的物理意义就是用各个item在人群里的表现来衡量任意item的接近程度,在原来的评分矩阵中,小明的向量是[5,3,0,5,5],即小明对item1, item3, item5都是很喜欢的,对这三个item,是不是可以在上述item相似度矩阵中找到与之最接近的n个item呢?答案是肯定的,如果item足够多,那么n可以等于200,就作为小明的推荐列表了,这就是ItemCF所做的事。
        以上就是两种协同过滤的原理,协同过滤可以说是最经典的推荐算法,你们可能已经发现:UserCF倾向于社会化,为你找到与你接近的群体,ItemCF则倾向于个性化,帮你找到你自己会喜欢的那一类物品。如果你是产品经理,看到这里可以跳过后续的几个算法,快速浏览后面的排序算法、业务过滤,了解整个系统运作即可;如果你是数据挖掘工程师,不妨集中精神继续看完接下来的几个召回算法。

3.1.3 传统矩阵分解(MF)& SVD & SVD++

        矩阵分解(Matrix factorization)的思想和协同过滤完全不同,我们看一下评分矩阵:
在这里插入图片描述
        前面提过矩阵中为0的表示这个人还没接触过这个商品,但实际小明喜不喜欢这个商品,我们是不知道的,换句话说,小明对于item3将会有一个具体的分数,只是我们目前不知道而已,那我们能不能预测出这个分数呢?是肯定的,为了方便理解,先把矩阵中为0的格子换成问号:
在这里插入图片描述
        矩阵分解可以计算出上面所有问号的近似值,是很纯粹的数学问题。我们知道两个矩阵相乘能得到一个新的矩阵,反之,一个矩阵也可以分解成两个矩阵相乘:
在这里插入图片描述
        一个评分矩阵分解成两个矩阵后,分别表示用户隐因子矩阵P、项目隐因子矩阵Q,什么意思呢,解释起来会比较复杂,我的理解如下:

        你对《泰坦尼克号》的喜爱程度是5分,矩阵分解后,用户隐因子矩阵P表示的是其他用户有几分像你,项目隐因子矩阵Q表示其他电影有几分像《泰坦尼克号》,从而加权组合计算得出所有人喜欢每个电影的程度。

        因此矩阵分解的过程就是拟合出这两个子矩阵的过程:
在这里插入图片描述

算法思路:

  1. 初始化左矩阵P 及 右矩阵Q, 赋予随机值
  2. 构造目标函数C = 评分矩阵 - 左矩阵 x 右矩阵
  3. 利用梯度下降法求解, 设定步长及结束条件:
    达到最大迭代次数 C足够小 C变化足够小
  4. 利用步长更新左右矩阵
  5. 迭代结束后: 评分矩阵 ≈ 左矩阵P x 右矩阵Q
  6. 原评分为0的位置得到非0值, 作为预测分数
  7. 将预测分数从高到低取n个作为召回

        可以不用理解,知道结论即可:评分矩阵A可以分解成两个子矩阵,两个子矩阵再相乘一次得到近似矩阵A′≈A,其中A′ 把A的0值计算出来了,且两个矩阵的非0值是非常接近的,有理由认为0值计算出来的就是预测值,评分矩阵就解出来了,即可从高到低把预测分数高的200个物品推荐给小明。
        矩阵分解的变种还有SVD奇异值矩阵分解和SVD++,SVD是对传统矩阵分解的一个变种,把一个评分矩阵分解成三个子矩阵,中间矩阵反映的是分解后能还原为原矩阵的程度,计算公式和思想不同,但形式上都是希望把0值计算出来。SVD++在 SVD 模型的基础上融入用户对物品的隐式行为,认为 评分=显式兴趣 + 隐式兴趣 + 偏见,在计算0值时会加入该用户对于所有物品的评分与全体用户平均水平的差异,例如它发现你大部分平分都比平均值低0.5分,那么在计算你对新物品的喜欢程度时,额外减去0.5分,这相当于加入了”大胆的猜测“作为偏置值,因此SVD++计算耗时十分漫长,有时会因为过于”大胆“而使效果更差,因此实际使用不多。

3.1.4 贝叶斯个性化排序(BPR)

        BPRMF也是一种矩阵分解,但它是基于BPR这种思想来实现的矩阵分解,因此和传统矩阵分解区分开来。假设小明喜欢的物品集合是I,其余物品集合是J,显然评分表现上是Ui>Uj的,为了求出具体的评分,传统矩阵分解训练的过程是为了拟合一组参数矩阵P和Q,来预测出小明对J集合的评分,BPR的训练过程则是为了拟合一组参数矩阵W和H,来最大化小明对I和J两者评分的差距,即求概率P(Ui>Uj)时,W和H的值,求出后两矩阵相乘后得到的矩阵是用户对任意商品的排序分,从高到低选择推荐即可。下面给出无数学公式的算法思路,参考于刘建平老师的博客,有兴趣的同学可以去详细学习原理:传送门
        损失函数L:
在这里插入图片描述

算法思路:
输入:训练集D三元组,梯度步长α, 正则化参数λ,分解矩阵维度k
输出:模型参数,矩阵W,H
1.随机初始化矩阵W,H ;
2.迭代更新模型参数 (损失函数是越来越大的);
3.如果W,H收敛,则算法结束,输出W,H,否则回到步骤2.
4.当拿到W,H后,就可以计算出每一个用户u对应的任意一个商品的排序分;最终选择排序分最高的若干商品输出

3.1.5 基于词向量的召回(word2vec)

        NLP领域也能用来做推荐召回,其思想很直观明了,我们知道一篇文章里面的关键词往往和文章主题有关,换言之,同一个主题的文章,关键词往往接近甚至一样,再换言之,同一主题的文章的关键词,往往捆绑出现,理解这个思想后,我们来看看怎么将词向量用于推荐。
        我们升华一下,同一主题的文章看成是同一类用户,文章里面出现的关键词看成是用户喜欢过的物品名称,也就是说同一类用户喜欢的物品,往往捆绑出现,比如小明和小军是同类人,小明按时间先后购买的物品集合是 [球衣,足球,足球鞋,长袜,护板] ,小军按时间先后购买的物品集合是 [哨子,足球,足球鞋,护板],显然这类用户喜欢的物品有一个捆绑出现的关系,那么来了一个新用户小王,他的行为数据表现出对 足球鞋 的喜欢,根据小明和小军的表现来看,如果只推荐1个商品,可以推 “足球”或“长袜” ,足球往往在足球鞋之前被购买,长袜往往在其之后被购买,因此向前或向后推荐均可;如果我们要推荐2个商品,那么可以推球衣,足球,哨子,长袜,护板中的任意2个,依然是向前或向后均可,这里推荐1个或2个就是一个窗口概念,窗口越大,推荐范围越大,捆绑关系越不明显,反之越小,捆绑关系越强。这个特例明白的话,就推广一下概念,成千上万的用户,每个用户各自喜欢的商品集合按时间先后排序,训练一个模型,那么这个模型就描述了这个人群里面的捆绑关系,此时来了一个新人,一旦他表现出对某个商品的喜欢,模型就可以根据该商品去寻找捆绑的其他商品推荐给他。这是通俗的解释,技术一点的语言概括就是:把用户一列行为看成文本,商品就是单词,利用nlp技术计算每个词(商品)的向量,这样可以衡量商品之间的相似度。利用用户历史购买记录,推荐相似的商品。这就是word2vec词向量模型所做的事。
        比较经典的几个召回算法介绍完了,它们是并列的,多选一的关系,回到一开始的场景,从9999个商品召回200个给小明的任务就完成了,当然如果你希望召回的结果作为最终推荐结果,那么可以不需要后面的排序算法,把200设置为10个即可。

3.2 排序算法

        推荐的评价指标中有一些指标是会衡量推荐的顺序的,如MAP,MRR,这些指标在单纯的召回算法中无法体现,因为召回算法仅告诉我们用户可能购买的物品,但无法得知购买的概率,并且上面提到的召回算法都和只用到了用户的行为信息数据,没用上关于商品和用户的相关属性,依然存在很大的提升空间,这就需要第二层“漏斗”——排序算法。
        排序算法实际是一个有监督学习里面的分类任务,既然如此,我们就用分类中效果比较不错的新秀——LightGBM来解决问题(Xgb也是可以的),简便,轻盈,快速,还能输出概率值,这里不赘述它的原理,有兴趣的同学自行了解,我们直接上用法。
        每个被推荐的用户从召回算法出来后都有200个适合他的物品,接下来讲一下建模思路,设原始数据是1-4月份的行为数据:
在这里插入图片描述

        1-3月份的数据经过召回算法处理得到召回结果,与用户信息表关联并做特征工程,用4月分的数据为其打标签,会得到如下训练集:

在这里插入图片描述
        然后训练模型,把User_name及Item_name两列盖住,不难发现模型学习的本质是“具有某某属性的用户会购买某某特征的物品”,这个模型就能很好地解释了当前数据集里面人群的购买习惯;调参,输出概率值,即为用户购买某商品的概率了,从高到低选取10个推荐结果即可。

3.3 业务过滤

        到此为止我们已经推送了10个小明最有可能购买的商品了,但是考虑到推荐的周期性(不可能只运行一次对吧),因此可以结合我们的业务需求去设计一些业务规则,如:用户购买过同样商品后需要多久后才继续推荐这个商品(即使模型算出来的概率很高);或者同样商品在连续几个推荐周期内重复推荐,用户仍没有购买,我们就不能强人所难了,诸如此类的规则。业务过滤实现方法很多,可以SQL定期构建重复商品表,排序后的推荐结果与此表关联过滤再进行推荐,等等。
        另外还有一些冷启动和新用户等问题的处理方案,不同场景处理方法不同,可以做一些处理并加入到算法里面,也可以单独走另一套流程,如创建热榜规则,对新用户只推热榜商品,或对活跃用户推送新商品,好处是对于活跃用户或热门商品来说,将新商品/新用户与之联系能快速产生交互数据,方便后续的推荐使用。

4 评价指标

        最后我们希望衡量整体推荐效果如何,推荐上有几个常用指标:

PRE精确率: 推荐的基金中, 被用户”喜欢”的部分占推荐数的比例, 取值范围[0,1]
REC召回率: 推荐的基金中, 被用户”喜欢”的部分占用户所有”喜欢”的比例, 取值范围[0,1]
F1: 与机器学习一样, 综合考虑了PRE和REC的值
HR命中率: 被推荐的用户中有”喜欢”的人数占总用户数
MRR平均排名: 推荐列表中, 用户”喜欢”的第一个基金的排名的倒数, 越大越好
MAP平均精度: 推荐列表中, 每个用户”喜欢”的基金的排名倒数之和的平均值

        计算公式直接借用其他大佬总结的图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
        第一类指标关心用户想要的,我有没有推荐到,强调语文里的“准确性”,分别为Precision@K、Recall@K、F1@K、HR@K ; 第二类指标更关心找到的这些项目,是否放在用户更显眼的位置里,即强调“顺序性”,分别为MRR@K、MAP@K。实际上常用的是PRE、REC、MRR和MAP,其中对于后两个考虑顺序的指标来说,通常数值会比较低,且波动较大,而REC在用户浏览记录很多但推荐数目较少时,得分会非常低,因此如果对于推荐效果要求并非十分严格的系统,PRE能更好反映推荐质量。

纯手打,肝了一段时间终于写完,本系列的下一篇将用代码实战去实现这套系统,如果觉得对自己有帮助,请点赞收藏加关注O

猜你喜欢

转载自blog.csdn.net/a7388787/article/details/109184324