李渊驰 哔哩哔哩技术 2023-06-27 12:01 发表于上海
本期作者
李渊驰
(资料图片)
哔哩哔哩资深开发工程师
背景介绍
作为一个拥有庞大年轻用户群体和多元化内容资源的视频平台,B站为广告主提供了丰富的投放场景。为了实现更精准的广告投放,B站商业化技术团队深入挖掘用户、物料、场景等多方面的数据特征,并构建精细化的目标受众画像。这些数据在经过特征计算后会成为模型训练所需的训练样本,通过模型训练得到能够对广告创意进行点击率、转化率预估的深度模型。当用户进行访问时,作为广告检索引擎的一部分,在线CTR预估服务会使用深度模型,对候选集内的广告创意逐个进行点击率、转化率预估,这些数值会在精选阶段用来挑选出价值最高的广告创意返回给用户。模型预估的准确性直接决定了广告检索引擎的效果,为了确保模型训练和模型推理阶段所使用的样本数据的一致性,提供一个全面、稳定、高效的广告特征平台显得尤为重要。
遇到的问题
模型训练
模型训练分为离线训练和实时训练两部分,在构建特征平台之前,特征处理的主要流程如下图所示。
离线训练
离线训练主要用于训练以天为单位的模型,通过处理前一天的日志数据得到训练样本,分为数据拼接、样本生成、模型训练三个阶段:
1) 数据拼接
将广告引擎日志和用户行为日志进行拼接,写入日志消息队列,进一步和离线Hive表和离线Redis库中的预处理数据进行拼接,生成离线Hive表作为离线视图,最后将数据文件存储至HDFS。
2) 样本生成
使用MapReduce框架读取并处理HDFS上的数据文件,使用Python脚本进行特征计算,将生成的训练样本文件存储至HDFS。
3) 模型训练
模型训练框架从HDFS读取样本文件,执行模型训练任务。
实时训练
实时训练主要用于训练以小时为单位的模型,通过处理前一个小时的日志数据得到训练样本,由于处理的数据量较小且时效性更高,实时训练能够得到更好的效果:
1) 数据拼接
与离线训练有所不同,实时训练的过程中,在日志消息与离线数据进行拼接后,将消息写入新的消息队列作为实时视图。
2) 样本生成
使用Flink流处理框架读取消息队列,使用Java实现的UDF来进行特征计算,将生成的训练样本文件存储至HDFS。
3) 模型训练
模型训练框架从HDFS读取样本文件,执行模型训练任务。
模型推理
在线CTR预估服务,将使用深度模型对候选集中的广告创意进行点击率、转化率预估,其中特征处理的主要流程如下图所示:
在线推理
在线服务部分,CTR预估服务会将请求侧数据和广告侧数据进行拼接,处理后生成推理样本,与模型训练类似,也分成数据拼接、样本生成、模型推理三个阶段:
1) 数据拼接
广告检索引擎将请求侧数据和从BS服务召回的广告侧数据发送至CTR预估服务,CTR预估服务与在线词表和在线Redis进行拼接。
2) 样本生成
CTR预估服务使用C++实现的特征计算算子完成特征处理,生成训练样本。
3) 模型推理
CTR预估服务使用深度模型对样本进行推理,计算得到广告创意的点击率、转化率预估值。
结合上述模型训练和模型推理的执行流程,可以发现现有系统存在以下问题:
1) 数据源分散
训练时数据源来自于多个预处理结果,拼接成本较高。
2) 数据不一致
训练时数据和推理时数据的产出分别来自于两组任务,任务间数据处理方式存在差异,产出版本也不统一。
3) 计算不一致
在离线训练、实时训练、在线推理三个流程的特征计算阶段,分别需要使用Python、Java、C++三种语言进行实现,代码逻辑难以完全一致。
4) 排查问题成本较高
当需要排查模型训练和模型推理的一致性问题时,离线无法获取推理阶段使用的完整特征数据,难以快速准确定位问题。
架构设计
针对上述问题,我们希望能够提供一个涵盖模型训练过程和模型推理过程的特征平台,确保模型训练时和推理时样本数据的一致性,从而提升模型预估的效果。同时考虑到模型训练过程中,数据拼接阶段的资源开销,我们设计了一套基于在线服务侧的实现方案,通过在线服务侧上报特征数据的方式,大幅简化了模型训练过程中的数据拼接工作。新的实现方案涵盖了模型推理和模型训练两个部分,具体如图所示:
模型推理
模型推理侧的升级点主要是提供了竞胜广告的特征数据上报能力,具体包括了:
1) 获取实时Redis数据上移至广告检索引擎
Redis中主要存储了实时的用户侧特征数据,获取数据的操作上移至广告检索引擎后,确保了发送至CTR预估服务和特征上报服务的用户侧特征是一致的
2) 新增在线特征上报服务
在线服务侧新增了特征上报服务,广告检索引擎在返回竞胜的广告创意前,会将该广告侧数据和请求侧数据一起发送至特征上报服务。该服务与CTR预估服务使用相同的代码实现,并且加载了相同的在线词表,在经过数据拼接阶段后,会将拼接完成的信息作为一条文本消息上报至消息队列,其中包含了特征计算阶段所需的全部字段。
3) 升级C++特征计算库
通过进一步优化,将CTR预估服务中的特征计算模块升级成了特征计算库,主要进行了如下修改:
a. 新增序列化/反序列化功能,能够对拼接后的用户侧和广告侧数据进行序列化/反序列化操作。
b. 移除/简化第三方库的依赖,尽可能降低JNI调用过程中的额外依赖。
模型训练
模型训练侧的升级点主要是简化了数据拼接,并且统一了模型训练和推理的特征计算实现,具体包括了:
1) 简化数据拼接
由于特征上报日志中已经包含了特征计算的全部字段,因此新方案只需要拼接用户行为日志和特征上报日志,将结果写入消息队列即可得到实时视图,将结果写入Hive表即可得到离线视图。
2) 统一离线训练和实时训练
在离线训练的过程中,使用Flink-Batch的方式从离线视图中获取数据,后续操作与实时训练相同,使用UDF生成训练样本,并将样本数据写至HDFS。
3) 使用JNI调用特征计算库
使用JNI技术实现了在Flink流处理框架中,通过UDF调用C++特征计算库进行处理,统一了特征计算的代码实现。
实践及收益
自特征平台上线以来,已有三个深度模型采用新方案进行训练,在模型效果和训练成本上均取得了显著收益。
在模型效果方面,累计修复了72%的特征一致性问题(其中9%的特征严重不一致,diff比例大于10%),从而提高了模型预估的准确性。这使得效果广告整体收入提升了1.30%,同时在信息流、Story和播放页三个场景中,点击率分别提升了4.61%、1.36%和2.42%。
在训练成本方面,大幅简化了离线训练和实时训练过程中的数据拼接,降低了Flink硬件资源需求,使得模型训练的Flink任务并发度下降了79%。此外,通过对视图模块的重构,训练任务流程变得更加清晰简洁,进一步降低了模型迭代和问题排查的成本。
总结和展望
在商业技术部的工程团队、数据团队和算法团队的紧密协作下,我们成功构建了一套实时流广告特征平台。这一平台克服了数据源分散、数据不一致、计算不一致以及排查问题成本较高等诸多挑战。它为离线训练和实时训练提供了一套统一的数据处理和特征计算方案,简化了数据拼接流程,提升了模型预估的准确性,并降低了训练成本。
为了持续优化广告特征平台,各团队将在未来的工作中加强沟通与协作,共同探讨和研究平台的优化方向。我们将致力于进一步提升模型性能,优化训练和推理流程,并为商业化业务的持续增长提供坚实的技术支持。
以上是今天的分享内容,如果你有什么想法或疑问,欢迎大家在留言区与我们互动,如果喜欢本期内容的话,欢迎点个“在看”吧!