168大数据

标题: 58同城智能推荐系统的演进与实践 [打印本页]

作者: 168主编    时间: 2019-4-19 11:04
标题: 58同城智能推荐系统的演进与实践
58同城智能推荐系统大约诞生于2014年(C++实现),该套系统先后经历了招聘、房产、二手车、黄页和二手物品等产品线的推荐业务迭代,但该系统耦合性高,难以适应推荐策略的快速迭代。58同城APP猜你喜欢推荐和推送项目在2016年快速迭代,产出了一套基于微服务架构的推荐系统(Java实现),该系统稳定、高性能且耦合性低,支持推荐策略的快速迭代,大大提高了推荐业务的迭代效率。此后,我们对旧的推荐系统进行了重构,将所有业务接入至新的推荐系统,最终成功打造了统一的58同城智能推荐系统。下面我们将对58同城智能推荐系统展开介绍,首先会概览整体架构,然后从算法、系统和数据三方面做详细介绍。
整体架构首先看一下58同城推荐系统整体架构,一共分数据层、策略层和应用层三层,基于58平台产生的各类业务数据和用户积累的丰富的行为数据,我们采用各类策略对数据进行挖掘分析,最终将结果应用于各类推荐场景。
推荐系统是一个复杂的工程,涉及算法策略、工程架构和效果数据评估三方面的技术,后文将分别从这三方面介绍58同城推荐系统。
算法
推荐涉及了前端页面到后台算法策略间的各个流程,我们将推荐流程抽象成如下图所示的召回、排序、规则和展示四个主要环节:
在上述的四个环节中,召回和排序是推荐系统最重要的两个环节。规则和展示样式一般变化周期较长,而召回和排序有很大的挖掘空间,会被不断的迭代,我们的推荐算法工作也主要是围绕召回和排序进行。下图是我们推荐算法的整体框架,主要包括基础数据的计算以及上层的召回策略和排序模型的迭代。
基础数据计算主要包括用户标签和帖子标签的挖掘,这部分工作由用户画像、搜索和推荐多个团队共同完成,最终各团队共享数据。基于用户注册时填写的基础属性信息和用户行为日志,可以挖掘出用户人口属性和兴趣偏好信息,如用户的年龄、性别、学历、收入等基础属性,用户感兴趣的地域商圈、二手房均价、厅室、装修程度等偏好信息。帖子标签挖掘包括提取帖子的固定属性、挖掘衍生属性以及计算动态属性。固定属性直接从帖子数据库提取即可,如分类、地域、标题、正文、图片、房源价格、厅室、小区等。我们还会基于贴子信息是否完备、价格是否合理、图片质量好坏、发帖人质量等多个维度来计算帖子质量分。基于用户行为日志数据可以计算帖子的PV、UV、点击率、转化率、停留时长等动态属性。这些数据最终会在召回环节和排序环节使用,例如基于用户标签和帖子标签可以进行兴趣召回,将用户标签和帖子标签作为特征迭代机器学习模型。
召回主要负责生成推荐的候选集,我们采用多种召回源融合的方式来完成该过程。我们先后迭代了如下各类召回策略:
上述不同的召回算法都产生出了一部分推荐候选数据,我们需要将不同的召回数据融合起来以提高候选集的多样性和覆盖率,这里我们主要使用两种召回融合策略:
召回环节新召回源的添加或者新融合策略的上线,例如开发了一种新召回算法、需要修改调制融合策略中的配比等,我们都会做线上ABTest,最终通过比较不同策略的效果来指导我们的迭代。值得一提的是,召回环节我们还会有一些过滤规则,例如过滤低质量帖子、在某些特定场景下对召回算法产生的结果加一些条件限制等。
排序环节我们主要采用Pointwise方法,为每个帖子打分并进行排序,通过使用机器学习模型预估帖子的点击率、转化率和停留时长等多指标来做排序。早期我们主要优化点击率,目前我们不仅关注点击率外还会注重转化率的提高。在58同城的产品场景中,转化主要指用户在帖子详情页上的微聊、打电话操作。
排序离线流程主要包括样本生成和选择、特征抽取、模型训练和评价。首先对埋点日志中的曝光、点击、转化和停留时长等数据做抽取解析,如基于曝光序列号关联各类操作、解析埋点参数(例如日志中记录的实时特征)、解析上下文特征等,并同时打上label,生成模型样本。然后对样本进行过滤,例如过滤恶意用户样本、过滤无效曝光样本等。然后对样本做特征抽取,生成带特征的样本,我们主要从用户、帖子、发帖人和上下文四个维度做特征工程。之后,按照一定正负样本比例做采样,最终进行模型训练和评估,离线评估指标主要参考AUC,离线效果有提升后会进行ABTest上线,逐步迭代。我们先后迭代上线了如下排序策略:
基于上述基础机器学习工具,目前我们主要会迭代点击率、转化率和停留时长预估模型,线上会ABTest上线单指标模型、多指标融合模型,以提高推荐效果。
架构
对于推荐系统来说,一套支撑算法策略高效迭代的推荐后台系统至关重要,我们基于微服务架构设计了推荐后台系统,它扩展性好、性能高,系统架构如下图所示,系统分为数据层、逻辑层和接入层,数据层提供各类基础数据的读取,逻辑层实现召回和排序策略并支持不同策略的ABTest,接入层对外提供了通用的访问接口。
数据层提供推荐逻辑所需要的各类数据,这些数据存储在WRedis、文件、WTable等多种设备上,我们将所有数据的读取都封装成RPC服务,屏蔽了底层的存储细节。这里包括检索服务、召回源读取服务、帖子特征中心和用户特征中心:
逻辑层实现了详细的推荐策略,包括推荐主体服务、召回服务、排序服务和ABTest实验中心。这些服务由不同的开发人员维护,保证了推荐策略的高效迭代,例如召回和排序是我们经常迭代的环节,由不同的算法人员来完成,召回服务和排序服务的分离降低了耦合,提高了迭代效率。
接入层直接和客户端交互,从客户端接收请求并调用推荐主体服务获得推荐帖子id列表,然后查询出帖子详细属性返回给客户端做展示。在大部分推荐场景中,接入层由业务方维护,可能是PHP或Java实现的http接口;也有少部分场景的接入层是我们自主维护,我们采用58自研的MVC框架WF实现了相关http接口。
我们采用58自研的RPC框架SCF实现了上述微服务架构的推荐系统,采用58自研的监控系统WMonitor实现了推荐系统的立体监控,整个技术栈是Java。我们采用多线程、异步、缓存、JVM调优、降级、限流等措施保证了推荐系统的稳定和高可用,目前我们的推荐系统日均处理数亿的推荐请求,平均耗时约30毫秒。
数据
这里的数据主要指推荐埋点数据和推荐效果数据:埋点数据是推荐系统的基石,模型训练和效果数据统计都基于埋点数据,需保证埋点数据的正确无误;效果数据是对推荐系统的评价,指引推荐策略的迭代,构建完备的效果数据体系至关重要。
我们的推荐埋点日志数据包括曝光日志、点击日志、转化日志和页面停留时长日志等,这些日志数据都需要客户端通过埋点来产生。这里简单解释一下这些操作的含义:客户端请求一次推荐接口得到推荐结果列表叫做一次曝光;用户点击推荐结果列表上的某条帖子进入帖子详情页叫做一次点击;用户在帖子详情页上进行微聊、打电话、收藏等操作叫做转化;用户在帖子详情页上的阅读时间叫做页面停留时长。这里的曝光、点击和转化是一个漏斗,操作数量是逐渐递减的趋势。由于58同城上用户对帖子的访问可能来源于推荐、搜索和运营活动页等场景,为了标识出推荐产生的点击/转化/停留时长,我们需要在埋点中加入推荐相关的参数。我们将埋点参数设计成一个固定格式的字符串,它包含了曝光唯一序列号、推荐位标识、召回号、排序号、规则号、展示号、帖子id列表、帖子id等字段,这些字段将会作用于机器学习模型训练样本生成和推荐效果统计中。埋点参数主要分为列表参数和单贴参数两类:推荐接口返回一个帖子列表,会对应返回一个列表参数,包含了曝光序列号、推荐位标识、召回号、排序号、规则号、展示号、帖子id列表等字段;返回的帖子列表中,每个帖子会对应返回一个单贴参数,包含曝光序列号、推荐位标识、召回号、排序号、规则号、展示号、帖子id等字段。客户端得到推荐接口返回的埋点参数后,会将列表参数埋入到曝光日志中,将单贴参数埋入到点击日志、转化日志和停留时长日志当中,注意这里埋点时需要推荐列表页向帖子详情页传递单贴参数,一般需要通过修改跳转协议来实现。最终埋点日志中有了这些参数后,我们便可基于曝光唯一序列号将曝光、点击、转化、时长数据join起来,产生模型训练样本以及漏斗效果数据。值得一提的是,我们采取透传的方式在推荐后台、接入层、客户端间传递埋点参数字符串,所有埋点参数由推荐系统后台生成,接入层和客户端均不做任何处理。埋点参数仅由我们推荐一方负责,这样能够避免多方改动埋点参数,从而减少埋点错误的可能性,由于是透传处理,也便于今后埋点参数的扩展。
埋点数据是推荐系统的基石,不能有遗漏或者错误,这就要求我们严格把控开发测试流程,尤其是APP上的埋点,若发版之后发现有错误,便要等到下一次发版时解决。客户端开发和测试同事不清楚埋点参数的含义但熟练掌握测试环境部署及拥有Android和IOS测试机,而推荐后台同事清楚埋点参数含义但对测试环境较生疏并缺乏测试机,因此我们总结出了测试同事负责环境部署、推荐后台同事负责检验埋点参数的测试流程,详细流程如下图所示。此外,58同城上的APP开发比较复杂,不同产品线各自开发自己的APP业务模块,APP平台方开发主模块,每次发版前都有一个集成阶段,合并所有业务方提交的代码,产生最终的APP包,集成阶段很可能会发生业务方埋点未生效的情况。因此,我们的埋点测试包括业务方内部测试和集成测试两个阶段,以保证埋点万无一失。
我们的推荐效果数据是一个多维数据集,我们主要关注推荐位上的点击、转化、停留时长等指标。日常工作中我们需要从不同业务线、不同客户端、不同推荐位、不同推荐算法等多个维度去分析这些指标数据,例如我们会观察房产和车在相同推荐位上的数据对比、猜你喜欢场景上不同召回或排序算法的数据对比、二手房详情页在Android和IPhone上数据对比等。各种数据分析对比能帮助我们优化推荐策略,甚至能发现某些业务线功能逻辑上的隐藏BUG,例如在我们推荐项目攻坚阶段,我们通过分析比较二手房详情页在Android和IPhone两端的推荐效果,发现了IPhone上详情页浏览回退的BUG,最终反馈给业务方并解决了该问题,该BUG的解决使得我们在二手房详情页推荐位上的推荐点击量提高了数十万。
我们从离线和实时两方面构建推荐效果数据,数据统计流程如下图所示:
早期,离线效果数据统计是通过 MapReduce + Hive + MySQL 来实现的,我们首先会编写MapReduce程序对原始埋点日志进行抽取生成Hive表,然后会编写大量的Hive SQL来统计各类指标数据,并将结果数据写入MySQL数据表,最终做可视化展示和邮件报表。由于我们比较的维度和指标多,Hive SQL语句的编写消耗了我们不少人力。在数据平台部门部署了Kylin多维分析系统后,我们将效果数据统计工作迁移到了Kylin上,我们只需要设计好Hive源数据表,并设置好维度和度量,Kylin便能根据维度和度量来自动预计算结果数据,这省去了我们编写Hive SQL的工作,大大提高了效率。关于如何利用Kylin构建多维数据集可以参考此文《基于Kylin的推荐系统效果评价系统》。
实时效果数据我们采用Storm + HBase 来计算,实时效果数据主要用于异常埋点监控、新上线推荐算法效果快速反馈、模型异常监控等,我们实现了一个包含较少维度的多维数据统计,今后我们将尝试引入Druid等实时多维分析系统来完善推荐实时效果数据的建设。
总结
本文介绍了58同城智能推荐系统在算法、工程和数据三方面的技术演进。我们在最近一年加快了推荐业务的迭代速度,接入了房产、车等业务线在APP、PC、M三端共计近百个推荐位,我们的推荐点击占比指标(推荐位上产生的点击量在总体点击量中的占比)相比一年之前提高了2~3倍,达到了20%~30%,每天能够产生数千万的推荐点击量,为业务线带来了流量提升。
任何推荐系统的发展必会经历推荐位扩充和推荐算法深入优化两个阶段,流量指标可以通过扩充推荐位来快速提高,当推荐位稳定之后,就需要依赖更加深入的算法优化来继续提高指标,而此时的效果提升也会相对缓慢。目前,我们的流量指标已相对稳定,我们会更进一层去关注转化指标,提高用户进入帖子之后与发帖人进行微聊或电话沟通的可能性,帮助用户找到真正有用的信息。
作者:詹坤林,58赶集集团TEG架构线智能推荐部负责人、算法架构师,前腾讯高级工程师,从事推荐算法和架构设计工作。






欢迎光临 168大数据 (http://www.bi168.cn/) Powered by Discuz! X3.2