[转]增益模型(Uplift Modeling)的原理与实践

这篇文章写的真的很不错,原理讲解的比较清楚透彻。近期有项目要做某种营销方法的增益模型,从这篇文章中可以比较系统的看到增益模型的实现方法、模型评价等,尤其是对公式的推导,可以说非常专业、非常有帮助。

原文章: 智能营销增益模型(Uplift Modeling)的原理与实践

其他好的参考文章:如何用增益模型,探讨精准营销的底层逻辑?(营销逻辑)-正经科普

 【Uplift】建模方法篇 - 知乎

因果推断笔记——uplift建模、meta元学习、Class Transformation Method(八)_悟乙己的博客-CSDN博客

文章目录
增益模型因果与推论(Causal Inference)
增益模型的表示
差分响应模型(Two-Model Approach)
模型优缺点
差分响应模型升级版(One-Model Approach)
Class Transformation Method
Class Transformation的两个假设
Modeling Uplift Directly
增益模型的评估
uplift 柱状图
Qini曲线(Qini curve)
累积增益曲线(Cumulative Gain curve)
优惠券发放Demo
差分响应模型
Class Transformation Method
传统响应模型
模型评估
Python Uplift Modeling工具包:Pylift
总结
训练样本收集
多维度建模与个性化广告推送
Reference
增益模型因果与推论(Causal Inference)
常用的点击率预测模型,称为响应模型(response model),即预测用户看到商品后点击的概率。在智能营销的发放优惠券场景下也可以使用这种模型,即用户看到优惠券后购买商品的概率。但在这种场景下,很自然会想到,用户是本来就有购买的意愿还是因为发放了优惠券诱使用户购买?对有发放优惠券这种有成本的营销活动,我们希望模型触达的是优惠券敏感的用户,即发放的优惠券促使用户购买,而对优惠券不敏感的用户——无论是否发券都会购买——最好不要发券,节省成本。营销活动中,对用户进行干预称为treatment,例如发放优惠券是一次treatment。我们可以将用户分为以下四类:

persuadables不发券就不购买、发券才会购买的人群,即优惠券敏感人群
sure thing:无论是否发券,都会购买,自然转化
lost causes:无论是否发券都不会购买,这类用户实在难以触达到,直接放弃
sleeping dogs:与persuadables相反,对营销活动比较反感,不发券的时候会有购买行为,但发券后不会再购买。
建模时主要针对persuadables人群,并且要避免sleeping dogs人群。如果使用reponse model,则难以区分这几类人群,因为模型只预测是否购买,但人群的区分需要明确是否因为发放优惠券才导致了购买行为,这是一个因果推论问题(causal inference)。在优惠券发放Demo一节可以看到,response model(一个预测模型)可以取得很好的效果(转化率很高),但转化的用户中persuadable的比例相当少,并不是营销中的target。

营销活动中,我们要预测的是某种干预(treatment)的增量,这种模型称为增益模型(uplift model)。设G GG表示某种干预策略(如是否推送广告),X \boldsymbol{X}X表示用户特征,Y = 1 Y=1Y=1表示用户输出的正向结果(如下单或点击):

Reponse model: P ( Y = 1 ∣ X ) P(Y = 1 | \boldsymbol{X})P(Y=1∣X),看过广告之后购买的概率
uplift model: P ( Y = 1 ∣ X , G ) P(Y = 1 | \boldsymbol{X}, G)P(Y=1∣X,G),因为广告而购买的概率
增益模型的表示。因此增益模型依赖AB实验的数据。

下面介绍三种增益模型建模方法。

差分响应模型(Two-Model Approach)
差分响应模型很直觉。分别对AB实验的实验组和对照组数据独立建模,预测时分别实验组模型和对照组模型预测用户的分数,两个模型预测分数相减就得到了uplift score。

实验组是使用干预策略的用户(treatment),对照组是未使用干预策略的用户(control),正样本都是下单用户

模型优缺点
差分响应模型简单粗暴,还很直觉。两个独立的模型分开训练容易累积误差(两个独立模型的误差会累加传递到最终的uplift score)。不过考虑到实现简单迅速,实践中可以作为baseline使用。

差分响应模型升级版(One-Model Approach)
差分响应模型的训练数据和模型都是各自独立的,可以分别在训练数据层面上打通以及在模型层面上打通,得到升级版的差分响应模型。

在实验组和对照组的用户特征中,加入与T TT有关的特征,实现数据层面的打通,即实验组和对照组合并,使用同一个模型训练。这是阿里文娱提到的一种方法,但我感觉这样无法满足用户特征样与条件策略独立的假设。

Class Transformation Method
另外一种更严谨的可以实现实验组对照组数据打通和模型打通的方法叫做class transformation Method

(8)式就是要计算的uplift score,此时只有Z ZZ一个变量,可以直接对Z = 1 Z=1Z=1这建模,相当于优化P ( Z = 1 ∣ X ) P(Z=1|\boldsymbol{X})P(Z=1∣X)单独建模。而P ( Z = 1 ∣ X ) P(Z=1|\boldsymbol{X})P(Z=1∣X)可以通过任何分类模型得到,所以这个方法称为Class Transformation Method. 实际上,Z = 1 Z=1Z=1就是实验组中下单的用户和对照组中未下单的用户,因此可以直接将实验组和对照组用户合并,使用一个模型建模,实现了数据层面和模型层面的打通。预测时,模型预测的结果就是uplift score,这点与差分响应模型不同。

Class Transformation的两个假设

Modeling Uplift Directly
除了Class Transformation可以直接对uplift建模外,还有另外一种直接优化uplift的方法,主要用于树模型,该方法直接修改树模型的特征分裂计算方法。常用的特征分裂指标是信息增益分别是分裂前后treatment和control样本的分布,可以用KL散度(KL divergence)、欧氏距离或者卡方距离来刻画这样的分布。

该方法可以直接对uplift建模,理论上精度会很高,但实际应用上除了修改分裂规则外,还需修改loss函数、剪枝算法等,成本较高。

增益模型的评估
响应模型可以通过一个测试数据集来计算precision,recall和AUC,但因为增益模型中不可能同时观察到同一用户在不同干预策略下的响应,因此无法直接计算上述评价指标。增益模型通常都是通过划分十分位数(decile)来对齐实验组和对照组数据,间接评估,而不是在一个测试集上直接评估。

uplift 柱状图
测试集上,实验组和对照组的用户分别按照uplift由高到低排序,划分为十等份,即十分位(decile),分别是top 10%用户,top 20%用户……top 100%用。这种方法只能定性分析,无法计算出一个具体的值来整体评价模型的好坏。

Qini曲线(Qini curve)
可以在uplift bars的基础上绘制曲线,类似AUC来评价模型的表现,这条曲线称为Qini curve,计算每个百分比的Qini系数,最后将这些Qini系数连接起来,得到一条曲线。Qini系数计算如下:

如上图,横轴等于0.2时,对应的纵轴大概是0.0032(uplift score),表示当uplift score等于0.0032时,可以覆盖前20%的用户数量,从图上看,这部分用户就是persuadable用户。

图中虚线是随机的base曲线,Qini曲线与随机random曲线之间的面积作为评价模型的指标,面积越大越好,面积越大,表示模型结果远超过随机选择的结果,与AUC类似,这个指标称为AUUC(Area Under Uplift Curve)。

Qini系数分母是实验组和对照组的全体用户数,如果两组用户数量差别比较大,结果容易失真。另一种累积增益曲线可以避免这个问题。

累积增益曲线(Cumulative Gain curve)
累积增益曲线计算如下

各符号含义与Qini系数符号含义相同。其中n t ( ϕ ) n_t(\phi)n 
 (ϕ)表示在ϕ \phiϕ百分比下,实验组(treatment)的用户数量,n c ( ϕ ) n_c(\phi)n 

 (ϕ)是在ϕ \phiϕ百分比下,对照组(control)的用户数量。与Qini系数相比,累积增益的分母是百分比ϕ \phiϕ下的实验组或对照组人数,并乘以n t ( ϕ ) + n c ( ϕ ) n_t(\phi) + n_c(\phi)n 
 (ϕ)作为全局调整系数,避免实验组和对照组用户数量不平衡导致的指标失真问题。

可以将累积增益曲线与random line之间的面积作为评价模型表现的指标。

优惠券发放Demo
这里有一个优惠券发放的例子 。这是一次优惠券发放活动,对用户以短信方式发放5折优惠券,本次活动实验组(treatement,短信方式发送5折优惠券),对照组(不发券)37701名用户,注意到实验组和对照组不满足P ( T ) = P ( C ) = 1 2 P(T) = P(C) = \frac{1}{2}P(T)=P(C)= 
 的条件。

这个例子还有一点特别,这其实是在一个预测模型上再做一次uplift modeling。本身实验组和对照组的数据是通过一个XGB模型预测出来的用户,该模型预测用户领取优惠券后是否会下单。根据模型预测结果,筛选一批高于某个阈值的用户,分成实验组和对照组。因此这次AB结果本身可以看出这个预测模型的uplift score。

这个预测模型的AB实验中,实验组转化率是2.69%,对照组转化率是2.28%,两组的转化率远高于以往运营随机筛选或根据条件筛选用户的转化率。但是,注意到这个预测模型的uplift score只有0.0041(2.69%-2.28%)。说明预测模型筛选出来的用户本身就有下单意愿,并不一定是因为发放优惠券而下单,所以实验组中的用户persuadable的比例应该不是很高。

在一个预测模型上再做uplift modeling相当于是在下单意愿高的用户中再筛选persuadable用户,其实实践上没有太大必要。但是作为一个例子,数据还是比较完美的,而且实验组和对照都通过同一个预测模型筛选而来,然后再随机分组,是满足uplift modeling条件的。

差分响应模型
实验组和对照组分别建模,使用lightGBM模型,分别取80%数据为训练集,20%数据为测试集。两个模型在测试集上的表现如下(未调参):
方便起见,将实验组和对照组20%的测试数据合并作为整个uplift model的测试集,流程如下。使用的数据集是经过了response model预测后的结果,相当于先筛选了一批下单概率高的用户,因为实验组和对照组用户都来自于同一个response model,可以认为两组用户特征分布式相同的。实际应用时,要注意实验组和对照组的用户特征分布是否一致。
 (X)排序,得到uplift bar,如下图所示。横轴是测试集中每个用户uplift的十分位数(decile),共10个bin;纵轴是每个bin的uplift均值。由于uplift排序是从低到高,因此这个uplift bar看起来是反的(正常应该是从高到底排)。

Class Transformation Method
训练和测试过程如下图所示。从实验组和对照组筛选出Z = 1 Z=1Z=1的用户作为正样本,其余的作为负样本。同样使用lightGBM模型(未调参)。

传统响应模型
为了对比,这里生成了一份传统响应模型的结果。注意这个对比其实没有什么意义,因为这些数据本身就是一个响应模型预测的结果,再预测一次的意义不大。

响应模型使用LightGBM,正样本是下单用户,负样本是未下单用户,处理流程如下。将实验组(treatment group)切分为训练集和测试集,训练集用于训练预测模型,之后用该模型预测实验组的测试集作为P T P^TP 
T
 ,预测整个对照组的数据作为P C P^CP 
C
 ,然后计算uplift score。注意到这里实验组的测试集数量是远远少于对照组数量的,所以两边的数据量不均衡。这种方法计算出来的uplift score是模拟分数。

模型评估
Qini曲线图如下。

Adjusted Qini曲线如下。

Adjusted Qini是为了避免实验组和对照组数据不均衡而导致Qini系数失真而设计的。计算方式如下:

累积增益曲线如下:

在Qini曲线下,差分响应模型的总体效果要好一些。而在累积增益曲线下,Class Transformation模型的总体效果要好一些。实验组和对照组数据不平衡的情况下,Qini系数可能有偏差,但本次对比的实验数据两组用户数量是接近的,这个问题还在研究中。

Python Uplift Modeling工具包:Pylift
Pylift是uplift建模的Python工具包。Pylift在sklearn的基础上针对uplift modeling对各模型做了一些优化,同时集成了一套uplift评价指标体系。所以Pylift内核还是sklearn,在sklearn外面封装了一套API,针对树模型做了uplift优化,可以通过Pylift实现直接的uplift modeling.

官网的示例代码如下。

from pylift import TransformedOutcome
up = TransformedOutcome(df1, col_treatment='Treatment', col_outcome='Converted')

up.randomized_search() # 对所有参数grid search,十分耗时,使用时注意限制参数searching的数量
up.fit(**up.rand_search_.best_params_)

up.plot(plot_type='aqini', show_theoretical_max=True) # 绘制aqini曲线
print(up.test_results_.Q_aqini)
所有模型的实现都通过类TransformedOutcome操作,通过传参来指定模型。默认的模型是XGBRegressor. 如果使用其他模型,通过参数sklearn_model指定,如下:

up = TransformedOutcome(df, col_treatment='Treatment', col_outcome='Converted', sklearn_model=RandomForestRegressor)
参数col_treatment是指数据集df中区分是否是treatment group的字段,通过0/1二值区分,col_treatment相当于label字段,如有转化是1,无转化是0.

Pylift另一个方便之处是提供了计算uplift评价指标的函数。如果是使用TransformedOutcome生成的结果,直接输入up.plot(plot_type='qini')即可绘制qini曲线。如果是自己的数据,可以通过下述方式来绘制曲线:

from pylift.eval import UpliftEval
upev = UpliftEval(treatment, outcome, predictions)
upev.plot(plot_type='aqini')

Pylift用于实验很方便,但因为还是基于sklearn,当达到千万量级的数据量时,还是需要考虑分布式。

总结
个人理解,增益模型实际上是一大类模型框架,本质上可以用传统响应模型或其他机器学习模型嵌入增益模型的框架,但是预测结果并不是一个概率,模型评价方式也有变化。

训练样本收集
增益模型建模强依赖于AB实验,数据要求很高。建模时要求实验组和对照组样本数量一样(实践中不一定有这个严格要求)。而且实验组和对照组的样本特征分布要一致,例如,训练数据不能是实验组预测后的结果、对照组随机选择的结果这样的组合,因为这样不满足干预策略与用户特征相互独立的假设(P ( G ∣ X ) = P ( G ) P(G | \boldsymbol{X}) = P(G)P(G∣X)=P(G))。故实验组中还需要预留一部分随机选择的用户,与对照组中的用户作为模型迭代的数据,或者实验组与对照组都先经过某个策略或模型的筛选。

多维度建模与个性化广告推送
上述所有模型都是针对G = T G=TG=T或者G = C G=CG=C,即干预策略只有一种,对于发券,相当于一个treatment只有一种折扣,对于广告push,一个treatment也只能有一种内容。而treatment可以用多种维度,如不同渠道发放不同折扣的优惠券,不同场景推送不同内容的push。传统的response model以转化为多分类问题解决,但uplift modeling难以简单转化为多分类问题。

此外,个性化广告推送也依赖长期和短期的用户行为特征构建。不同营销场景下的用户特征可以共用,可以构建统一的线上线下特征平台。

Reference
Causal Inference and Uplift Modeling: A review of the literature
Uplift modeling for clinical trial data
https://pylift.readthedocs.io/en/latest/introduction.html
Pylift: A Fast Python Package for Uplift Modeling
阿里文娱智能营销增益模型 ( Uplift Model ) 技术实践
 

你可能感兴趣的:(机器学习,uplift增益模型)