@onejune
2021-10-15T00:03:06.000000Z
字数 9136
阅读 2083
MindAlpha
FTRL
ESMM
cvr
如图所示,最外面的大椭圆为整个样本空间S,其中有点击的事件(y=1)的样本组成的集合为,对应图中的阴影区域。传统的cvr模型是使用图中的阴影区域训练得到的,同时训练好的cvr模型又需要在整个样本空间做预估。
由于点击事件相对展现事件要少很多,因此只是样本空间S的一个很小的子集,从上提取的特征相对于从S中提取到哦特征而言是有偏的,甚至是很不相同。从而,按这种方法构建的训练样本集相当于是从一个与真实分布不一致的分布中采样得到的,这一定程度上违背了机器学习算法之所以有效的前提:训练样本与测试样本必须独立地采样自同一个分布,即独立同分布的假设。
训练样本从整体样本空间的一个较小子集中提取,而训练得到的模型却需要对整个样本空间中的样本做推断预测的现象称之为样本选择偏差。样本选择偏差会伤害学到的模型的泛化性能。
推荐系统展现给用户的广告数量要远远大于被用户点击的广告数量,同时有点击行为的用户也仅仅只占所有用户的一小部分,因此有点击行为的样本空间相对于整个样本空间来说是很小的,通常来讲,量级要少1~3个数量级。在淘宝公开的训练数据集上,只占整个样本空间的4%。而对Mobvista的normal广告来说,这个比例只有0.8%。这就是所谓的训练数据稀疏的问题,高度稀疏的训练数据使得模型的学习变得相当困难。
ESMM模型利用用户行为序列数据,在完整的样本数据空间同时学习点击率和转化率(post-view clickthrough&conversion rate,CTCVR),解决了传统CVR预估模型难以克服的样本选择偏差(sample selection bias)和训练数据过于稀疏(data sparsity )的问题。
用户在观察到系统展现的推荐商品列表后,可能会点击自己感兴趣的商品,进而产生购买行为。换句话说,用户行为遵循一定的顺序决策模式:impression → click → conversion。 CVR模型旨在预估用户在观察到曝光商品进而点击到商品详情页之后购买此商品的概率,即pCVR = p(conversion|click,impression)。
将(1)分成两部分:
综上可得:
对于(23)和(25)式:
下面对y和z的取值分情况讨论:
(1) 当z=1时,必有y=1(有转化必定有点击):
(2)当z=0时:
cvr的梯度公式为:
ctr梯度的更新需要分y=1和y=0两种情况考虑:
(a) y=1时:此时表示有点击无转化
即便一条样本被点击了,但是由于最终没有转化,随着ivr几率的大小,ctr模型的更新需要向反方向进行调整,在极端情况下,即ivr几率大于1,ctr的梯度反向更新;这样的修正是符合直觉的,没有转化的ctr的正样本的置信度小于有转化的正样本的置信度;
(b) y=0时:此时表示无点击也无转化
有了损失函数的梯度,我们就可以通过FTRL算法进行online learning。不过与传统的model train不同的地方在于:
FTRL的算法框架如下:
使用FTRL优化的EESMM代码如下:
算法步骤如下:
(1) 解析训练样本,分别提取ctr和cvr特征,并进行特征组合
(2) 根据λ1更新每个feature的weight
(3) 根据更新后的weight分别预估ctr和cvr
(4) 根据预估的ctr和cvr,分别更新两个子任务的梯度和学习率等超参变量
(5) 继续(1)
(6) 保存ctr和cvr模型
private void optimize(Sample sample) {
for (int i = 0; i < sample.strFeaturesCtr.size(); ++i) {
for (int m = 0; m < modelConfig.paraSize(); ++m) {
Parameter parameter = modelConfig.getPara(m);
if (featureInfo.z[m] <= parameter.ctr_lambda1 && featureInfo.z[m] >= -parameter.ctr_lambda1) {
featureInfo.omiga[m] = 0;
} else {
double rst = -1 / ((parameter.ctr_beta + sample.sqrtNCtr[i]) / parameter.ctr_alpha + parameter.ctr_lambda2) * (featureInfo.z[m] - Math.signum(featureInfo.z[m]) * parameter.ctr_lambda1);
featureInfo.omiga[m] = rst;
}
}
}
for (int i = 0; i < sample.strFeaturesCvr.size(); ++i) {
for (int m = 0; m < modelConfig.paraSize(); ++m) {
Parameter parameter = modelConfig.getPara(m);
if (featureInfo.z[m] <= parameter.cvr_lambda1 && featureInfo.z[m] >= -parameter.cvr_lambda1) {
featureInfo.omiga[m] = 0;
} else {
double rst = -1 / ((parameter.cvr_beta + sample.sqrtNCvr[i]) / parameter.cvr_alpha + parameter.cvr_lambda2) * (featureInfo.z[m] - Math.signum(featureInfo.z[m]) * parameter.cvr_lambda1);
featureInfo.omiga[m] = rst;
}
}
}
//calcuate gradient of loss(grad)
predict(sample, predictCtr, null, grad, sample.featureInfosCtr, false, true);
predict(sample, predictCvr, null, grad, sample.featureInfosCvr, false, false);
// ctr feature update
for (int i = 0; i < sample.featureInfosCtr.length; ++i) {
FeatureInfo featureInfo = sample.featureInfosCtr[i];
if (featureInfo == null) {
continue;
}
for (int j = 0; j < modelConfig.paraSize(); ++j) {
grad[j] = (sample.labelCvr - predictCtr[j]*predictCvr[j])*(1.0 - predictCtr[j])
/ Math.max((1.0 - predictCtr[j]*predictCvr[j]), 0.001) + sample.labelCtr - predictCtr[j];
grad[j] *= -1;
delta[j] = (doubleSqrt(sample.nCtr[i] + grad[j] * grad[j]) - sample.sqrtNCtr[i]) / modelConfig.getPara(j).ctr_alpha;
featureInfo.z[j] += grad[j] - delta[j] * featureInfo.omiga[j];
}
if (sample.labelCtr == 1) {
featureInfo.positive += 1;
} else {
featureInfo.negtive += 1;
}
}
// cvr feature update
for (int i = 0; i < sample.featureInfosCvr.length; ++i) {
FeatureInfo featureInfo = sample.featureInfosCvr[i];
if (featureInfo == null) {
continue;
}
for (int j = 0; j < modelConfig.paraSize(); ++j) {
grad[j] = (sample.labelCvr - predictCtr[j]*predictCvr[j])*(1.0 - predictCvr[j])
/ Math.max((1.0 - predictCtr[j]*predictCvr[j]), 0.001);
grad[j] *= -1;
delta[j] = (doubleSqrt(sample.nCvr[i] + grad[j] * grad[j]) - sample.sqrtNCvr[i]) / modelConfig.getPara(j).cvr_alpha;
featureInfo.z[j] += grad[j] - delta[j] * featureInfo.omiga[j];
}
if (sample.labelCvr == 1) {
featureInfo.positive += 1;
} else {
featureInfo.negtive += 1;
}
}
}
关于cvr预估的第三个重要问题“安装延迟",这也是MindAlpha解决的一个重要难题。那么我们是如何解决的呢?
预知后事如何,且听下回分解......
Mobvista AI中心算法一哥——尹广学
1 Entire Space Multi-Task Model: An Effective Approach for Estimating Post-Click Conversion Rate
2 Mobvista发布一站式全链路机器学习平台MindAlpha