文章作者:省钱快报算法团队

编辑整理:Hoh Xil

内容来源:作者授权

出品平台:DataFun

导读: 省钱快报是一家中小型综合类电商 APP,近 2 年平台规模有了较大增长,AI 在平台业务发展中发挥了巨大作用。 本文以推荐场景优化在省钱快报的发展为脉络,对于中小型电商公司在资源有限的客观条件下,对机器学习和深度学习的运用进行了架构和模型的相关探索。

业务背景

省钱快报推荐业务主要涉及首页 feeds 推荐、详情页相似商品推荐、收藏、个人中心等其他入口的推荐,业务指标着重关注 ctr/cvr/gmv 等,产品形态上和淘宝、京东等大致一样,不同之处在于下单的动作发生在第三方 app 上。简单来说用户在快报上的成交链路为浏览-> 点击-> 领券-> 跳转至第三方平台详情页并下单。因此不同于一般电商业务,快报的交易场景下转化漏斗较多,漏斗各层都需要关注。点击率、领券率、下单率每个环节都需要最优化,而各个指标又相互牵制相互影响,优化过程困难重重。

系统架构

▷▷ 数据流

数据流分为离线部分和实时部分,离线部分主要包含了 app 曝光日志、线上服务特征日志的收集、拼接、清洗等,大体上是一个 label match 的过程,这一过程的准确性决定了后续阶段模型能够给业务带来的收益,如果 label match 出错了,那训练出来的模型也必然是不可用的,一定不会带来好的应用效果。数据拼接的任务一定要尽可能的保证曝光、点击、订单的量和比例都能和 BI 报表的统计数据对的上,这是训练出可靠模型的前提。快报团队非常重视数据的准确性,我们从多个方面检验和保证最终数据的准确无误。这中间最重要的是需要设计一个跟踪用户请求、曝光、点击、订单整个转化链路的唯一 ID,我们称之为 traceID,主要通过这个 ID 来完成 label match 的过程。

▷▷ 模型训练和评估

快报模型团队在 tensorflow 的基础上自研开发了一套轻便灵活的模型训练系统,整个模型训练、评估和上线的过程都通过配置文件完成。另外鉴于训练资源的问题我们开发了增量训练的功能,即 base 模型为过去 90 天的数据训练的模型,之后的模型在 base 模型的基础上逐天增量训练,一般情况下增量训练能在一个小时内完成。同时相比于 batch 模型 ( 每天训练过去 90 天的模型 ) 增量模型能更好的学习到近期的数据分布,从 auc 上看这种训练方式能提升接近 1 个点的 auc。

模型训练部分有几点经验可以说一下:

  • 为了保持线上、线下特征一致性,我们在线上会直接把特征落下来。第一,省去线下再次进行特征抽取的过程。第二,可以尽可能的保证特征的一致性,避免因为线上、线下特征不一致导致模型效果不理想。
  • 训练数据集和测试数据集应该严格按照时间划分,防止发生穿越情况,测试数据集必须是"未来"的数据,一般我们会用昨天以前的若干天数据作为训练数据,用当天 ( 可能若干小时,一般建议选择 8 点到 12 点这段时间数据 ) 的数据作为测试数据,每次模型调参训练时训练集、测试集应当固定,以保证评估结果的可对比性。
  • 根据我们的经验,从远到近按天 shuffle 训练的效果要好于多天一起 shuffle 训练,auc 在千分位有若干点提升。
  • 评估主要看 auc、user auc。

▷▷ 模型在线服务

对于深度模型,模型服务模块我们直接使用了 tensorflow serving,FM 模型的服务是自己开发的 Java 微服务,不多表述,主要说一下 tf serving 在我们预估服务上的应用。

tf serving 有很多优秀的特性:

  • Google 开源,开箱即用,安装、使用简单
  • 支持模型版本控制、回滚
  • 支持并发,吞吐量高
  • 支持模型热更新
  • 支持 RESTful/HTTP 或者 gRPC 接口

自己开发深度模型的预测服务需要大量的工作,鉴于 G 厂已经开源了 tf serving,而其性能经过验证也是符合我们线上要求的,所以我们利用 tf serving 来完成模型的预测工作。由于在 FM 的阶段我们已经积累了很多模型服务的基础功能,例如模型热更新、模型上线/下线切换、版本管理等等,因此这些没有用 tf serving 自带的功能,而是主要通过集成 consul 来配合完成上述功能和预测服务的注册发现的。

在推荐业务的模型中我们用了大量 ID 类特征,所以开了比较大的特征空间 ( 2 的 28 次方 ),整个模型文件大概 19G 左右,线上预测的平均耗时在 10ms 左右。根据我们的经验,最能提升性能的优化就是对请求进行分片,并行请求模型服务,这样大概能提升 40% 左右的延时,当然耗时主要还是跟模型的复杂度有关,因此需要在模型复杂度 ( 效果 ) 和耗时之间做出合理权衡。

模 型 演 进

快报推荐模型的演进过程大致是从 FM->DeepFM->custom DNN 这样的一个过程,中间还经历了 Din/Dien/ESMM 等探索和过渡期。

▷▷ base 模型 ( FM )

一般的模型演进过程都是从 LR 或者 GBDT 开始,我们直接跳过了 LR 的阶段,直接过渡到了 FM 作为第一个模型。究其原因,FM 早在 13 年左右就已经开始被大范围使用,而我们在 18 年中才开始应用模型进行排序工作,FM 模型的效果已经得到各大厂的广泛验证,因此我们也比较有信心将 FM 作为 base model。

相比于历史更悠久 LR 模型,FM 模型可以自动做二阶的特征组合,相比于需要人工进行特征组合的 LR 来说 FM 在这方面完爆之。

看公式,FM 只是比 LR 多了后面交叉项的因式分解部分,实际上这也算是如今大行其道的 embedding 的雏形了。公式上看直接计算 FM 复杂度是 O(KN^2),但是上述公式在简化后可以在 O(KN)复杂度内计算,而在稀疏情况下往往大量 x 为 0,因此计算通常远远小于 O(KN)的复杂度,同时稀疏模型的模型文件也可以大幅压缩,在实际应用中我们去除了 w 和 v 全为 0 的参数,模型文件压缩了 80% 左右,同步模型所需的带宽和 predictor 服务所需的内存也大幅减少。

我们上线的第一版模型是 FM+FTRL 的组合,经过多次迭代 auc 大致在 0.68~0.69 左右,线上累计 ctr 提升 30%+。

▷▷ FM 到 DeepFM

经过小半年的迭代,FM 逐渐有点力不从心,在特征上挖掘和利用的差不多的时候我们逐渐开始把方向转向深度模型,希望深度模型能进一步带来效果提升。

深度模型在 15、16 年之后慢慢变成主流,在 Google 开源 tensorflow,发表 wide&deep 模型,推出 alpha go 之后,深度模型便彻底火了起来。但是在推荐/搜索领域深度模型真正应用的好的也就是头部几个大厂,小公司印象里有成功应用的并不多见。我们在 18 年底押注深度学习,经过调研后第一个模型便确定为 DeepFM,因为 FM 模型我们已经做的相当成熟练,因此从 FM 升级到 DeepFM 是理所当然。

DeepFM 本身并不复杂,从本质上讲只是在 FM 的基础上增加了若干层神经网络而已,embedding 层都是共享的,因此可以端到端的训练。相对于 FM 模型,DeepFM 的 NN 部分可以增加高阶的特征交互,弥补 FM 在高阶特征组合上的补足 ( 原理上 FM 可以任意阶组合,但是受限于计算复杂度,一般应用中只有二阶 )。相较于 FNN 这种把 FM 的输出当作 NN 输入的模型,DeepFM 可以端到端的训练,而且能同时保留二阶和高阶的特征组合。

在 FM 迁移到 DeepFM 后,并没有取得预期的效果,auc 和 FM 持平,经过多次调优依然不能超越 FM。究其原因,我们推测有如下两点:

  • 在我们的推荐排序场景下二阶的特征组合已经可以完全满足组合特征的需求;
  • 我们 FM 实现过程中未出现的特征参数是没有初始化的,也就默认是 0。但 tensorflow 会初始化一个随机值,这有可能影响到最终评估的效果。

后来翻阅各种资料,受 YouTube Net ( Deep Neural Networks for YouTube Recommendation )、和 DIN ( Deep Interest Network ) 等文章的启发我们把用户的点击序列加入到模型当中,用户的行为序列往往能非常好的刻画该用户的兴趣分布。和 DIN 不同的是,我们没有对用户行为序列做 attention,我仅仅把序列做了一次 sum。总的来说和 sum 相比 attention 并没有明显优势,而且计算量更大。另外 average 的效果也略差于 sum,看其他一些团队的经验貌似也有类似结论,所以我线上模型仅对序列做了 sum。这一次改动 auc 提升了 2 个点左右,线上 ctr 有接近 10% 的提升。

▷▷ 其他模型探索

在 DeepFM 成功上线并取得不错效果之后,我们又花了很长一段时间探索了诸如 DIN/DIEN、ESMM、DCN、xDeepFM 等当时一些思路新颖的模型,下面主要回顾一下在这些模型上的尝试。

1. DIN/DIEN

DIN/DIEN 是阿里妈妈团队的 ctr 模型,主要用在广告 ctr 预估上业务上,当然推荐排序场景也可以应用。上图中和 Base 模型相比 DIN 的主要思想是引入 attention,一般网络中对序列特征等多值/变长的特征处理方法通常是 embedding 之后做 sum/average/pooling 等操作,将其变为定长。序列有长有短,这类操作往往导致信息损失和误差。我们认为序列中每个元素都代表用户的兴趣点,引入 attention 之后便可以通过网络来学习整个序列,每个点都可以学到一个归一化的权重,整个序列可以通过加权和来表示,则兴趣的表示更加合理,理论上效果要好的多。

而 DIEN 更进一步引入 RNN 来提取兴趣,序列按时间先后顺序先通过 RNN 再对 RNN 的输出做 attention,可以兼顾长短期兴趣及兴趣的演进,因此比 DIN 更加合理。

我们在实验中使用了过去 30 天点击过的物品序列,物品所属类别序列,物品品牌序列等,序列长度为 50,其他特征方面和 DeepFM 差不多,经过多次迭代和调整,线下 auc 相比 DeepFM 没有提升,最终没有上线。DIN/DIEN 对数据要求比较高,我们最长商品点击序列定为 50,实际上大部分样本序列都非常短,序列的延续性不高,这些因素都影响了模型能力的发挥。

2. DCN、xDeepFM

DCN 和 DeepFM 相比主要区别是左边 FM 部分替换为一个 cross network 的网络,其中第 L+1 层表示为 X_{l+1}=X_0X^T_lw_l+b_l+X_l,可以简单理解为前一层和第 0 层 ( 即输入层 ) 的特征组合。虽然 cross net 可以非常方便的控制任意高阶的特征组合,相比 FM 的二阶组合更具优势,但是从公式可以看出每一层都与输入层有太强的关联,因此高阶的特征交叉和一阶特征有很大相关性。

微软出的 xDeepFM 则更进一步将 DeepFM 左边 FM 部分替换为 CIN ( Compressed Interaction Network ),xDeepFM 及 CIN 的结构如下图:

X^k即为 K 阶的特征组合,相比于 DCN 中的 cross network,CIN 表达能力更强。在 CIN 中第 K 层表示为X^k_{h,*} - \sum_{i=1}^{H_{k-1}}\sum_{j=1}^mW^{k,h}_{ij}(X^{k-1}_{i,*}*X^0_{j,*}),通过堆叠点乘和 1 维卷积操作,CIN 能更充分的进行高阶特征融合,在加上右边的 RNN,使得模型可以兼具更强的记忆和泛化能力。在我们的实验中,使用的特征和 base model 保持一致,仅仅改变网络结构,实验结果是 DCN 和 DeepFM 持平,xDeepFM 在 auc 上仅有非常微弱的优势,但其计算量太大,线上预估时长较长,最终没有上线。

3. ESMM

ESMM 也是阿里团队出的模型,其主要思想是将 ctr/cvr 两个目标放在统一的空间里进行训练,以解决 cvr 模型对于曝光样本的不可见和多目标优化、训练的问题,这个模型会放在后面多目标优化一节详细说明。

4. 自定义网络模型

经过 DIN/DIEN/DCN/xDeepFM 等一系列模型的研究之后,我们开始反思为什么这些大名鼎鼎的模型在我们的业务中没有达到预期?一方面业务不同、数据不同,没有一个万能的模型。另一方面我们在照搬这些模型的时候也许有一些细节没做好,这块后续还会进一步研究。之后我们从业务出发,逐渐开发和调整自己现有的网络结构和参数,最终我们的自定义网络经过多次迭代和优化,累计 auc 提升了接近 2 个点,下面是最终的网络结构。

模型效果对比

5. pairwise model

我们在 pairwise model 方面也做了好一些尝试,模型上改动不大,主要是 loss 部分改为 BPR ( Bayesian Personalized Ranking ) loss,训练数据由 pointwise 调整为 pairwise。

在 pair 构造方面主要尝试过以下几种方式构造 ( positive>negative ) 的样本对:

  • 同一次请求内行为:订单 > 点击 > 曝光,对曝光进行下采样,控制样本量
  • 同一次 session 内行为:订单 > 点击 > 曝光
  • 用户一天内推荐列表所有行为:订单 > 点击 > 曝光,对曝光进行下采样,控制样本量

以上方案均按 skip above 思路只用最后一次点击以上的曝光样本做负样本。

pairwise 方法考虑到了 item 之前的偏序关系,相比 pointwise 方法在列表排序场景中显得更合理,但是在实际应用中没有达到预期的效果。我们总结了 pairwise 方法的一些不足之处:

  • 评估指标调整为 ndcg,但是用下单、点击、曝光来作为标签也不是很合理
  • 样本量和 pointwise 方法相比会急剧膨胀,如果不做合理的下采样,模型将难以训练
  • 对数据噪声更敏感,一个错误数据可能会影响到许多 pair
  • pair 的构造过程相当于强行改变来原有的数据分布,样本构造不合理则模型很难有好的效果,而构造合理的 pair 往往很困难

根据我们经验,pairwise 方法的难点主要集中在样本构造方面,想要合理的构造训练的 pair 对是困难的,订单和点击构造多少 pair、订单和曝光构造多少 pair、点击和曝光构造多少 pair 都是很难确定出合理的数值的,考虑的训练成本问题需要进行负采样,这也会损失部分信息,从我们的经验来讲,总体上 pairwise 方法不太适合做 feeds 类产品的排序而更适合在搜索领域去应用。

  1. 模型总结

在省钱快报推荐业务近 2 年的模型应用中,我们总结了以下一些经验:

  • 在模型应用过程中选一个好的 base model 是第一步,强烈推荐第一版模型先上 LR/GBDT 等模型。第一版模型主要是打好一个基础,在数据、特征、label match、模型评估等方面先建立起完善的 pipeline 和环境,之后才能更好的发力。如果第一个模型太过复杂,模型可解释性差,那就不容易排查问题,而且复杂的模型对数据/特征/评估等环节的要求更高,因此第一版模型不宜采用太复杂的模型。
  • 没有通用的模型,只有适合的模型,模型要随业务变动,往往根据业务特点针对性挖掘一些好的特征、增加一些训练数据比应用更新更复杂的模型来的更直接,所以我们也一直强调数据大于模型。
  • 线下实验在评估的时候,一定要对齐测试样本,如果不能对齐测试集则 auc 就没有可比性。
  • 每次线下实验不应该加太多特征、调太多参数,尽量保持耐心,每次实验最好只改变一处,这样方便得到可靠的实验结论。
  • 轻易不要改变原始数据的分布。

对于深度推荐系统,有如下一些经验与思考:

▷ 向量化的必要性:

应该先从一个更宏观的角度来看向量的问题,不只是在推荐系统,或是 NLP 这些,而应该一切事物。如果前一句成立,则向量化就是必要的。而为什么说一切事物,其灵感直接来源于 NLP,如 E(法国) + E(首都) ~ E(巴黎)。如一个个词一样,所有事物都在某个空间中可以用向量准确的表达,在推荐系统则可能有 E(couponA) + E(couponB) + … ~ E(couponC)。但是,显然我们没有 NLP 中对词的表达准确,所以一个优化的思路就是如何更准确的表达向量。要更准确,对应向量所要含有的信息量就应该足够大,显然现在使用的 16 维度向量不可能很好的包含这些信息。理想状态下,人看到一个商品,基本已经知道了这个商品的大部分特征,如类目,品牌,大致价格等。目前的算法是死的,要人为的指导它学习的方向,所以用商品向量 + 类目向量 + 品牌向量…作为一个商品就会有更足的信息这也是加类目序列的初衷。同时这样也可以看作将原来 16 维度的商拓展到了 16*N,当然这样的拓展是不如直接使用高纬度向量的。

▷ 关于不做 Mask:

输入的序列必须定长,假设取用户历史最近的 50 个点击,必然有很多用户没有 50 个点击。对于点击序列不做 Mask 将输入相同的随机初始化的向量,如下所示,全 0 向量对"缺失商品"的表达能力,很可能是不如网络学习的结果的。注意:这种方法是对于随机初始化的向量,且向量可学习。


序列:[S:12312,S:2345235,S:345345,S:-1,S:-1,S:-1,S:-1,S:-1,...]
S:-1 -Hash-> 325344354 -embeding_lookup-> [.3,.5,.6,.7...]
S:-1 -Hash-> 325344354 -embeding_lookup-> [.3,.5,.6,.7...] -Mask-> [.0,.0,.0,.0....]

▷关于特征交叉:

很多方法如 PNN,LatentCross 都是在对特征做交叉以更深的挖掘特征中信息。快报目前的特征是全部哈希后的随机初始化向量,在同一个特征域内,网络能对这种交叉关系进行比较好的学习。所以 PNN 中的以特征做点积、内积的方式并没有收益。

DeepFM,FM 也是一种特征交叉的方式,不同于一般的经验,在我们的数据集上去掉 FM 部分是有一些收益的。我们的理解是普通特征经过了 embeeding ( 如性别 0, 1-> 性别向量 X1, X2 ) 再通过网络训练,一方面本身的信息量放大了,另一方面特征直接的交叉关系可被网络学习到。所以 DeepFM 在我们的特征工程下是负收益。

多 目 标 优 化

快报推荐业务主要关注 ctr、cvr 两个指标 ( 当然还有人均 gmv、人均订单、arpu 等 )。

▷▷ ctr/cvr 平衡

针对 ctr、cvr 我们分别训练了 2 个单独的模型来做针对性优化,其中 ctr model 以曝光为负样本,点击为正样本,cvr model 以点击为负样本,下单为正样本。

做过电商的都知道,ctr 和 cvr 往往反着来的,提升 ctr 的同时 cvr 就可能下降,提升 cvr 那么 ctr 就可能下降,算法同学需要权衡 ctr、cvr 两个指标取得一个最优解。

我们线上最终排序的时候基本上是 CTR^t*CVR 这种方式,对于 t 的确定,我们通过线下计算来确定,基本上希望按最终公式排序后的点击 auc 能够不降或者微降,同时下单 auc 能提升,因为总的来说先有点击后有订单,所以点击这一步需要保证不能降太多。最终我们用这种方式上线后 ctr 微降 1% 左右,cvr 提升 10%,总体达到了不错的效果。

目前我们的目标还比较少,基本通过上述公式可以比较好的满足业务需求。

我们也尝试过在线上通过一个简单 lr 模型来更好的拟合 ctr 和 cvr,但是最终效果不太理想,从总的思路来讲我们需要让整个转化漏斗的每个环节的敞口最大化。

▷▷ ESMM

在 ctr 和 cvr 分别建模的情况下 cvr 模型由于下单样本相对于曝光/点击样本来说非常少,导致 cvr 模型难以充分训练。另外只用点击到下单的样本则丢失了曝光样本当中的大量信息,模型的预估也存在偏差。受到阿里 ESSM 模型的启发我们也尝试将 ctr、cvr 融合在一个模型进行建模。底层的输入一致,ctr 任务和 cvr 任务共享 embedding 层,对于 cvr 来说可以在整个曝光的大空间内学习 embedding 向量。

因为有两个网络因此模型训练时长大致也增长一倍,从模型服务的角度讲好处是请求模型时只需要请求一个模型就可以。在具体应用时我们可以得到三个预估数值:pctr、pcvr、pctcvr,在线下评估的时候分别评估了 pctr 对应的点击 auc,pcvr 对应的下单 auc,二者组合对应的点击/下单 auc,从最终线下评估结果看 ESMM 要差于两个模型分开训练,最终线上的效果也低于基线。

ESMM 之所以没有达到预期,猜测有若干原因:

  • 在我们的场景中往往 ctr 高的商品 cvr 低,cvr 高的商品 ctr 低,两个任务的关联性有时候刚好是反的。
  • 我们没有精细调整两个任务 loss 的权重,也许这块可以优化。
  • pcvr 其实实际是曝光到下单也即 pctcvr,论文中关于 ctr、cvr、pctcvr 三者的关系说的有点模糊。

在 ESMM 方面有应用经验的同行可以给点意见,一起交流分享一下。

模 型 调 优

▷▷ 超参数及特征上的探索

由于模型较为复杂,数据量大,训练成本高,无法用网格法暴力调参数,使用分阶段调参。

顺序为:隐层大小-> 学习率->Batch Size->Drop out/L1/L2 的顺序进行参数调优。

在快报的数据集分布上,改变学习率带来的提升比较明显,由于 Adam 优化器占用内存大,使用 Adagrad 所以对应的 batch size 较小,可能不同于其他文章中分享的经验。网络层数越高准确度越高,结构影响很小,当达到一定层数后再提升带来的收益很小,综合考虑计算成本取了 500*300 层。

输入的数据全部是哈希之后 embedding 的所以有一个哈希空间和 embedding 向量维度的取舍,向量维度越高越准确,哈希空间也是。所以要根据机器内存综合考虑哈希冲突率和向量维度的影响。

下表为在其他参数不变的情况下,调整不同参数带来的 AUC 变化。

▷▷ 激活函数

激活函数方面,选择了常用的 Relu。尝试过 prelu 和 dice ( DIN 中提出的激活函数 ),有略微的正收益,其中 Dice>Prelu。

值得一提的是 Dice 激活函数在运算中进行了相当于 BatchNorm 的操作,在预测中 Batch 有变化时,输入结果将随之变化。例如,输入(x_1, x_2)得到预测结果(y_1, y_2)和输入(x_1,x_2,x_3)得到预测结果(z_1,z_2,z_3)时会导致(y_1 !=z_1, y_2 != z_2),不便于 Debug,故未应用在线上模型中。

▷▷ 特征处理

数据和特征对于模型的重要度不言而喻,在特征挖掘方面因业务而异,没有统一的标准,我们主要分用户侧特征、商品侧特征、店铺特侧特征、上下文及交互特征等。

在特征处理上我们基本分两大类方式:

  • ID 类特征和 category 特征在 id 化 ( 为了方便我们采用 hash 方式 ) 后做 embedding。
  • 数值类特征按等频分桶 ( 部分特征也会根据业务做一些数值变换 ) 进行离散化之后做 embedding。

对于缺失值我们以业务字段对应的默认值填充。另外关于特征选择,我们首先会评估特征的覆盖率,准确性和获取难度等。然后会做一下相关性分析,经过以上步骤如果特征可用,我们会先直接加入该新特征,并在后续考虑是否做一下特征交叉等。

有了深度模型之后特征选择、特征工程往往容易被忽视,因为什么特征都全部 embedding 之后放到网络里面就可以了,但是原则上加特征之前还是需要做个简单评估,并且建议特征最好一次加 1-2 两个,加特征实际上是有成本的,尽量避免一次性进行大批量的特征加入。

▷▷ position bias

推荐列表上不同位置的点击率天然有差别,我们在做排序时,需要考虑到这种差别。因为 position 是排序之后确定的,因此在预测时是不知道的,一般的做法是在训练时加入 position 信息作为特征,在预测时给 position 一个默认值,以达到消除 position 偏置的效果。一开始我们也是按照这个思路去做的,在预测时尝试给过多个默认 position,但是在线上实验时,效果总是不及 baseline。后来无意中看到 Google 的 Rules of Machine Learning- Best Practices for ML Engineering 一文中有关 positional feature 的 rule 才恍然大悟,原文引用如下,希望对在研究 position bias 相关内容的同行有所帮助:

Note that it is important to keep any positional features somewhat separate from the rest of the model because of this asymmetry between training and testing.

Having the model be the sum of a function of the positional features and a function of the rest of the features is ideal.

For example, don’t cross the positional features with any document feature.

也即在使用位置特征的时候需要保证位置特征和其他特征相互独立,而不论 FM 还是 NN 模型中位置特征和其他特征都有交互,因此线上效果一直不符合预期。受此启发我们重新调整了模型之后上线效果和 base 比上下小幅波动,基本持平,之所以没有预期的提升,我们认为在我们的场景中 position bias 的影响并不大。

模 型 serving

▷▷ tf-serving

tf serving 这块没有太多可说的,部署也很方便,直接用 docker 去安装就可以了,非常简单。稍微不同的地方是我们对它做了一点包装,给 tf serving 集成到了 consul,以方便模型预测服务的微服务化。由于 tf 模型内存消耗大,我们模型更新的时候不是热加载的,模型更新过程中模型服务会中断,这个时候系统会先把要更新的模型实例从 consul 上解除服务注册,等到模型更新完成后重新注册到 consul 上,然后继续提供模型预测服务。考虑到流量问题我们模型的更新是一台一台依次更新的。

▷▷ online feature

网上很少有人介绍模型预测部分线上特征的构造,大体上基于 tensorflow 的模型在预测阶段有两大方案:

  • 所有特征提取、构造的代码写成 op,打到模型文件里。这种方案输入模型预估服务的一般是原始文本/数值特征,特征的提取转换都发生在预估服务中,也就是 tensorflow serving 帮我们完成特征提取/转换的工作。
  • 特征的提取和构造单独抽出来,作为一个服务,客户端先请求特征服务,由特征服务构造特征并请求模型预估服务。这种方案下特征处理在模型外部,输入到模型的是处理好的数值特征。

两个方案各有优缺点,方案一更直观一些,缺点是需要单独编写 op,还需要保证特征一致性,