写点什么

统一预估引擎的设计与实现

发布于: 2021 年 07 月 20 日

1. 背景


随着互联网的快速发展,互联网上出现了各种海量的信息。怎么样为用户推荐感兴趣的信息是个很大的挑战?各种各样的推荐算法、系统都涌现出来。而预估引擎可以说是推荐系统中比较重要的一环,预估引擎效果的好坏严重影响了算法效果。结合 oppo 的业务场景,我们的预估引擎需要解决几个问题:


(1)通用性:oppo 的推荐业务场景非常多,包括信息流、商店、短视频、联盟、锁屏杂志、音乐等业务,预估引擎要支持这么多的场景,框架一定要通用。


(2)多模型预估:在广告场景中,需要支持 ocpx,需要一次请求同时预估 ctr 和 cvr,可能是多个不同的转化模型(例如下载、付费等)。


(3)模型的动态更新:有些模型是小时更新、有些模型是天级更新,需要做到能够无感的动态更新。


(4)扩展性:各个业务用到的特征、字典、模型类型都可能不一样,要做到比较容易扩展。


2. 定位与技术选型


考虑到各个业务的业务特征差异比较大,统一预估引擎如果要支持各个业务的策略实验和分流实验,会让预估引擎模块非常臃肿,没法维护。所以最终决定预估引擎只做预估相关的事情。从原始数据到得到预估 ctr 结果,需要经过特征提取,提取特征之后的结果再进行模型预估。考虑到特征提取结果比较大,一次预估需要用的特征结果大约有 2M,这么大的数据如果通过网络来传输,耗时太长。所以预估引擎总体的流程包括了两部分:特征提取和模型预估。


3. Predictor 的设计与实现


3.1 Predictor 模块在整个推荐系统中的位置



以 oppo 手机应用市场为类来说明 predictor 模块在整个系统中的位置, ranker 模块负责排序,包括各种分流实验和各种运营策略等。它通过 grpc 框架与 predictor 模块进行通信。


3.2 Predictor 模块的主体流程



图中示意了两个请求的处理流程,图中提特征包括多个特征 conf,每个样本、每个特征配置提取一次。预估也会是多个模型,每个样本、每个 conf、每个模型会预估多次。特征提取依赖外部字典,预估依赖外部的模型文件,外部字典的更新、双 buf 切换都是通过字典管理模块来完成的。下面分别就字典管理模块、分 task, 提特征,预估,merge 进行详细说明。


3.3 字典管理模块


如下图所示:conf1, conf2, lr_model_x0 等表示磁盘上的文件,每个文件名都是通过不同的字典解析类来解析,这个字典解析类负责管理这个文件的加载,双 buf 切换。例如:FeatureConfDict 负责解析 conf1,它内部保存两个 FeatureConfList 类型的 buf,当 conf1 文件发生更新时,就用备的 FeatureConfList* 进行加载,加载完成后,在加载过程中,服务使用主的 FeatureConfList*指针。加载完成后,进行主从切换,待没有请求使用老的 buf,就释放到老的 buf 内存。



3.4 分 task 逻辑


接收到一个请求,这个请求指定了多 conf 多模型来预估。如下图所示:



上图表示一共有 8 条样本,分别用两个 conf:conf0, conf1 来提取特征,其中 conf0 的结果由 model0,model1 来预估,conf1 由 model2,model3 来预估。按照 2 个样本一个 task,拆分完 task 之后会得到 4 个 task,如下图所示:



按照样本维度进行拆分成 4 个 task,丢到线程池去执行。


3.5 Merge 流程


在预估完成之后,需要按照 conf/model 这个维度进行组织预估结果给 ranker, 最终的 response 如下图右子图所示。



3.6 特征提取框架的设计


特征提取框架线上、线下都会用到,这样比较好保证线上线下的一致性。所以设计的时候要同时考虑到线上线下的业务场景。


线上是将请求带来的数据与字典数据拼成一条条样本,进行特征提取的。而线下是编译 so,通过 mapreduce 来调用,样本是通过反序列化 hdfs 的一条条文本得到的。


3.6.1 特征配置文件格式


特征配置文件包括两部分: schema 部分,特征算子部分。


3.6.2 schema 部分



上图中有 5 个 schema 配置


user_schema:表示当前的用户相关信息,只在在线方式使用,由上游请求带过来。


item_schema:表示推荐的 item 相关信息,只在在线方式使用,一部分由请求带过来,一部分由字典文件中获取。


context_schema:表示推荐的上下文相关信息,只在在线方式使用,由上游戏请求带过来。例如:当前网络状态是 wifi 还是 4G。


all_schema: 表示最终的样本的 schema 信息。在线模式是将 user_schema, item_schema,context_schema 的各个字段放在 all_schema 的对应位置,离线模块是将 hdfs 的一行行文本,按照 all_schema_type 指定的类型进行反序列化生成的。不管是在线还是离线,特征框架的样本最终的字段顺序都是按照 all_schema 顺序存放的


all_schema_type: 离线模式才会用到,指定了各个 schema 的类型,这些类型名都是事先定义好的,在离线模式下,根据 schema 类型来反序列化各个字段。


3.6.3 特征算子配置部分



每个特征包括下面这些字段:


Name: 特征名字


Class:表示这个特征用的哪个特征算子类,对应代码里类名


Slot: 唯一标识一个特征


Depend: 表示该特征依赖哪些字段, 这个字段在上述 all_schema 中必须存在


Args: 表示传给特征算子的参数, 框架会转成 float 传给算子


Str_args: 传给特征算子的参数,以字符串的形式传递。


3.6.4 特征分 group(common 和 uncommon)


一次预估请求里面,所有样本的用户和 context 信息是一样的, 考虑到有些特征只依赖用户和 context 信息,这部分特征只需要提取一次,所有样本共用。


特征配置里面一部分特征会依赖其他的特征(例如组合特征、 cvm 特征),所以需要对特征的依赖进行分析,用来判断一个特征最终依赖的字段信息。



i_id 特征依赖 item 字段的 item_id,所以它是 uncommon 特征


u_a/net 特征只依赖 user_schema 或者 context 字段, 不依赖 item 字段,所以它是 common 特征 u_a-i_id 组合特征依赖 i_id 特征,间隔依赖 item_id,所以它是 uncommon 特征,


u_a-net 组合特征只依赖 u_a 和 network 字段,所以它是 common 特征,在特征提取的时候,一次请求只算一次。


注意:这里特征分 group 是异步字典更新线程来负责计算好的,不是请求来了现算的。


3.7 预估部分


前面提到了,一个请求里面指定了用哪个特征配置文件来提取特征,用哪个模型来预估。所有的模型都是有异步字典更新线程来负责更新。目前支持了 LR, FM, DSSM, Deep&Wide 等模型的预估,并且比较容易扩展。下面大概介绍下两个根据业务场景做了深度优化的模型:


3.7.1 FM 模型预估(LR 类似)



其中



考虑到业务场景,多个样本的 user/context 信息是一样的,那么线上 FM 的 预估可以写成这个形式:



标红部分所有样本都是一样的,一个请求只用计算一次。


3.7.2 DSSM(双塔)模型


双塔模型的网络结构如下图所示:



实际上一共有三个塔,C(context 信息),U(user 信息), I(item 信息), user 与 item 子塔得到的向量经过点积,再与 C 进行求和。


3.7.3 在线 serving 部分


考虑一些场景的 item 的信息变化比较慢,一般离线将 item 的子塔先计算好,得到向量,通过字典的方式动态加载。



在线的时候只用计算 c 塔,u 塔, 一个请求只有一条样本需要计算;I 塔部分由查字典得到向量。计算量相比全连接,大幅度减少。性能有大幅度的提升,但是由于 user 信息与 item 只有一层点积相乘,相比全连接,离线 auc 会下降 1%,所以比较适合召回或者粗排等对准确度要求不高的场景。在信息流广告、联盟广告业务替换原来的统计 ctr 粗排,综合指标提升 5、6 个百分点。


3.8 性能优化


预估引擎模块对时延要求很高,但是为了达到比较好的算法效果,特征规模又在不断的增加,所以在设计预估引擎的时候,做了很多性能优化的考量。主要包括以下几个方面:


(1)通过对象池来减少内存分配,提高性能。


(2) 特征字段的依赖都事先转化成下标,在提取特征的时候,就直接使用下标来取对应的字段,减少计算量。


(3)有些特征依赖其他特征结果,会频繁按照 slot 去查询对应结果,考虑到 slot 数据有限,采用数组来代替。


4. 总结


目前 predictor 模块支持了大多数推荐场景,包括信息流内容、信息流广告、应用市场、联盟、搜索、短视频、oppo 锁屏杂志、音乐等场景,部署在近 2000 台机器上,说明这套设计还比较稳定、扩展性比较好。目前支持业务平滑的切换到 dnn 模型,各个业务场景都取得一定的收益。


作者简介


肖超 高级数据挖掘工程师


10+年的广告系统工程落地经验,在 oppo 主要负责模型的特征提取、推理的工程落地工作。


更多精彩内容,请扫码关注【OPPO 互联网技术】公众号



发布于: 2021 年 07 月 20 日阅读数: 14
用户头像

还未添加个人签名 2019.12.23 加入

OPPO数智技术干货及技术活动分享平台

评论

发布
暂无评论
统一预估引擎的设计与实现