Torch-RecHub是一个轻量级的pytorch推荐模型框架,易用易拓展,聚焦复现业界实用的推荐模型,以及泛生态化的推荐场景,是值得学习和掌握的。而且,Torch-RecHub有优秀的团队一直在维护和改进,并且有良好的社群可以学习和讨论。
随着移动互联网的飞速发展,人们已经处于一个信息过载(VS信息不足)的时代。在这个时代中,信息的生产者很难将信息呈现在对它们感兴趣的信息消费者面前,而对于信息消费者也很难从海量的信息中找到自己感兴趣的信息(搜寻成本过高)。
推荐系统的核心任务是从海量物品中找到用户感兴趣的内容。在这个背景下,推荐系统包含的模块非常多,每个模块将会有很多专业研究的工程和研究工程师。俗话说,不谋全局者,不足以谋一域。因此,我们有必要梳理清楚整个推荐系统的架构,知道每一个部分需要完成哪些任务,是如何做的,主要的技术栈是什么,有哪些局限和可以研究的问题。本文将会从系统架构和算法架构两个角度出发解析推荐系统通用架构。
系统架构的设计思想是大数据背景下如何有效利用海量和实时数据,将推荐系统按照对数据利用情况和系统响应要求出发,将整个架构分为离线层、近线层、在线层三个模块,更多的是考虑推荐算法在工程技术实现上的问题。下图是Netflix在2013年提出的架构,其中的技术也许不是现在常用的技术了,但是架构模型仍然被很多公司采用。
简单来说,各层的功能如下所示,本文之后会详细介绍:
离线层是计算量最大的一个部分,需要实现的主要功能模块是:数据处理、数据存储;特征工程、离线特征计算;离线模型的训练。目前主流的做法是HDFS,收集到我们所有的业务数据,通过HIVE等工具,从全量数据中抽取出我们需要的数据,进行相应的加工,离线阶段主流使用的分布式框架一般是Spark,如下图所示:
离线任务一般会按照天或者更久运行,比如每天晚上定期更新这一天的数据,然后重新训练模型,第二天上线新模型。
离线层面临的数据量级是最大的,面临主要的问题是海量数据存储、大规模特征工程、多机分布式机器学习模型训练。
近线层的产生是同时想要弥补离线层和在线层的不足,折中的产物。它可以获得实时数据,然后快速计算提供服务,但是并不要求它和在线层一样达到几十毫秒这种延时要求。
它适合处理一些对延时比较敏感的任务,比如:
近线层的发展得益于最近几年大数据技术的发展,很多流处理框架的提出大大促进了近线层的进步。如今Flink、Storm等工具一统天下。
所有的用户请求都会发送到在线层,在线层需要快速返回结果,它主要承担的工作有:
在线服务的数据源就是我们在离线层计算好的每个用户和商品特征,我们事先存放在数据库中,在线层只需要实时拼接,不进行复杂的特征运算,然后输入近线层或者离线层已经训练好的模型,根据推理结果进行排序,最后返回给后台服务器,后台服务器根据我们对每一个用户的打分,再返回给用户。
在线层最大的问题就是对实时性要求特别高,一般来说是几十毫秒,这就限制了我们能做的工作,很多任务往往无法及时完成,需要近线层协助我们做。
在实际的工业场景中,不管是用户维度、物品维度还是用户和物品的交互维度,数据都是极其丰富的,学术界对算法的使用方法不能照搬到工业界。当一个用户访问推荐模块时,系统不可能针对该用户对所有的物品进行排序(学术界做法)。所以一个通用的算法架构,设计思想就是对数据层层建模,层层筛选,帮助用户从海量数据中找出其真正感兴趣的部分,如下图所示:
召回层的主要目标时从推荐池中选取几千上万的item,送给后续的排序模块。由于召回面对的候选集十分大,且一般需要在线输出,故召回模块必须轻量快速低延迟。由于后续还有排序模块作为保障,召回不需要十分准确,但不可遗漏。
目前基本上采用多路召回解决范式(一方面各路可以并行计算,另一方面取长补短),分为非个性化召回和个性化召回。个性化召回又有content-based、behavior-based、feature-based等多种方式。
召回主要考虑的内容有:
粗排的原因是有时候召回的结果还是太多,精排层速度还是跟不上,所以加入粗排。粗排可以理解为精排前的一轮过滤机制,减轻精排模块的压力。粗排介于召回和精排之间,要同时兼顾精准性和低延迟。
精排需要在最大时延允许的情况下,保证打分的精准性,是整个系统中至关重要的一个模块,也是最复杂,研究最多的一个模块。
精排和粗排层的基本目标是一致的,但是和粗排不同的是,精排只需要对少量的商品进行排序即可。因此,精排中可以使用比粗排更多的特征,更复杂的模型和更精细的策略(用户的特征和行为在该层的大量使用和参与也是基于这个原因)。
目前精排层深度学习已经一统天下了,精排阶段采用的方案相对通用,首先我们要解决的是样本规模的问题,尽量多的喂给模型去记忆,另一个方面时效性上,用户的反馈产生的时候,怎么尽快的把新的反馈给到模型里去,学到最新的知识。
重排序在业务中,获取精排的排序结果,还会根据一些策略、运营规则参与排序,比如强制去重、间隔排序、流量扶持等、运营策略、多样性、context上下文等,重新进行一个微调。
本文将会分别从算法和工程两个角度出发,按照推荐系统的环节来介绍当前主流的一些推荐算法技术栈。
召回一般都是多路召回,从模型角度分析有很多召回算法,这种一般是在召回层占大部分比例点召回。除此之外,还会有探索类召回、策略运营类召回、社交类召回等。接下来我们着重介绍模型类召回。
通过某种算法,对user和item分别打上Embedding,然后user与item在线进行KNN计算实时查询最近邻结果作为召回结果,快速找出匹配的物品。需要注意的是如果采用模型召回方法,优化目标最好和排序的优化目标一致,否则可能被过滤掉。
在这方面典型的算法有:FM、双塔DSSM、Multi-ViewDNN等。
用户在使用APP或者网站的时候,一般会产生一些针对物品的行为,比如点击一些感兴趣的物品,收藏或者互动行为,或者是购买商品等。而一般用户之所以会对物品发生行为,往往意味着这些物品是符合用户兴趣的,而不同类型的行为,可能代表了不同程度的兴趣。比如购买就是比点击更能表征用户兴趣的行为。在召回阶段,如何根据用户行为序列打embedding,可以采取有监督的模型,比如NextItemPrediction的预测方式即可;也可以采用无监督的方式,比如物品只要能打出embedding,就能无监督集成用户行为序列内容,例如SumPooling。
这方面典型的算法有:CBOW、Skip-Gram、GRU、Bert等。
用户往往是多兴趣的,比如可能同时对娱乐、体育、收藏感兴趣。这些不同的兴趣也能从用户行为序列的物品构成上看出来,比如行为序列中大部分是娱乐类,一部分体育类,少部分收藏类等。用户多兴趣拆分可以更细致刻画用户兴趣的方向。
本质上,把用户行为序列打到多个embedding上,实际它是个类似聚类的过程,就是把不同的Item,聚类到不同的兴趣类别里去。目前常用的拆分用户兴趣embedding的方法,主要是胶囊网络和MemoryNetwork,但是理论上,很多类似聚类的方法应该都是有效的,所以完全可以在这块替换成你自己的能产生聚类效果的方法来做。
这方面典型的算法有:Multi-InterestNetworkwithDynamicRoutingforRecommendationatTmall等。
知识图谱有一个独有的优势和价值,那就是对于推荐结果的可解释性:比如推荐给用户某个物品,可以在知识图谱里通过物品的关键关联路径给出合理解释,这对于推荐结果的解释性来说是很好的。缺点在于,在排序角度来看,是效果最差的一类方法。所以往往可以利用知识图谱构建一条可解释性的召回通路。
这方面的算法有:KGAT、RippleNet等。
这方面典型的算法有:GraphSAGE、PinSage等。
排序模型是推荐系统中涵盖的研究方向最多,有非常多的子领域值得研究探索,这也是推荐系统中技术含量最高的部分,毕竟它是直接面对用户,产生的结果对用户影响最大的一层。目前精排层深度学习已经一统天下了,下图是王喆老师《深度学习推荐算法》书中的精排层模型演化线路。
在深度学习推荐算法发展早期,很多论文聚焦于如何提升模型的特征组合和交叉的能力,这其中既包含隐式特征交叉DeepCrossing也有采用显式特征交叉的探究。本质上是希望模型能够摆脱人工先验的特征工程,实现端到端的一套模型。
这方面的经典研究工作有:DCN、DeepFM、xDeepFM等。
在序列建模中,主要任务目标是得到用户此刻的兴趣向量(userinterestvector)。如何刻画用户兴趣的广泛性,是推荐系统比较大的一个难点,用户历史行为序列建模的研究经历了从Pooling、RNN到attention、capsule再到transformer的顺序。在序列模型中,又有很多细分的方向,比如根据用户行为长度有研究用户终身行为序列的,也有聚焦当下兴趣的,还有研究如何抽取序列特征的抽取器,比如研究attention还是胶囊网络。
这方面典型的研究工作有:DIN、DSIN、DIEN、SIM等。
传统做法在多模态信息融合就是希望把不同模态信息利用起来,通过Embedding技术融合进模型。在推荐领域,主流的做法还是一套非端到端的体系,由其他模型抽取出多模态信息,推荐只需要融合入这些信息就好了。同时也有其他工作是利用注意力机制等方法来学习不同模态之间的关联,来增强多模态的表示。
比较典型的工作有:ImageMatters:VisuallymodelinguserbehaviorsusingAdvancedModelServer、UMPR等。
这方面比较典型的算法有:ESSM、MMoE、DUPN等。
先强化学习能够比较灵活地定义优化的业务目标,考虑推荐系统长短期的收益,比如用户留存。在深度模型下,我们很难设计这个指标的优化函数,而强化学习是可以对长期收益下来建模。第二是能够体现用户兴趣的动态变化,比如在新闻推荐下,用户兴趣变化很快,强化学习更容易通过用户行为动态产生推荐结果。最后是EE也就是利用探索机制,这种一种当前和长期收益的权衡,强化学习能够更好的调节这里的回报。
这方面比较典型的算法有:DQN、ReinforcementLearningforSlate-basedRecommenderSystems:ATractableDecompositionandPracticalMethodology。
跨域推荐系统相比一般的推荐系统要更加复杂。我们要关心在不同领域间要选择何种信息进行迁移,以及如何迁移这些信息。
这方面典型的模型有:DTCDR、MV-DNN、EMCDR等。
这里的经典算法有:MRR、DPP、RNN等。
推荐系统的实现需要依托工程,很多研究界Paper的idea满天飞,却忽视了工业界能否落地,进入工业界我们很难或者很少有组是做纯research的,所以我们同样有很多工程技术需要掌握。下面列举了在推荐中主要用到的工程技术:
Torch-RecHub是一个轻量级的pytorch推荐模型框架,可以用来做工程实践和研究。本质上就一个基于PyTorch的Python库,可以下载调用。这个库目前还在由开发团队不断拓展中,感兴趣的也可以申请加入团队。
pipinstalltorch-rechub在作者安装的时候,出现了一些错误,可能是因为Windows操作系统的原因。
解决方案:
PS:手动下载annoy离线安装可能会失败,显示缺乏依赖库的安装(手动安装,不会自动安装所依赖的库?)。推荐安装C++,一劳永逸。
深度学习模型基本都需要有输入和输出来进行训练,DIN也不例外。因此,我们需要将原始数据转换为模型要求的输入类型(特征工程),才能进一步调用。
fromtorch_rechub.basic.featuresimportDenseFeature,SparseFeature,SequenceFeature#获得每个类别的数量,用来指定vocab_size的大小n_users,n_items,n_cates=data["user_id"].max(),data["item_id"].max(),data["cate_id"].max()#对于sparsefeature,需要输入embedding层,所以需要指定特征空间大小和输出的维度features=[SparseFeature("target_item",vocab_size=n_items+2,embed_dim=8),SparseFeature("target_cate",vocab_size=n_cates+2,embed_dim=8),SparseFeature("user_id",vocab_size=n_users+2,embed_dim=8)]target_features=features#对于序列特征,除了需要和类别特征一样处理意外,item序列和候选item应该属于同一个空间,我们希望模型共享它们的embedding,所以可以通过shared_with参数指定history_features=[SequenceFeature("history_item",vocab_size=n_items+2,embed_dim=8,pooling="concat",shared_with="target_item"),SequenceFeature("history_cate",vocab_size=n_cates+2,embed_dim=8,pooling="concat",shared_with="target_cate")]2.3.3实验数据载入数据预处理后,获得特征后,就要按照深度学习的训练测试范式来构建批处理的dataloader。