论文地址:​​Entire Space Multi-Task Model: An Effective Approach for Estimating Post-Click Conversion Rate​

一、前言

点击率(Click-Through Rate,CTR)和转化率(Conversion Rate,CVR)在信息检索、推荐系统、在线广告等应用场景下都是非常重要的两个指标,因为它们直接关系到产品的盈利。

关于 CVR,其实大部分情况下指的是点击后转化率,即 pCVR(post-click Conversion Rate),这就会与 CTR 形成一个顺序和传递关系,因此在很多场景下,这个指标则更为重要,如:

  • 在电商推荐中,最大化 GVM(商品交易总额)是平台的重要目标之一,而 GMV 可以拆解为流量×点击率×转化率×客单价,可见点击率和转化率是优化目标非常重要的两个因子,而这两个指标的共同优化,其实就是一个多目标排序问题;
  • 在以 oCPC(Optimized Cost Per Click,以目标转化为优化方式的点击出价)为主的智能广告投放平台中,用 pCVR 作为目标来调整每次点击出价, 从而使 CPM(Cost Per Mille,千人成本)最大化 。

二、传统CVR预估存在的问题

传统 pCVR 预估采用的是类似 CTR 预估的技术,即通过点击的样本子集进行训练,推理的时候对整个展现(曝光)样本空间进行推断。但这种方法存在很多问题:

  • 样本选择偏差 (Sample Selection Bias, SSB)

后一阶段的模型基于上一阶段的采样后的样本子集进行训练(CVR模型的样本是点击的样本,不包含未点击的样本),但是最终是在全样本空间进行推理,这带来了严重的模型的泛化性问题

  • 样本数据稀疏 (Data Sparsity, DS)

通常后一阶段模型的训练样本规模通常远低于前一阶段任务,而且会出现正负样本极度不均衡。加大了模型训练的难度,同样带来了泛化性问题。(比如转化行为中的“付费”,正样本就极为稀疏)

  • 延迟反馈(Delayed Feedback)

点击后的转化(conversion)很可能延时发生,比如看过一个商品,但并没有马上去买,过了几天才去购买,给建模带来困难。(相关Paper: ​​Modeling Delayed Feedback in Display Advertising​​)

【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_多任务学习

三、学术界当前的解决方案

对于前两个问题,学术界也有很多解决方法,如:

缓解 样本稀疏(DS) 问题

  • 分层 CVR 模型(Hierarchical Estimatator)

针对不同的特征构建不同的分层分类器,并分别估算分布参数,然后使用逻辑回归来组合这些单独的分类器。这种方法可以粗力度预估以解决 DS 问题,但依赖先验知识来构建分层结构,难以在具有数千万 user 和 item 的推荐系统中应用。

  • 过采样方法(Oversampling Method)

通过复制稀少类的样本缓解不平衡,这有助于缓解数据的稀疏性,但是对采样率很敏感。

缓解 样本选择偏差(SSB) 问题

  • AMAN(All Missing As Negative,缺失值作为负样本)

应用随机抽样策略来选择未点击的展现作为负样本。它可以在一定程度上通过引入缺失观察的样本来 消除 SSB 问题,但通常会导致预测值偏低(训练样本负样本变多)。

  • 无偏差采样(Unbias Sampling)

使用 ​​蒙特卡洛拒绝采样法(Rejection Sampling)​​ 来拟合样本实际分布,制造无偏差采样,但会遇到数值不稳定问题。

上面的几种方法多多少少都存在一些问题,因此 SSB 和 DS 问题都没有被很好地解决,而且没有一个方法应用序列行为的信息。

2018 年阿里妈妈算法团队发表了一篇论文:《Entire Space Multi-Task Model: An Effective Approach for Estimating Post-Click Conversion Rate》,提出了 ESMM(Entire Space Multi-Task Model,完整空间多任务模型), ESMM 创新地利用用户行为序列数据,在完整的样本数据空间利用 MTL 同时学习点击率和转化率(post-view clickthrough&conversion rate,CTCVR),解决了传统 CVR 预估模型难以克服的样本选择偏差(SSB)和训练数据过于稀疏(DS)的问题。

四、ESMM算法原理

对于转化率而言,完整的业务流应该是:曝光(impression)→ 点击(click)→ 转化(conversion)。用户的行为遵循一定的顺序决策模式,以电商和广告为例,用户看到曝光的推荐,对感兴趣的内容会点击进入详情页进一步了解,之后才考虑是否购买发生转化。因此,对于这种顺序递进关系,整个任务可进行数学化描述:

假设训练数据集为 【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_深度学习_02【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_ESMM_03【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐系统_04 分别表示 click 和 conversion,其中的样本 【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_多任务学习_05 是从域 【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐算法_06 中按照某种分布采样得到的,【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐系统_07 是特征空间,【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐算法_08【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_多任务学习_09 是标签空间,【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐算法_10 为数据集中的样本总数量。在 CVR 预估任务中,【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_深度学习_11 是高维稀疏多域的特征向量,【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_ESMM_03【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐系统_04 的取值为 0 或 1,分别表示是否点击和是否购买。【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_多任务学习_14

CVR 模型的目标是预估条件概率 pCVR ,与其相关的两个概率为点击率 pCTR 和点击且转换率 pCTCVR ,它们之间的关系如下:
【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐算法_15
所以 【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐系统_16,即:
【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐系统_17
可见, pCVR 可以由 pCTR 和 pCTCVR 推导得出。从原理上来说,相当于分别单独训练两个模型拟合出 pCTR 和 pCTCVR,再通过 pCTCVR 除以 pCTR 得到最终的拟合目标 pCVR 。实际操作中,由于 pCTR 通常很小,pCTCVR 除这个很小的数,容易溢出。故 ESMM 采用了乘法的形式,避免了除法,且能够使 pCVR 的值在 [0, 1] 区间。由此可见,这三个预估模型都可以在整个样本空间上建模得到。

根据上面的分析,可知 pCTR 和 pCTCVR 是模型需要估计的两个主要因子,ESMM 使用了 MTL 方法,引入两个辅助任务,分别拟合 pCTR 和 pCTCVR,把 pCVR 当做一个中间变量,模型结构如下 :

【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_多任务学习_18


整体来看,对于一个给定的展现(曝光),ESMM 能够同时输出预估的 pCTR、pCVR 和 pCTCVR。它主要由两个子神经网络组成,左边的子网络用来拟合 pCVR ,右边的子网络用来拟合 pCTR。两个子网络的结构是完全相同的,并且共享 Embedding 参数。这里把子网络命名为 BASE 模型(这个 Base 模型结构,也是近年来基于 DL 的 CVR 预估模型比较经典的网络结构,因此论文中也简单的使用了这种结构,但真正用于生产环境下的结构可能要比这个复杂的多),两个子网络的输出结果相乘之后即得到 pCTCVR,并作为整个任务的输出。

ESMM 的损失函数由两部分组成,对应于 pCTR 和 pCTCVR 两个子任务,其形式如下:
【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_深度学习_19
其中,【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐系统_20【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_深度学习_21 分别是 CTR 网络和 CVR 网络的参数,【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐算法_22

注意,这里的pCVR 是隐式学习得到的,因为这里pCVR(粉色节点)仅是网络中的一个variable,没有显示的监督信号。

ESMM 可以有效解决传统 CVR 预估模型的一些问题,具体表现如下:
解决样本选择偏差(SSB)问题

  • 全空间建模: 和 CTR 一样,在全部展现样本上建模

CTR对应的 label 为 click,而 CTCVR 对应的 label 为 click & conversion,这两个任务都是使用全部样本的,而CVR又是根据这两者得出,因此 pCTCVR 和 pCTR, pCVR 都定义在全样本空间。通过分别估算单独训练的模型 pCTR 和 pCTCVR 并通过关系式可以获得 pCVR,三个关联的任务共同训练分类器,能够利用数据的序列模式并相互传递信息,保障物理意义。

  • 解决样本稀疏(DS)问题

迁移学习:在 ESMM 中,CVR 网络的 Embedding 参数与 CTR 任务共享,遵循特征表示迁移学习范式。Embedding Layer 将大规模稀疏输入映射到低维稠密向量中,主导深度网络参数。CTR 任务所有展现样本规模比 CVR 任务要丰富多个量级,该参数共享机制使 ESMM 中的 CVR 网络可以在未点击展现样本中进行学习

五、ESMM的性能提升

在 ​​阿里公开的数据集​​ 上,各个方法对比如下表所示:

【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_ESMM_23


其中,几个模型对应的方法如下:

  • BASE:经典的 CVR 预估模型结构,也就是 ESMM 左半边部分;
  • AMAN、OVERSAMPLING、UNBIAS:分别对应上面提到的几种学术界缓解 SSB 和 DB 问题的方法;
  • DIVISION: 先分别训练出拟合 CTR 和 CTCVR 的模型,再拿 CTCVR 模型的预测结果除以 CTR 模型的预测结果得到对 CVR 模型的预估;
  • ESMM-NS:是 ESMM 模型的一个变种,其在 ESMM 模型的基础上去掉了特征表示共享的机制。

在淘宝生产环境数据集上几种不同算法的性能测试对比 :

【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_深度学习_24


ESMM 在线 AB 测试效果的提升:

【推荐系统多任务学习MTL】ESMM 论文精读笔记(含代码实现)_推荐系统_25

六、代码实现

参考 github 代码

  1. ​构建分布式Tensorflow模型系列:CVR预估之ESMM(杨旭东 知乎)​
  2. ​代码实现1 (杨旭东)tensorflow​
  3. ​github(浅梦学习笔记)5.9K star​
  4. ​代码实现2 keras​

核心代码如下(参考 上述链接2)

def build_mode(features, mode, params):
net = fc.input_layer(features, params['feature_columns'])
# Build the hidden layers, sized according to the 'hidden_units' param.
for units in params['hidden_units']:
net = tf.layers.dense(net, units=units, activation=tf.nn.relu)
if 'dropout_rate' in params and params['dropout_rate'] > 0.0:
net = tf.layers.dropout(net, params['dropout_rate'], training=(mode == tf.estimator.ModeKeys.TRAIN))
# Compute logits
logits = tf.layers.dense(net, 1, activation=None)
return logits

def my_model(features, labels, mode, params):
with tf.variable_scope('ctr_model'):
ctr_logits = build_mode(features, mode, params)
with tf.variable_scope('cvr_model'):
cvr_logits = build_mode(features, mode, params)

ctr_predictions = tf.sigmoid(ctr_logits, name="CTR")
cvr_predictions = tf.sigmoid(cvr_logits, name="CVR")

prop = tf.multiply(ctr_predictions, cvr_predictions, name="CTCVR")

if mode == tf.estimator.ModeKeys.PREDICT:
predictions = {
'probabilities': prop,
'ctr_probabilities': ctr_predictions,
'cvr_probabilities': cvr_predictions
}
export_outputs = {
'prediction': tf.estimator.export.PredictOutput(predictions)
}
return tf.estimator.EstimatorSpec(mode, predictions=predictions, export_outputs=export_outputs)

y = labels['cvr']
cvr_loss = tf.reduce_sum(tf.keras.backend.binary_crossentropy(y, prop), name="cvr_loss")
ctr_loss = tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(labels=labels['ctr'], logits=ctr_logits), name="ctr_loss")
loss = tf.add(ctr_loss, cvr_loss, name="ctcvr_loss")

ctr_accuracy = tf.metrics.accuracy(labels=labels['ctr'], predictions=tf.to_float(tf.greater_equal(ctr_predictions, 0.5)))
cvr_accuracy = tf.metrics.accuracy(labels=y, predictions=tf.to_float(tf.greater_equal(prop, 0.5)))
ctr_auc = tf.metrics.auc(labels['ctr'], ctr_predictions)
cvr_auc = tf.metrics.auc(y, prop)
metrics = {'cvr_accuracy': cvr_accuracy, 'ctr_accuracy': ctr_accuracy, 'ctr_auc': ctr_auc, 'cvr_auc': cvr_auc}
tf.summary.scalar('ctr_accuracy', ctr_accuracy[1])
tf.summary.scalar('cvr_accuracy', cvr_accuracy[1])
tf.summary.scalar('ctr_auc', ctr_auc[1])
tf.summary.scalar('cvr_auc', cvr_auc[1])
if mode == tf.estimator.ModeKeys.EVAL:
return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics)

# Create training op.
assert mode == tf.estimator.ModeKeys.TRAIN
optimizer = tf.train.AdagradOptimizer(learning_rate=params['learning_rate'])
train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

七、常见问题

  • CTR低,CVR一定低吗

不一定。想象一个场景,一个item,由于某些原因,例如在feeds中的展示大图很丑,它被某个user点击的概率很低,但这个item内容本身完美符合这个user的偏好,若user点击进去,那么此item被user转化的概率极高。

CVR预估模型,预估的正是这个转化概率,它与CTR没有绝对的关系,很多人有一个先入为主的认知,即若user对某item的点击概率很低,则user对这个item的转化概率也肯定低,这是不成立的。更准确的说,CVR预估模型的本质,不是预测“item被点击,然后被转化”的概率(CTCVR),而是“假设item被点击,那么它被转化”的概率(CVR)。这就是不能直接使用全部样本训练CVR模型的原因,因为咱们压根不知道这个信息:那些unclicked的item,假设他们被user点击了,它们是否会被转化。如果直接使用0作为它们的label,会很大程度上误导CVR模型的学习。

  • ESMM的结构是基于“乘”的关系设计——pCTCVR=pCVR*pCTR,是不是也可以通过“除”的关系得到pCVR,即 pCVR = pCTCVR / pCTR ?例如分别训练一个CTCVR和CTR模型,然后相除得到pCVR

其实也是可以的,但这有个明显的缺点:真实场景预测出来的pCTR、pCTCVR值都比较小,“除”的方式容易造成数值上的不稳定。作者在实验中对比了这种方法。

  • 为什么不直接预测曝光维度的转换率呢? 而是需要预测两个值。或者说这种方式与直接预测曝光转换率的差异在哪?

这个模型最终可以输出曝光转化率的。直接预测曝光转换率会存在严重的正负样本不平衡的问题;同时采取两阶段学习,可以共享embedding,有迁移学习的效果。

参考

  1. ​推荐系统中的多任务学习(卢明冬)​
  2. ​阿里CVR预估模型之ESMM​