前言:本文章主要讲述本人在工作期间做的推荐系统工作,主要内容是从零开始构建一个可用的推荐系统,其中包括实时,离线两部分。笔者其实是第一次从零实现一个全面的推荐系统。本文章会记录下在开发过程中的技术细节,以及对推荐系统的一些看法。在笔者开发的过程中,很多的技术点其实都是现学现用的,难免会有不足和错误,希望读者在阅读过程中,如有发现,希望指出。
推荐系统从互联网时代开始便有相关技术,并且在演进过程中诞生了不少的经典算法,比如协同过滤CF,隐语义矩阵分解,personal rank等等。当然,这些算法随着大数据时代的到来变得更为出名,并且,随着深度学习时代的到来(大概是2012到2014年)的到来,基于神经网络的推荐系统也进一步发掘出来,产业化也逐渐出现,在这方面最出名的研究应当是Google的Deep Neural Networks for YouTube Recommendation(2016年论文),大概在这个时候,深度学习便在推荐系统中大行其道。而这几年,又出现了强化学习应用到推荐系统的相关研究。
笔者开发的推荐系统是面向短视频推荐的,类似B站,抖音这种。通过记录用户的观看点击等记录,利用算法理解用户的偏好,并进行推荐。
笔者在开发推荐系统时,参考了推荐系统方面最经典的架构,lambda架构,将整个推荐分为两个部分,离线部分以及实时部分。离线部分主要处理全量数据集,该部分的算法更关注推荐的精准性或其他相关指标,且算法运行时间较长。实时算法处理的是最近产生的一批数据,也可以说是数据流,该部分更关注运行的速度以及健壮性(其实就是时间复杂度和空间复杂度都不能高),该部分产生的推荐结果会直接推送给用户。
架构如下:
首先是业务端,需要接受推荐结果是业务端,产生用户操作记录的也是业务端,因此,在推荐的第一步,就是将用户操作数据收集下来,存在某个分布式数据库中,笔者用的是mongodb,接下来的离线推荐将基于该数据库中的数据。在上面的架构图中,笔者流出了几类常见的推荐算法,这些算法也是笔者致力于应用在推荐系统中的。在实时部分中,所操作的主要数据库不再是mongodb,而是redis,这是为了能够提升操作速度。流程如下:
离线部分以及实时部分将会在下文详细介绍。
离线推荐部分比较简单,由于不需要考虑算法的时间复杂度(一天跑一次或两次),因此只需要将注意力放在如何提高算法的某些推荐评测指标,比如RMSE/MAE, 召回率/精确率。
下面说一下笔者对上面架构图算法的一些理解,可供读者参考。
在笔者实现的推荐系统中,离线算法是被动吊起的,笔者基于crontab控制离线算法3小时跑一遍。
另外,为了解决稀疏性问题,笔者对原生的协同过滤算法进行了改动,加入了标签的考虑(用户是可获得用户标签的,物品也是),有兴趣的读者可私我了解。
首先看图:
实时部分解释起来相对麻烦。因为笔者将很多涉及到算法效率,健壮性的东西都放在实时里了,内容有点大。下面会逐一解释。
笔者在这里抓住一个东西:标签。实时算法将基于标签展开。
首先,视频是有标签的,这可以通过外包团队去打。一旦打好,就会存储在数据库中。但除此之外,用户也是有标签的——用户的标签通过其操作记录获得。比如,小明看了A,B,C三个视频,每个视频都会自己的标签,那小明的标签就是这些标签的加权组合(比如 A,B视频都有某个标签,那该标签在小明身上会占更多比重)。
上面两种标签都可以加入一些限制,比如对标签出现次数加入下限的限制。为什么这么设计呢?举个例子,小明看了若干视频,每个视频都带着自己的标签,比如A视频标签[a,b,c,d,e],B视频标签[b,c,e,f],那很明显地,对于小明来说,a,d,f出现了一次,b,c,e出现了两次,那么可以设置一个限制,出现过两次及以上的标签才纳入用户标签中,那小明的用户标签就是[b,c,e],这样做可以避免很多"噪音",“噪音”的意思是,只出现过一次或少数次的标签其实不能反馈用户的真实爱好,必须得多次。另外,去掉这些"噪音"还可以降低计算复杂度,毕竟向量更短。
标签可以理解为一个特征向量,每个用户,每个物品都带着这种特征向量。那如何利用这种特征向量呢?通过比较——然后就可以得出两个东西的相似程度了。这种比较不止可以用在用户-用户,物品-物品上,用户-物品也是可以的。 这就是这个实时算法妙的地方。
但这种比较不是余弦相似度,欧式距离这种比较,因为标签是中文,因此这里的比较必须基于NLP。实际上,笔者利用了了word2cvec的训练结果,直接获取两个中文词汇之间的相似程度,比如:similarity{爱好,兴趣} = 0.9。(word2vec是同事帮我训练的,但不难,只是采用的语料库很大,用了搜狗的开源语料库)。
笔者就是利用了用户-物品的比较方式。实现如下:
读者还看到,上面实时的图还包含了离线算法召回200个视频这个分支,这是笔者后面实现算法的时候加上去的。离线算法的推荐视频挺靠谱的,因此笔者将其前200个也拿出来作为召回集合,当然,这种计算也是异步的。这是一些小trick,在业务中会用的挺多这种手段,虽然操作不复杂,但能比较好的提高效果。
上面比较粗糙的讲述了笔者的推荐系统的工作。个人觉得,推荐系统其实是蛮有套路的,但在实践的时候,难度还挺大的,尤其是实时部分,涉及到健壮性,还有算法效率的考量,这个挺令我头痛的。
下面总结一下这些模块用到的技术:
笔者实现的推荐系统是基于python写的,即使是涉及到spark的部分,用了pyspark。
大致的工作就这些,有兴趣的研究的更深的可以私聊我微信:jiedemaikena
参考:https://blog.csdn.net/weixin_41697507/article/details/89386899