58 同城 | 深度学习在商业排序的应用实践
文章作者:覃然斌、王科 58同城
内容来源:58技术
导读: 在互联网商业变现场景中,广告变现占有主导地位。2012年随着深度学习网络AlexNet在ImageNet夺冠开始,深度学习迅速席卷图像、语音、NLP等领域,并逐步在互联网商业化最成功的搜索、推荐和广告领域获得突破并成为主流。
作为国内最大的生活信息服务平台,58拥有海量的C端用户和B端客户;商业中台团队为房产、招聘、黄页、二手车多业务线提供商业变现和营销解决方案。在广告变现的过程中,需要平衡好用户体验、广告主roi和平台收益,用户和广告的智能匹配工作为深度学习提供了很好的落地土壤。
01 系统框架
本文介绍深度学习在58商业排序CTR预估建模中的一些实践经验,主要聚焦于房产场景,从样本数据构建、模型算法迭代和线上推理优化三方面进行阐述。
商业服务的主要排序场景
商业排序系统框架如下图所示,分为离线和在线两部分,离线部分包括:离线与实时基础特征计算、特征中心同步与管理、原始样本串联、特征工程、训练样本构建、模型训练与评估、模型分发等环节。在线部分流程包含基于请求数据从特征中心拼接原始样本、特征工程、模型打分、平滑校准、业务规则调整重排及日志记录等环节。
商业排序系统框架
02 样本数据
数据决定模型效果上限,在实践中我们发现数据迭代比单模型提升重要得多,是整个算法落地中最重要的环节,下面先从特征工程和样本构建两方面说下我们一些实践经验。
1. 特征工程
① 基础特征
基于对用户行为模式及业务场景特性的理解,以房产ctr建模特征为例,考虑相关性、多样性、时效性、权威性等方面,从用户、客户、广告、上下文4个维度上,我们构建了如下基础特征体系[1]:
房产基础特征体系
基础特征构建过程中尽量贴近业务特性及用户场景;如为避免帖子在首次上线的情况下曝光太少,按帖子属性拆解,加入所属小区、商圈、区域、广告主等点击率特征;针对到市场上头部经纪人广告主,加入广告主帖子量、广告主帖子平均价格、广告主管辖小区数等特征。用户第一视觉决定了点击意愿,我们加入了title首词的embedding的表征。用户对看过的房源会有过载性,找房又是一个持续时间较长的行为,同时频控是短时的绝对过滤,我们加入帖子给用户展过的次数及用户点击过的次数,避免同样的帖子对用户持续无效的曝光,增加看到新房源的概率。基础特征工程常规流程使用标准化、归一化、连续分段、稀疏过滤、离散聚类和非线性transform等处理手段,与业界大多公司流程一致,这里不做过多说明。
② 高阶特征
表征学习在深度学习特征工程中非常有效,通过embedding向量表征帖子在用户兴趣点空间里面的距离关系,处理方式参考airbnb的实践[1]。从用户的交互式会话序列中,通过word2vec对item的共现关系进行建模,将其映射到低维连续的向量。为避免冷启动问题,对item按属性维度进行编码,使用embedded厅室 + embedded价格 + embedded商圈作为item vectors。word2vec在计算词向量时与其上下文关系非常大,用户行为序列不像文本一样存在标点、段落等标识去区分上下文,如何截断用户session及过滤就显得很重要了。我们直接采用计费反作弊状态对用户session中的行为进行过滤,然后按3小时时间窗口划分session片段构造上下文。向量效果评估采用相似性+应用端模型效果的评估方式。由于embedding网络参数一般采用不包含任何先验信息的随机初始化方法和输入信息的稀疏性,会导致embedding层的收敛速度极慢,此外embedding层的参数数量过多又会降低整个深度网络的收敛速度,因此对于广告维度的基础属性embedding,我们从端到端训练改为预训练进行特征生成[2] 。
③ Bias特征
列表页中广告位置越靠前点击率越高,位置偏差对预估的准确性影响很大,在lr模型中我们会将position特征当作普通特征看待拼到样本中进行位置纠偏,但是神经网络中如果直接将pos当作普通特征输入NN是行不通的,在浅层模型如xgb我们也遇到了相同的问题,pos特征太强会直接影响其他特征进而影响预测结果。NN模型情况中,我们探索后将position加入到最顶层处理bias消偏问题。房属于大宗商品,不同于电影和新闻等推荐场景头部重,需要在热度和新鲜度之间取得平衡,如果没有时间度量,模型在所有时间分布上预估趋近于平均,这与实际经验分布不符。我们需要在训练时考虑这一bias,否则由样本中其他特征强行解释由发布时间越长而带来额外曝光影响容易导致过拟合。在加入帖子时间新鲜度因子的基础上,我们参考google的做法[2],同时也加上了example age特征,根据训练样本曝光时间与预测样本时间差作为age。线上排序时,将age特征设置成默认值0,帖子不在具有age维度的偏差,有利于将那些刚发布曝光较少但是帖子很优质与用户match度更高的新帖子排出来。
**2. 样本构建:原始样本一致性与实时性
离线训练和在线预测时样本的差异会对模型的效果产生很大的影响,很多时候我们离线调优发现GAUC上涨了,但是线上没有效果,大多数情况是线上线下样本特征不一致导致的。只有保证pipeline线上线下的一致性,才能保证线上模型的效果。差异产生主要来源于原始特征和特征处理。线上线下使用同一个lib处理以避免处理过程产生diff。考虑到候选集过大对写盘的压力、特征迭代过程需要对原始特征处理调优及再加工、新特征的加入与迭代效率等情况,我们在线上拼接样本时直接将与时间相关特征落盘以记录当时的状态,离线通过状态回溯得到原始样本,再重新进行二次特征抽取得到训练样本;但这种方案对新加入的实时特征并不友好,需要持续积累训练数据,影响特征迭代效率。
为解决上述问题我们开发了另一种不经过线上系统的样本生成方案以支持对大量实时特征的迭代需求,由于特征生产时间与应用时间存在gap,需要记录特征在应用环境中生效时间(特别大量实时特征),然后通过时间戳查找当时的状态进行特征串联。离线天级别特征更新可看作无状态的,当天样本只会获取到线上生效前和生效后两种时间状态的特征,大量实时特征是随着时间状态快速迁移的,实时特征中有包含增量变更(如实时ctr、用户行为序列、用户个性化偏好等)和混合变更(如广告创意title大多数时间是不会变更,一旦变更后又能保持状态很长一段时间,如果以7天的时间窗口进行实时特征滑动,那么对串联当天曝光基础数据而言,这种就是混合的,有可能当天修改多次;也有可能当天从来不会修改而保持3天前修改过的状态,这时候当天的离线特征路径中就找不到)。将特征数据抽象分为有状态/无状态、纯全量变更、纯增量变更、增量全量混合等几种形态。混合状态数据、全量无状态数据先扫描一遍数据经过状态处理将其统一为纯增量有状态数据,形态打平便于状态的回溯,按key进行分组merge, 查找与要拼接Base数据时间一致的生效状态。这种方式只涉及一次shuffle与二次全量数据扫描,可以将同一维度(ad/user/aduser/context)不同版本的多个数据源(id/统计/实时or离线/用户画像/高阶特征)一键串联完成,大幅节约原始样本生成时间。
考虑到公司大多数任务都集中在凌晨集群资源紧张,依赖上游dwd及其它清洗配置生成,深度学习模型训练时间长,模型分发到线上会错过早上流量高峰,同时为了支持模型的近线更新,从集群资源利用分布、数据延迟情况、不需要完全一致性方面考虑,我们的方案是基于Flink 采用Kappa架构构建流式框架生成近线样本。由于用户的反馈有延迟,统计覆盖95分位点的反馈需要3min的窗口,我们基于此窗口的数据按pv维度进行聚合,先按pv维度对用户点击反馈进行缓存,串联时通过sessionid拉取同一pv下缓存的反馈数据,大幅降低了存储与请求量。一旦数据正负样本变化超出阈值就会丢弃这个窗口的样本数据并,5个窗口依旧没有恢复便kill application进行报警人工处理。
03 训练样本
在得到原始样本的基础上,训练样本构建主要分为清洗、采样两个环节。样本清洗我们提供了用户、曝光、点击三个维度的清洗,在曝光、点击、转化维度进行爬虫过滤、异常过滤、计费反作弊过滤基础上,我们会按ctr/cvr维度进行过滤,按百分位对头部用户进行截断,避免高度活跃用户对loss的影响。同时,相近上下文情况下,用户存在完全相反两种操作,如同一房源用户早上看房的时候点过了,晚上再找房的时候不点了,为了避免模型把样本学偏,这个时候我们会按user_item对其进行过滤掉。我们实践中采取的样本处理流程如图所示:
样本处理流程
通过探索实践我们的框架支持样本采样方法的灵活配置,包括均匀采样、正采样、pv维度、user维度采样组合、非点击采样、曝光采样以及各组合采样等。
- 均匀采样:无差别随机采样,设定正负样本比例,实践中通过调参比较模型损失,我们使用15%的采样频率在训练性能和效果上取得较好的平衡。
- 有行为pv欠采样:按pv维度保留有行为的session,相对于直接对全部曝光进行均匀采样,这种方式线上AB-test cpm2提升明显。
- 负样本欠采样:保留全部正样本,对整体负样本进行采样。
- 真曝光采样:保留用户最后一次点击行为位置之前的曝光的所有样本。
- 有行为user采样:按用户维度保留有行为用户的正样本,按用户维度对负样本进行随机采样。
- 候选采样:按user/pv维度保留有行为的正样本,负样本不仅从曝光log中采,而且直接使用精排服务的请求候选集中进行负样本获取,实践证明这样做效果要优于只保留有行为用户的负样本采样。
通过样本采样会修改了线上线下数据分布,ctr在迭代过程中线上线下样本存在天然的diff,模型具有贪婪性,出现频率越高,记忆效果越好,导致倾向于把高pv、高点击的结果往上推,但是存在其它点击率很高(曝光5次点击2次)的优质广告由于曝光过少导致一直推不上去;此外我们用的采样数据都是截断给用户的,经过模型作用后有偏的,不断形成负反馈,偏离越来越大,模型效果上线后会逐渐衰减,这种排序系统公平性问题Google 在2019年探索了[3]基于随机化实验的pairwise comparisons来度量推荐公平性,并基于此指标提出了正则化方法以改善模型推荐的公平性。同时,58列表页帖子存在同质化现象,用户的兴趣边界并不明显,可能存在误点,未点击也并不表示用户不感兴趣,点击的随机性就会偏重,但是构造训练样本时label却是0和1的区别。所以针对公平性及随机性,我们在处理样本的时候探索采用了候选采样。但是,只使用有行为的用户样本,模型就只能够学习到活跃用户或者有意向用户的行为习惯,这就导致线下数据与线上数据分布有偏差,所以需要根据各自业务场景下线上的AB-test效果来决定最终采用什么样的采样方式。采样后线上模型打分会产生偏移,ctr上涨但是cpm却下降,我们会通过插值法对其进行校准,带来cpm明显提升。最后,测试集的选取,尝试了N窗口训练,N+1测试,以及也参考Google做法[2]选择用户最后一次行为作为测试,避免穿越问题离线虚高,后者选取策略更优。
最终,我们将采样算子集成到pipline框架中,样本生成框架提供了从原始特征产出到最终训练样本生成的一键配置化方案,包括workflow管理、pipline管理、多源IO、输入解析、样本过滤、样本各维度原始特征串联、特征处理、采样、特征选择等各环节,配置实例如图4所示。大幅降低多条业务线样本生成的迭代成本。
一键配置化样本生成框架
小结:
样本构建策略的探索给我们带来了cpm2 近10%的提升,相对浅层模型,深度学习特征数据依旧比模型算法重要,很多同学平时比较关注模型算法,却往往忽略样本工程,特征一致性、时效性、样本分布等环节的工作,这些工作做好做扎实才能获得业务指标的提升。Embedding工作与其花更多的时间和精力尝试各种word2vec变种算法上,远不如花在训练语料构建上的收益大,同时embedding层将稀疏输入向量转换为稠密向量,太多的端到端学习会导致训练效率大幅降低,为了在性能和效率方面tradeoff,我们将重要的属性特征组合编码,通过预训练的方式引入深度网络,以降低训练及预估耗时长。
04 算法模型
2016年6月,Google提出了后续在工业界影响巨大的Wide&Deep[4]模型来预估点击率并取得了成功,2017年开始我们也逐步从基于ftrl 的online learning切入到深度学习的探索。根据58不同业务特点我们探索并差异化落地了一系列深度学习算法,首先探索并迭代了基于大规模ID特征的Wide&Deep,沿着Wide&Deep特征工程化的思路,历经Deep&Cross[5],FNN[6],DeepFM[7],NFM[8]以及多任务的ESMM[9]模型等,但是从特征工程化角度尝试尽可能多模型后,单模型结构对业务指标提升逐渐遇到天花板,更需要通过模型直接从数据中挖掘到潜在的内因并探索结构上的改进,如引入attention和序列模型。围绕数据的挖掘我们落地了基于序列数据引入attention的DIN[10],探索了兴趣演化的DIEN[11]和长序列MIMN[12]等。下面对我们模型选型的演化路径及实践的一些经验进行简要介绍。
1. Wide&Deep
wide&deep网路结构
Wide&deep网络结构如图5所示,它由浅层模型wide部分和深层模型deep部分进行联合训练构成,让模型同时具有了记忆与泛化的能力。记忆能力就是模型学习并利用历史样本中特征的交叉出现频率的能力。如回龙观与西二旗共现频率很高,用户点击了回龙观的房子就赋予相应西二旗房子更大的权重,这种复现是强特征,其权重会在模型训练过程中会调大,实现对此特征的直接记忆。而对于NN来说,特征会经过多层交叉,对这个特征的记忆就会弱化了,这时候就需要deep层通过神经网络深度发掘数据中的潜在模式,平滑推荐结果。
在实践中,相对于网络调参,更大的提升来自于特征处理上。通过对训练数据的分析,我们发现不同维度特征的取值分布、相同维度下特征值的差异都很大。例如帖子新鲜度、点击率等特征的数据服从长尾分布,大部分样本的特征值都比较小,少量样本特征值非常大。常规的归一化方法处理得到的特征分布仍然是长尾分布,数据左倾接近于0集中在非常小的取值范围内,大部分的数据都挤压在一块,导致样本特征的区分度减小,而少量的大值特征可能造成训练时的波动,减缓收敛速度。我们加入非线性函数变换使倾斜数据转换为类正态分布,但由于不同维度间特征的分布不同,处理的方式并不一定通用于其它特征。我们尝试了倒数、平方、开方、对数、Box-Cox等操作,最终选择了可解释性较好的前4种变换处理得到4个特征加入到特征集合中。Deep部分输入了全量特征向量,wide部分输入了用户的反馈行为及用户与item的一些交叉特征,对所有多值连续特征(如实时点击率等)进行等频离散化加入到deep部分做embedding。我们也尝试了多种连续特征离散化策略,如树模型离散化等,使用等频离散化保证了对于不同分布的特征都可以映射到近似的均匀分布,从而保证样本间特征的区分度和数值的稳定性;使用树模型离散化能够较好的确定离散化数量和离散化边界。我们也探索尝试了多种对离散特征进行hash分桶和分桶数量的组合策略。分桶不可避免会造成特征值碰撞,有效的降低碰撞可以使模型接收更多更准确的信息;如果分桶较大,虽然降低了碰撞概率,增加了信息的保留,但是训练的模型参数更多更复杂,影响模型训练和线上推理的效率。统计样本中id类特征在2周内的数据分布,根据业务特点和取值数量进行设置特征取值个数超过n(n>500)的ID类特征分2n+1个桶,有较好效果与效率,效果与更多分桶相当。过多极为稀疏的离散特征会在训练过程中造成过拟合问题,同时增加参数的储存数量。为避免该问题,我们对离散特征进行了低频过滤处理,丢掉小于出现阈值频次的特征。
参数调优上,在线上性能满足要求前提下,神经元层数及各层神经元个数的选择尽可能大,然后加入dropout来降低过拟合。dropout降低了节点间的敏感度,避免训练时的过分学习和节点依赖,推理时相当于起到了ensemble的作用,能够有效克服模型的过拟合。由于我们的数据都是经过归一化和分桶等处理再进行输入的,且网络深度不大,因此并没有使用BN。
最终,线上模型我们取得了+2.31%的cpm2提升及+9.0%的cvr提升。Wide&Deep开启了双模型组合的新思路,之后大量神经网络改进都是基于改进记忆或者泛化部分来进行。如使用Cross网络替代原来的wide部分的Deep&cross。后续改进的DeepFM、NFM、DCN[7]也都是Wide&Deep的延伸。针对Wide&Deep模型wide部分不具备特征自动组合的能力,我们升级了FM模型以加强了浅层网络部分特征组合能力。
2. DeepFM
在点击率预估中,用户意图和商品的匹配程度是最为核心的问题,将item和user根据业务知识进行组合是常见的处理方式。例如,候选帖对用户在价格偏好、厅室、商圈偏好组合是否满足,这种包含两个或多个维度信息交叉的特征是记忆关键。DeepFM使用FM对Wide部分作了替换,其表达式如公式(1)所示,通过自动组合二阶特征避免人工组合特征的费时费力与覆盖不足问题,使得模型捕获到更多特征之间的二阶影响。
DeepFM仍然保留了大部分Wide&Deep的调参动作。相对FM二阶交叉存在的模型爆炸问题,对三阶扩展无能为力。NFM利用神经网络替代FM二阶隐向量内积部分。NFM也是Wide&Deep的改进,对Deep部分加入特征交叉池化,加强了特征交叉。随着模型算法迭代提升空间逐步收窄,线上AB-test几乎没有增长,还增加了推理耗时。在这种情况下,更需要思考如何能够让模型围绕原始数据挖掘,从数据中获取影响优化目标的潜在因子,例如通过attention根据当前候选帖子动态表征用户。在学术界浙大通过在特征交叉与池化层之间引入注意力网络,提出了含有注意力机制的FM模型AFM[13]。工业界阿里版本基于业务观察理解,通过候选帖子与用户历史反馈生成注意力权重,提出了DIN模型,其根据具体业务场景和数据特点为出发点,是我们在结合自身业务分析后选择探索并落地DIN模型的原因。
3. DIN & DIEN
用户的交互历史能够高效的刻画用户的兴趣偏好,在3.1特征工程中我们提到根据airbnb做embedding思路生成高阶特征也是从用户行为空间获取帖子的表征,但它对用户历史反馈的帖子没有区分重要程度,也没有根据候选场景动态进行用户表征。租房场景中,用户的交互序列有效的反映了用户理想的房源,帖子序列间接的反映了用户偏好房源中的共性。在不同的候选场景下,用户对小区、商圈、区域、厅室、价格等反映出的兴趣度是不一样的,我们需要用候选帖子去用户交互历史捕获其兴趣权重,即在不同场景下用户的多元化意向,增强点击率预估的准确性;DIN模型网络结构如图所示:
DIN网路结构
模型通过attention机制来对用户历史反馈序列数据进行建模,不同的交叉计算出预估时请求的候选商品与用户交互历史中节点的匹配程度,然后通过加权求和来得出候选商品与用户历史兴趣的匹配程度。数据方面,我们通过Flink根据用户行为构建了房源,小区,商圈,区域和价格等sequence,用户序列行为的采集可以做到秒级延迟。特征处理过程中不使用原始值而对序列元素中的连续值进行分段能取得更好的效果。根据统计的用户点击次数分布和线上推理性能考虑,序列长度选择最近邻20个条记录,长度不足20,则使用缺失值进行填充。
用户的第一视觉很大程度上决定了点击意愿。在迭代的后期,我们进一步添加了用户点击标题特征序列。除了价格和位置外,用户发生点击行为的主要影响因素是标题的描述,通过标题序列特征的加入,更好的挖掘和表征了用户的直接意图,AB-test效果有明显提升。最终,在数据和模型的迭代上,我们取得了cpm2+10.83%,ctr2 +9.85%的效果。
DIEN是上一个模型DIN的升级版,基于围绕数据挖掘的模型取得较明显效果后,我们对其进行了探索实践。DIN解决了序列特征的应用,只区分了用户不同反馈的重要性问题,而用户的反馈或多或少是存在序关系的,如望京soho工作的人在找房时,开始会特别关注周边的小区,如花家地,金兴路等,随着探索会[3] 逐步扩散发现更多适合的小区,如何距离更远的北窑地等。我们在离线验证过程中GAUC没有明显提升,分析可能原因是用户使用目的明确,在58找房的场景更多使用筛选组合条件,一段时间探索后趋于稳定,兴趣进化并没有那么明显,同时也有可能因为B端经纪人客户供给分散度不足以支撑用户的选择,这部分待进一步深入分析和验证。此外,DIEN加入GRU来进行兴趣抽取,这样导致线上推理串行化,耗时数倍增长,所以我们没有上线AB-test查看线上效果。针对这个问题阿里的做法是将最耗时的序列模型部分拆到离线进行实时更新,服务耗时降低了数倍。
4. Multi-Task
广告预估场景中存在多个预估任务,比如ctr/cvr。既考虑到多个任务之间的联系和差别,我们利用Multi-TaskLearning的思想,同时预估点击率、转化率。原有cvr模型面临正负样本不均衡导致难以建模的问题,大量的负样本占据了模型中的多数参数,而对少量的正样本学习欠缺。解决正负样本不足通常使用样本选择来降低正负样本不均衡问题,通常有正样本正采样和负样本负采样,但是采样后不仅破坏了原有的数据分布,且负采样会带来信息的缺失。因此,传统的CVR模型都基于点击数据进行建模,虽然改变了原有的分布,缺失了部分信息,但是大大的降低了样本的不平衡性。然而基于点击进行CVR的建模往往也带来了一些问题,例如样本的选择偏差和训练样本的高度稀疏。偏差由于训练数据和测试数据分布不同,导致预测时的泛化性能降低;训练集只是训练空间中的少量部分,导致训练数据稀疏,模型难以拟合。我们选择了多种行为路径的联合建模-ESMM[11]来处理我们的业务场景,其网络结构如图7所示,ESMM模型使用两个辅助任务来对CVR问题进行建模,分别为CTR与CTCVR。由于CTR和CTCVR的加入,ESMM模型可以使用整个样本空间进行建模,因此后面的CVR问题也由整个样本空间得来。CTR、CTCVR模型两个部分共用的Embedding,使得CVR的信息更加丰富,更能够对真实的ID进行刻画。
ESMM网络
这部分线上AB-test业务数据没有取得预期的增长,还待进一步分析调优;但是从工程方面来看,一个网络同时返回ctr和cvr,极大降低资源消耗,是很有意义的工作。
5. 小结
面对广告点击率预估这样一个监督学习的问题,我们借助于深度学习尽可能多的节约特征工程中的人工投入,更多地让点击率预估模型和各个辅助模型自动完成特征构造的工作,并始终和点击率预估的目标保持一致。总体而言,我们更多的借鉴了工业界的优秀的算法,随着深度学习模型的进化速度越来越快,场景越来越广,针对模型迭代还需要我们结合自身业务特点充分调研和数据分析,然后再进行业务场景的落地。
05 系统工程
任何算法的落地都需要强大的系统工程能力去支持和实现,广告系统中用户请求曝光要求极高的时效性,我们场景对精排环节要求平响<15ms,TP999<50ms,加上反序列化解析及网络耗时,服务内部耗时约束时间实际更短。随着深度学习的落地、特征数增长、特征处理及网络结构复杂度的增加,我们线上性能受到了较大的挑战。算法工程师的目标是在公司给定资源约束下,以线上落地为目标,寻找并实现最优的解决方案,所以我们需要计算我们迭代的ROI,以较小的成本获取较大的收益。GPU主要应用在计算密集程度高、实际业务场景中QPS较低的语音及图像上面,在广告排序这种高并发请求、数据高度稀疏的场景下,GPU增加不必要的成本、复杂性和内存限制(CPU预处理->CPU-GPU传输->GPU计算),没有体现深度学习的性能优势,所以我们线上推理都是基于CPU进行的。下面说一下我们在基于CPU的深度学习系统工程中一些实践经验。
58商业排序系统框架整体如图2所示,其中线上精排pipline如下图所示:
精排处理流程
线上请求过来之后,首先构造原始样本数据,根据PV请求信息拼接特征中心(请求redis或DMP)构建各维度的特征抽取上下文,对生成的上下文数据使用我们配置的各类型算子对原始样本进行特征抽取,然后对得到的样本数据进行协议转换,调用模型计算进行打分,然后进行结果调整(对打分进行平滑校准、根据业务及规则进行重排等),最后构造返回结果。
针对深度学习推理服务优化我们从模型算法层、业务应用层、系统计算层三个方面开展,虽然模型算法优化也很有效,但是不同的参数就能导致性能观测大幅波动,如embedding size 大小会大幅影响模型大小、训练速度和推理速度,一个hashbucketsize参数也会对线上推理造成很大的影响,这就导致针对算法层的优化不具有通用性。在算法层针对性的调参优化后,我们主要从业务应用层和系统计算层加速提升服务性能。我们的优化点如图9所示,下面从应用层与系统层展开说明。
线上服务优化
1. 应用层
① Pipline优化
特征处理算子和pipline优化中,使用工具分析性能热点,合理优化代码,如:jdk8 steamapi慎用,老老实实用回for循环;字符串操作尽量少;替换性能差的方法,如split;更换序列化与反序列化方法及协议;流程上对共用功能进行统一,如协议解析、用户特征抽取等只做一次并缓存;本地加上双级cache,避免redis中不存在的key每次查询;帖子维度实时离线特征分离cache等操作,从业务流程合并特征处理。
② 统一特征预处理
Tensorflow提供了很多方便好用的特征处理接口,如 tf.feature_column直接输入原始数据,在建模时给予我们极大的特征工程便利性。Feature column是原始数据到模型可接受数据的连接桥梁,将原始的数据转化为模型可以接受的dense tensor,如图10所示,包含了连续值分段,离散值映射等功能将原始数据转换为0~N的连续整型数据,然后再通过indicator或embedding转换为模型可接受的dense tensor。
feature column 特征工程接口[图来着tensor官网]
Tensor训练时耗时如图11,其中红框为特征转换,蓝框为前向计算,绿框为梯度更新。这部分线上线下一致,统计后数据表明特征转换耗时约占整个从输入到预估耗时将近20%。将特征转化作为模型计算的一部分,极大的影响了训练和推理时的性能。因此,我们将模型计算中的特征转化统一拆分到特征处理框架中。
深度学习模型计算耗时统计
在深度学习算法上线之初,我们沿用的是已有的特征处理框架,该框架主要面向lr/xgb模型进行设计,其中:缺失值用-1表示,特征值返回为整型。Featurecolumn使用vocabulary或hash_bucket将原始特征值转换为0N的连续整型数,同时hash_bucket过程会将原始输入转换为字符串类型后再进行hash,然后取模得到0N的连续整型数据,包含了额外处理。原有特征抽取框架返回了默认值-1,由于缺失值为-1和特征值的不连续导致即使有限的整型数据也需要使用vocabulary进行重新映射;特征处理框架中字符串数据hash为整型后的vocabulary映射;特征处理框架中字符串hash为整型后,featurecolumn转化为字符串后再hash等过程,这些处理极大影响模型训练与推理性能。此外,放在计算密集的模型计算去进行特征处理,资源无法平滑扩展,每个epoch都会重复处理,也不利于调参。针对这些问题,我们优化统一特征处理lib,解放计算性能,缺失值统一由0替换;支持特征值偏移操作;类别特征转换支持vocabulary与hash_bucket映射;连续数据通过指定分段方式输出0~N的分段索引值。分离后将特征工程交由专业的大数据框架进行处理,训练样本直接通过spark生成训练需要的tfrecords格式,通过spark的并行性,大幅加快了训练样本生成,大大降低了训练耗时。同时,去除了feature_column层的依赖,线上特征处理资源也能平滑扩展,模型推理也得到较大提升。
③ 模型协议修改
原有tensorflow模型导出与官方给的多数例子一样,使用build_parsing_serving_input_receiver_fn来构建模型的输入接收器方法,该方法接受序列化为字符串的tf.train.example作为输入,然后通过提供的feature_spec解析,并返回所有解析的Tensor作为特征进行输入。实践中发现这部分序列化过程和反序列化过程耗时比较大。
我们修改为build_raw_serving_input_receiver_fn接收器方法,这样在推理阶段我们可以根据构建的配置文件,动态指定每个特征通过tensor直接喂到网络,省略了example序列化过程和反序列化过程,预估过程耗时降低25%。所有特征通过tensor喂入网络时值得注意的是,当特征值为字符串类型时,仍然需要转换为byte数组然后才能转换为tensor,字符串类型需要指定字符串的长度,这仍然需要大量的推理时间。因此,去除了所有的字符串的输入,全部转换为整型/浮点数类型。进一步省略了协议转换中tensor转换的耗时,也降低了模型对内存的消耗。
在特征抽取时, 样本是按行保存的,这样使得特征抽取不仅可以使用多线程, 而且线程之间耗时的较为均匀,而在输入模型时,是按列进行输入的, 即一个特征保存为一个tensor。从特征抽取到模型打分需要进行tensorflow协议适配,而这个转换过程是串行的,无法并行化。在DIN模型上线时,发现原有深度学习上线时没有使用到大量的序列特征,特征抽取框架没有很好的支持序列特征的处理,将序列数据保存为字符串类型,然后在数据适配阶段再反解回去,导致在协议转换时非常的耗时。在特征抽取直接返回列存储,消除协议适配时data format的过程,format部分耗时降低90%。
2. 系统层加速
CTR预估模型的主流架构可拆解为embedding+ mlp,embedding在推理时是一个超大的table,只是一个取的过程,使用时属于I/O密集操作,mlp包括GEMM,activation,bias和batchnormalization等,mlp + 基础模型(lr/fm等)主要是元素积的矩阵运算,计算量不大;而din/dien引入attention, GRU等结构后计算量暴涨。针对计算层优化从喂入数据调整、模型量化、模型剪枝、模型压缩、矩阵计算优化、支持全新向量计算指令集等方面入手。
由于线上推理基于CPU,所以像Nvidia发布的只支持GPU的 TensorRT就无法满足我们的需求。基于我们特征体系及候选集下测试了tensorflow serving,相对我们优化之前的嵌入调用,Batch size=100的条件下,上涨100%,batch_size=300的情况下涨幅更大,达到157%;大特征集下其中协议转换、grpc序列化及网络耗时占比过高,同时定制化输入不方便,交互协议无法修改。考虑我们目前精排候选集不会大幅增加的情况下,从特征处理与模型计算之间的耗时及线上CPU资源利用分布来看,我们选择通过api进行嵌入调用,特征抽取与模型计算共同部署。
Tensorflow 一般使用float32的数值类型,研究表明FP16精度的算法模型接近于FP32相同的算法准确度,因此可通过使用半精度来降低模型的计算需求和数据传输需求以提高推理性能[14][15][16],各设备厂商也都提供支持,如:
Intel MKL-DNN [17], Google GEMMLOWP[18], ARMCMSIS [19], Nvidia TensorRT[20]等。
我们使用的是Intel的架构自身对tensorflow做了优化[21],所以第一步尝试了MKL。指令支持方面,我们首先对线上平台:
32Intel(R)Xeon(R)CPUE5-2630v3@2.40GHz
进行了理论FLOPs分析,其中8/16/32线程性能如表1所示:
8 thread | 16 thread | 32 thread |
---|---|---|
fma fp32 perf:662.3965 gflopsfma fp64 perf:331.1150 gflopsavx fp32 perf:331.0797 gflopsavx fp64 perf:165.5737 gflopssse fp32 perf:165.5506 gflopssse fp64 perf:82.8166 gflops | fma fp32 perf:1324.6517 gflopsfma fp64 perf:662.3838 gflopsavx fp32 perf:661.1188 gflopsavx fp64 perf:330.0723 gflopssse fp32 perf:331.1051 gflopssse fp64 perf:165.3885 gflops | fma fp32 perf:1326.7139 gflopsfma fp64 perf:660.5904 gflopsavx fp32 perf:659.7766 gflopsavx fp64 perf:329.4999 gflopssse fp32 perf:331.6430 gflopssse fp64 perf:165.6869 gflops |
表1 线上机器flops
不同的指令集能获得不一样的浮点性能,同时16到32thread的过程中cpu上涨了,但是处理能力没有提升,当浮点乘加的能力被充分利用后,超线程并不能带来好处,预估的batchsize需要根据算力调优。重新编译tensorflow以适应我们的线上机器配置,经过重新编译和调参,开启了MKL及XLA22加速,支持SIMD指令集兼容了avx2和FMA,在我们线上的数据集中提升近20%的性能,相比预期低了很多,应该是MKL优化的操作符多用于CNN模型。实践中碰到bazel引用了大量的外网的资源无法编译的问题,如果本地电脑直接代理即可,但是使用本地的linux或者macos编译出来的lib很多底层库版本不一致,线上升级会比较麻烦。推荐使用和线上机器参数、系统完全一致的机器进行编译,如果由于公司规定不方便线上代理,可以写个简单脚本对workspace及bzl下的链接进行扫描并下载,编译时指定下载所在目录即可。
模型压缩,我们采用的3层全连接,hash及embedding维度都进行了优化以处理模型大小到可接受程度,测试发现对我们效率提升有限。剪枝能减少FLOPS,但因为我们的模型网络本身就不是特别复杂;同时图像特征离线处理完成,不带有卷积等结构单元,这部分的工作并没有大幅提升,同时再训练处理不方便。加入构建文本处理及图像特征生成后,为进一步加速我们的应用,在支持tensorflow XLA后,也评估了另两种IR(Intermediate Representation)转换的OpenVivo[23]和TVM[24]第三方工具加速性能,相对于openvivo需要额外部署推理,TVM更具通用性,借鉴业界的方案[25],我们选择了TVM进行下一步探索实践。TVM是一系列工具集(TVM stack),它是提供计算图级优化和运算符级优化的编译器,支持如高级运算符融合、内存延迟隐藏、基于学习的成本建模方法来快速搜索代码优化等功能,这部分工作目前还在开发测试,暂时未能给出线上加速效果数据。
3. 小结
通过在应用层和系统层的优化工作,在线推理性能提升80%,训练提升70%。当然,系统加速的方案还在持续优化中;还需要可以支持更大特征候选集、更复杂特征和模型算法的落地,系统工程的工作为算法落地提供了强有力支撑。
06 总结与展望
未来我们需要在数据、算法和系统工程方面持续探索和优化,寻找业务增长点。持续跟进业界技术动态,并结合58多业务场景进行差异化定制和实践。
首先数据依旧是重点,样本用户反馈信息存在噪音导致模型偏移,前期做了一些样本的探索,后续将会进一步深入研究。通过数据挖掘更多业务因子,优化多商业产品混排,重排序,多样性[26]等逻辑。加入更多数据,如用户负反馈信息序列[27]等。在特征方面,在广告创意和视觉等方面落地更多深度学习算法,加强用户第一视觉的理解,首图信息及title文本理解,描述候选keyword和keyword分级,挖掘多模态融合的特征表征;探索更多对个性化创意排序方案。
探索粗排精排融合方案,相对精排,粗排受到计算规模的限制,58商业广告的粗排模型经历了从简单特征统计模型到轻量级LR/Tree/FM模型,以及双塔深度学习模型,但双塔限制了user与item之间的特征交叉,同时最终的目标拟合只能是向量内积式,模型表达能力较弱。需要进一步挖掘粗排的提升空间,在架构和模型推理上深入探索,在性能与效果上寻求平衡以支持粗排模型逼近精排模型的在线推理。
工程上需要支持更大的模型,支持更大的样本及特征规模以及模型的实时更新,跟进Tensorflow的新特性,并对目前实际应用中遇到的问题针对性优化。定义和设计新的系统架构以适应深度学习落地领先算法的能力。
作者简介:
覃然斌:58商业产品技术部资深算法工程师,专注于广告预估迭代与优化。
王科:58商业产品技术部-策略技术团队算法开发工程师, 主要从事58同城租房点击率预估的的优化与迭代。
[1]. Mihajlo Grbovic and Haibin Cheng. Real-timePersonalization using Embeddings for Search Ranking at Airbnb. KDD '18:Proceedings of the 24th ACM SIGKDD International Conference on KnowledgeDiscovery & Data Mining (2018)
[2]. Paul Covington Jay Adams Emre Sargin. Deep NeuralNetworks for YouTube Recommendations. Proceedings of the 10th ACM Conference onRecommender Systems, ACM, NewYork, NY, USA (2016) (toappear)
[3]. Beutel, A., Chen, J., Doshi, T., Qian, H., Wei, L.,Wu, Y., Heldt, L., Zhao, Z., Hong, L., Chi, E. H., et al. Fairness inrecommendation ranking through pairwise comparisons. arXiv preprint. arXiv:1903.00780,2019.
[4]. H.-T. Cheng, L. Koc, J. Harmsen, T. Shaked, T.Chandra, H. Aradhye, G. Anderson, G. Corrado, W. Chai, M. Ispir, et al. Wide& deep learning for recommender systems. arXiv preprint arXiv:1606.07792,2016.
[5]. Ruoxi Wang, Bin Fu, Gang Fu, and Mingliang Wang .2017. Deep & Cross Network for Ad Click Predictions. arXiv preprintarXiv:1708.05123 (2017).
[6]. W. Zhang, T. Du, and J. Wang. Deep learning overmulti-eld categorical data.In ECIR, 2016.
[7]. Huifeng Guo, Ruiming Tang, Yunming Ye, Zhenguo Li,and Xiuqiang He. 2017. DeepFM: A factorization-machine based neural network forCTR prediction. In Proceedings of the IJCAI. 2782--2788. http://dl.acm.org/citation.cfm?id=3172077.3172127
[8]. Xiangnan He and Chua Tat-Seng. 2017. Neuralfactorization machines for sparse predictive analytics. In Proceedings of theSIGIR. ACM, Shinjuku, Tokyo, 355--364.
[9]. Xiao Ma, Liqin Zhao, Guan Huang, Zhi Wang, Zelin Hu,Xiaoqiang Zhu, and Kun Gai. 2018. Entire Space Multi-Task Model: An EffectiveApproach for Estimating Post-Click Conversion Rate. SIGIR (2018).
[10]. GuoruiZhou, Chengru Song, Xiaoqiang Zhu, Xiao Ma, Yanghui Yan, Xingya Dai, Han Zhu,Junqi Jin, Han Li, and Kun Gai . 2017. Deep interest network for click-throughrate prediction. arXiv preprint arXiv:1706.06978 (2017).
[11]. G.Zhou, N. Mou, Y. Fan, Q. Pi, W. Bian, C. Zhou, X. Zhu, and K. Gai, Deep interestevolution network for click-through rate prediction. ArXiv, 2018.
[12]. Q.Pi, W. Bian, G. Zhou, X. Zhu, and K. Gai. Practice on long sequential userbehavior modeling for click-through rate prediction. In KDD, pages 2671–2679, 2019.
[13]. JunXiao, Hao Ye, Xiangnan He, Hanwang Zhang, Fei Wu, and Tat-Seng Chua. 2017.Attentional factorization machines: Learning the weight of feature interactionsvia attention networks. arXiv preprint arXiv:1708.04617 (2017).
[14].https://software.intel.com/zh-cn/articles/lower-numerical-precision-deep-learning-inference-and-training
[15].B.Jacob, S. Kligys, B. Chen, M. Zhu, M. Tang, A. Howard,H. Adam, and D.Kalenichenko. Quantization and training of neural networks for efficientinteger-arithmetic-only inference. CVPR, 2018
[16]. V.Vanhoucke, A. Senior, and M. Z. Mao. Improving the speed of neuralnetworks on cpus [C]. NIPSw, 2011.
[17]. Intel(R)MKL-DNN, “Intel(R) Math Kernel Library for Deep Neural Networks. https://intel.github.io/mkl-dnn/index.html.
[18].GEMMLOWP,“Gemmlowp: a small self-containedlow-precision GEMM library.” https://github.com/google/gemmlowp.
[19].ARM,“Arm cmsis nn software library.”http://arm-software.github.io/CMSIS 5/NN/html/index.html.
[20].Nvidia,“8 bit inference with TensorRT”. http://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inferencewith-tensorrt.pdf.
[21].https://software.intel.com/en-us/frameworks/tensorflow
[22].https://github.com/tensorflow/tensorflow/tree/master/tensorflow/compiler/xla
[23]. https://docs.openvinotoolkit.org/2019_R2/index.html
[24].T.Chen, T. Moreau, Z. Jiang, L. Zheng, E. Yan, M. Cowan, H. Shen, L. Wang, Y. Hu,L. Ceze, C. Guestrin, A. Krishnamurthy, TVM: An automated end-to-end optimizingcompiler for deep learning,2018,[online]Available: https://arxiv.org/abs/1802.04799.
[25]. https://yq.aliyun.com/articles/569539
[26]. YueFeng, Jun Xu, Yanyan Lan, Jiafeng Guo, Wei Zeng, and Xueqi Cheng. 2018. FromGreedy Selection to Exploratory Decision-Making: Diverse Ranking withPolicy-Value Networks. In SIGIR (SIGIR'18). 125--134.
[27]. WentaoOuyang, Xiuwu Zhang, Shukui Ren, Li Li, Zhaojie Liu, Yanlong Du. Click-ThroughRate Prediction with the User Memory Network. KDD 2019
今天的分享就到这里,谢谢大家。