在线学习(Online Learning),顾名思义,是一种实时模型训练的方法,能够根据线上实时得到反馈数据,快速获取用户的最新兴趣,实时的进行模型调整自适应,从而提高线上预测的准确率,这几年比较热门,所谓“天下武功,唯快不破”,传统的离线训练模式,模型不能及时的更新,针对用户实时的行为不能做出快速的反应,在用户与产品交互性越高的场景就越需要去引入在线学习的模式,最典型的场景莫过于资讯推荐(头条)、沉浸式视频场景推荐(抖音)、以及广告推荐等领域;另外业界也是证明,在线学习对于新内容的分发有比较明显帮助,也能在新内容的上线当天快速进行试验,判别内容的优劣。
业务背景
游可赢流量池广告目前针对业务上希望对冷启动有一个较好的快速反馈效果,能够更及时的处理新建广告、新用户等问题,并且希望进一步提升模型的效果,所以针对当前业务,我们开始了在线学习的系统的开发,但是在线学习对数据的pipeline的稳定性、流量样本的分布矫正、模型训练稳定性以及模型部署都提出了比较高的要求。游可赢后台服务日请求量峰值3.5亿,QPS峰值6.6k,DSP每日请求回传数据数据在140亿/天,并且随着业务增长这个流量会一直增长,我们需要将一致性特征、曝光、点击、注册、回流等多个流进行在线join,最后形成一致性样本实时发送到我们的在线样本池中;我们的模型测也需要实时的获取我们的样本数据,按照一定的触发策略,进行实时训练,输出模型推给线上进行实时的预测,所以在工程上的压力还是比较大。
在线学习的挑战
数据实时化难点
-
多路数据在线join
在线需要根据唯一的请求ID,进行在线关联,峰值QPS可以达到30w ,需要大数据的状态存储,保障数据的拼接率,工程压力很大。 -
样本归因
因为数据上报的天然串行化,导致label滞后,广告CVR场景,转化的正样本delay现象更加明显,广告的注册、回流往往会在曝光后很晚,短则几小时,长则2,3天,例如一些比较大的游戏,由于本身下载就需要很久,导致注册和点击会有很大的时间gap,点击是需要长时间等待转化上报,需要确定如何归因样本label,这个问题我们叫延迟反馈问题。 -
数据的容灾
实时任务稳定性没有离线任务好,遇到流量高峰或者机器故障怎么保障数据稳定及在线学习效果影响降低到最小。
算法难点
-
实时数据分布不均匀,正样本delay
实时数据不像离线数据,在训练之前进行了shuffle,数据会有整体不均匀的情况,例高峰期与低峰期的样本分布整体分布都是不一样的,并且通过我们离线分析发现不同广告在不同时间点的曝光也不一样,这个也与我们的预算控制有关,以及正负样本分布也会出现不均匀的情况,并且由于归因的策略会有样本纠偏的问题,这里就不赘述,看了下面就知道为何需要样本纠偏了。 -
模型训练
在线模型训练还是和离线模型训练存在挺大区别,样本存在天然的分布不均匀问题,模型很容易训练偏,模型效果不稳定,所以在训练上需要对样本进行针对性处理,例入样本如何去构造、样本回放填补实时样本分布问题、训练触发条件调优、增加样本之后如何防止模型过拟合等等,都是需要进行尝试
技术选型
数据流工程方面,因为我们需要对实时样本要求必须有很高的准确性以及实时性,并且在任务的容灾、状态管理方面有着较高的要求,Flink在实时处理方面有着优秀的性能、吞吐、容灾,并且算子丰富,批流一体的支持也使得它近几年在大数据处理领域成为一颗冉冉升起的新星,所以我们选择了Flink作为我们的在线样本生产引擎,调研了公司内部的Flink平台之后,最后使用了公司内部的Oceanus Flink平台来做样本生产。
实现方案
整体推荐框架我们采用流批混合方式,采用实时和离线两条链路进行生产,总体包括5个主要模块:预测模块、特征及样本模块、模型训练模块、模型管理上线模块、全链路监控模块。
- 预测模块 简单来说,预测模块接收用户请求,通过获取离线、实时特征模型管理模块推送的最新模型进行在线预预测,同时产生日志,用于后续统计离线、实时的特征和样本。
- 特征及样本模块 特征和样本模块主要包括离线、实时两条链路,分别通过我们的离线、实时日志采用Spark、Flink处理生产。如果说模型决定了推荐效果的下限,那么推荐特征、样本数据的质量就决定了推荐模型的上限,所以这部分的工作是相当重要的。
- 模型训练模块 模型训练模块通过流批结合训练,实时模型定期在离线模型的基础上进行增量训练
- 模型管理上线模块 主要包括模型管理、模型评估、异常回滚等功能。
实时样本生成
上图展示了实时样本的生成过程,样本生产引擎通过唯一requestID对请求回传特征流、曝光、点击、注册、回流进行实时join,最后实时样本通过TDbank消息队列进行存储以及离线备份,业务前期我们为了快速上线,采用Interval join方式进行在线拼接,但是该方案由于本身业务流量会很大,会造成任务状态过大高峰期可以到达TB级别,造成RockSDB抖动,影响任务稳定性,并且计算资源消耗也会比较多,所以后续我们采用了多流union +timer 的方式进行改造实现,具体实现方案后续可以专门写一个文章来分析Interval join 的几个问题以及如何自定义状态管理实现多流join,经过定向优化后我们任务的计算资源消耗可以减少1/2以上;并且在开发过程中对异常数据的过滤、热点数据处理、RocksDB、Flink调优等都是可以单独写一篇文章进行分享的,这里就不展开了。
样本cache策略
一个广告的转化需要经过请求、曝光、点击、转化,所以负样本会先到达,针对这个问题目前有两种范式:
Facebook 的做法:负样本会先cache,等待后续可能发生的正样本,若正样本到达,则只保留正样本,更新模型一次。
Twitter 的做法:两条样本都会保留,都会去更新模型,这样实时性最高。
对比两种方案我们最后选择两者结合,离线分析样本拼接的窗口,满足95%以上数据拼接率的情况的时间窗口,超过窗口的正样本正样本最后进行补发,但是会加上一个retraction标志,表示这是一个迟到的正样本,后续模型会对该部分样本进行梯度处理,抵消之前负样本对loss的影响,其中等待的时间窗口T的设定会对模型效果有一定的影响,可以通过试验选择合适的窗口,例如我们将ctr的点击、曝光两条流的时间窗口定为10min,10min内曝光如果能够匹配到点击即下发正样本,不能下发负样本,超过10分钟的数据我们对其进行正样本补发。
批流结合训练
流式训练的在线学习模型具有很强的时效性,能捕捉数据分布的实时变化,迅速发现最新的流行趋势,然而由于上面提到的流式训练的label存在一定的错误比例,相比于离线模型存在欠拟合状态,并且离线数据由于样本是天级别统计,训练数据训练之前会充分shuffle,并且label的准确度更高,可以补充流模型的问题,所以我们采用了流批结合得到在线学习方案:实时模型定期在离线模型的基础上进行增量训练。
监控
样本数据作为在线学习的基石,质量的好坏就决定了整个在线学习的上限,所以对于在线学习任务的稳定性、样本的拼接效果、数据的实时性的保障都至关重要。
- ** 特征监控**
针对特征监控,包括从原始离线数据源、实时数据源的任务做任务告警,特征生产出现问题的时候第一时间处理;同时我们也对特征进行了质量监控,数值型的特征我们从更新数量、最大值、最小值、方差、均值、上四分位数、下四份数、极差、众数、标准差等统计指标对数据做监控;字符型特征主要包括更新数量、空值率告警。其中监控告警逻辑需要根据业务数据自行定制不同策略,找到符合业务逻辑告警规则需要不断调试才能确定。
-
样本监控
样本部分的监控包括任务监控、指标监控:
1.任务级监控主要包括:背压告警、CPU使用率、Checkpoint大小及耗时等,这些任务级别的监控Oceanus已经内置,我们可以在任务设置中进行配置
2.指标监控
指标监控主要包括小时级监控、分钟级别监控。小时级监控主要对样本拼接率、正样本拼接率、负样本拼接率、retreaction样本比例进行监控;分钟级监控因为在线学习实时要求比较高,小时级的监控再发现问题的话,等到修复重新积累样本,可能已经好几个小时过去了,这对我们的业务影响很大,所以还需要分钟级数据监控包括:样本产出速率、特征值为空比例、正负样本比例、retreaction样本比例,其中部分数据的波动很大,数据分布不同时间分布不均匀,很难形成告警逻辑,这部分数据只进行数据采集展示用于快速排查逻辑,只需要对样本产出速率、特征值为空等指标监控,能快速衡量出线上任务是否出现问题进行告警即可,这块后续我们会陆续补齐
-
模型监控
模型部分包括模型效果实时监控、模型指标(AUC、bias、predict_mean、real_mean等)监控、训练性能监控(io耗时、train耗时、io/train耗时占比、样本平均等待时长、数据积压),保证模型的正常训练。
效果
目前上线后,对比离线模型,在线学习模型可以看到在点击率比离线模型有点击率相对提升约2.8%,其中整体偏差从10%降低到5%,冷启动偏差从14%降低到6%,降低幅度达到50%,说明模型的预测更准确了,模型的auc也有所提升
后续方向
探索更多的在线学习范式,在动态的调整模型参数,避免模型过拟合或者欠拟合,动态结构如何与静态结构组合,目前还比较简单粗暴,后面这部分还值得优化。另外可以尝试指定不同的样本权重,比如冷启动样本权应该重高一些,帮助模型快速学习;另外像样本回放、蒸馏学习等都可以尝试下。
参考资料
1.在线学习在爱奇艺信息流推荐业务中的探索与实践
https://www.infoq.cn/article/lthcdazelzgc639p1p5q
3.京东搜索排序在线学习的 Flink 优化实践
https://zhuanlan.zhihu.com/p/344054330
4.微博如何基于 Flink 生成在线机器学习的样本?
https://segmentfault.com/a/1190000024423669
5.Flink on RocksDB 参数调优指南
https://km.woa.com/group/38788/articles/show/413643
6.Apache-Flink深度解析-JOIN 算子
https://cloud.tencent.com/developer/article/1407308