电商多目标优化小结

986 阅读6分钟
原文链接: zhuanlan.zhihu.com

背景

一直以来,电商场景就存在ctr、cvr、gmv、成交uv等多个目标,都是核心指标。理想情况下,提升ctr就能提升gmv,但据我所知,在一定程度上,ctr和gmv并不是完全一致。一般大幅的ctr提升,都会带来相关的gmv的提升,但小幅度的ctr提升就不一定了,有的时候还是负向的。

那是否只优化GMV就可以了呢?一方面,虽然电商公司最终追求gmv,但是ctr之类的指标,一定程度上代表着用户体验,也需重点关注。另一方面,GMV等成交指标,比起点击率相关的指标,更难优化。成交比起点击,数据稀疏很多,且受更多的场外因素影响。

大数公司这个问题并不严峻,每个目标训练个模型,拍个公式在线上揉在一起也能用。且在大公司,不同模型各自有团队在做,也没有很强的融合意愿。而我们不行,由于淘宝的网络效应,决定了我们无法依靠cpc竞价的模式走向盈利。因此,只做好ctr预估并不够,如何融合ctr、gmv、收入等目标,则成为我们重点要解决的问题。

去年ESMM出来时,我们已经做过一些相关尝试了,并没有很成功。当时的想法很朴素,希望从丰富的ctr样本中学习到一部分能够generalization的表达,辅助cvr的学习。ESMM这篇论文给了我们进一步的信心。另外,还从dupn的论文中借鉴了不少特征构建的想法,经过几个月的尝试,迭代了几版,拿到相对不错的结果。

模型总体策略

模型预估目标

用户在平台的行为遵循一定的顺序决策模式: impression->click->conversion,

CVR模型旨在预估用户在观察到曝光商品进而点击到商品详情页之后购买此商品的概率,即pCVR=p(conversion|click, impression)。 CVR模型的目标是预估条件概率pCVR,与其相关的两个概率为点击率pCTR和点击且转化率pCTCVR,它们之间的关系如下:

模型结构

样本按照正负样本比例=1:6的比例进行采样,这里的正样本指的是点击正样本。

借鉴阿里妈妈提出的ESMM模型(完整空间多任务模型),使用全站用户行为序列数据(包括点击、加购、收藏等),使用多任务学习的思路,引入了两个辅助的学习任务,在完整的曝光样本空间,分别拟合pCTR和pCTCVR,从而缓解传统CVR预估模型难以克服的样本选择偏差和训练数据稀疏的问题。


对于一个给定的展现,模型能够同时输出预估的pCTR、pCVR、pCTCVR。模型主要由两个子网络组成,左边的子网络用来拟合pCVR,右边的子网络用来拟合pCTR。两个网络的输出结果相乘,即为pCTCVR。 具体反映在目标函数中:


即用CTCVR和CTR的监督信息训练网络,隐式学习CVR。本次实验,只使用MTL模型的CVR网络产出的CVR预估分用于排序。

过程中一些有意思的点

预估偏置问题

一开始,我们希望直接采用ctcvr的结果,去替代线上的融合模型。但结果不太理想,我们做了很多数据分析,发现主要是由于ctcvr在预估上存在比较大的偏置。比如对订单量很少的样本,cvr预估会明显偏高。而在数据量相对丰富的头部样本,预估的分数没有表现出差异,过于集中。

尝试了几种校准方案后,效果不是特别理想。但发现模型结构中的cvr,校准的难度比ctcvr低,经过一段时间的尝试,上线效果还是不错的。

增加attention层的share

原有结构仅共享底层embedding表达,即CVR-task和CTR-task两个子网络的embedding层共享embedding向量(特征表示)词典。embedding层的参数占据整个网络参数的绝大部分,需要大量的训练样本才能充分学习到。

由于CTR任务的训练样本量远远超过CVR任务的训练样本量,ESMM模型中,embedding共享的机制能够使得CVR子任务能够从只有曝光没有点击的样本中学习,从而可以极大缓解训练数据稀疏的问题。

在此基础上,鉴于行为序的重要作用,我们把行为序列的attention参数共享。对比原结构:ctr、cvr、ctcvr的auc都有明显的提升。

DUPN类的特征

这个说法是我们内部发明的,其实一点也不严谨,只不过是我们借鉴了dupn那边论文中特征构建的方式。

不同的ID特征从不同规模上刻画了商品。比如shop、brand、cid、sale等属于比较泛化的特征,描述商品的一般特征;而商品ID属于非常个性化的特征,描述了商品的独特性。

在用户点击序列的基础上,拓展dupn的思路,根据用户当前或历史的行为,去预测用户的一些隐藏信息,比如偏好品牌、偏好类目、用户购买力、价格偏好、商品的评价数量、商品的价格、商品的销量、商品的喜欢数等泛化特征,这些信息与原始用户点击序列一起,会帮助模型学习商品表达。

训练本身的问题

虽然ESMM的思路很赞,但是联合训练本身就会带来新的问题,模型训练收敛更难了,且更慢了。在我们前期实践过程中,经常会发现logit飘了、nan了,除了一些代码bug外,就需要精细的调参和数据清洗了。

训练速度慢,对我们也是一个很大的挑战。我们的集群资源有限,特别要训练ctcvr模型,对数据量的要求更高,也是我们在ctcvr上进展缓慢的另一个重要原因。

可以预见,如果我们再增加更多的目标loss,这个问题会更尖锐。

一个小问题

在计算ctcvr_logits的时候,应该算sigmoid(ctr_logits) * sigmoid(cvr_logits),即两个网络的输出,做sigmoid之后再相乘。众所周知,TensorFlow中是不提供单独的cross entropy loss计算函数的,只有softmax_cross_entropy_with_logits和sigmoid_cross_entropy_with_logits两类。(不过现在Keras里有这种东西了,categorical_crossentropy可以指明输入的是logits而非softmax)。

重新实现了sigmoid + loss交叉熵函数,并对边界值进行了严格校验。但是在embedding向量从32维扩展到128维是,会出现输出Nan的情况,调小优化器的学习率,可以暂时避免出现Nan。

总结

这种mutil-task联合训练的方式,在我们线上实践中,比单独ctr和cvr模型分开训练,总体表现上要好不少,可以做到ctr不怎么降,gmv、收入有明显的提升。

再说个题外话,针对多目标的问题,我们还想过尝试RL。RL最吸引我的是long term reward,我们可以在reward中引入多目标。但RL的问题太多了,而现有的技术,大多已经是基于实时的行为seq做,RL目前没有给我特别大的吸引力。

最后,非常感谢参与其中的小伙伴们坚持不懈的努力。