Press "Enter" to skip to content

超越流失预测和流失提升

因果数据科学

在客户流失情况下如何最好地定位政策

封面,作者提供的图片

数据科学中非常常见的任务之一是客户流失预测。然而,预测客户流失通常只是一个中间步骤,很少是最终目标。通常,我们真正关心的是减少客户流失,这是一个独立的目标,不一定相关。事实上,例如,知道长期客户比新客户更不容易流失并不是一个可行的见解,因为我们无法增加客户的保有期。相反,我们希望知道的是一个(或多个)处理对流失的影响。这通常被称为流失提升

在本文中,我们将超越客户流失预测和流失提升,而是考虑到客户保留活动的最终目标:增加收入。首先,降低客户流失的政策可能也对收入产生影响,这应该被考虑在内。然而,更重要的是,只有客户不流失时增加收入才是相关的。相反,对于高收入客户来说,减少流失更为重要。这种流失和收入之间的相互作用对于理解任何处理活动的盈利能力至关重要,不容忽视。

礼品和订阅

在本文的其余部分,我们将使用一个玩具示例来说明主要思想。假设我们是一家有兴趣减少客户流失并最终增加收入的公司。假设我们决定测试一个新想法:向我们的用户发送1美元的礼品。为了测试处理是否有效,我们仅随机将其发送给我们客户群的一小部分。

cost = 1

让我们看一下我们可用的数据。我从src.dgp导入数据生成过程dgp_gift()。我还从src.utils导入一些绘图函数和库。

from src.utils import *from src.dgp import dgp_giftdgp = dgp_gift(n=100_000)df = dgp.generate_data()df.head()
数据快照,作者提供的图片

我们有关于100_000个客户的信息,我们观察到他们成为活跃客户的月数,他们在上个月生成的收入(rev_old),上个月和之前一个月之间的收入变化(rev_change),是否随机发送了礼品以及两个感兴趣的结果:流失,即他们是否不再是活跃客户,以及他们在当前月份生成的收入。我们用字母Y表示结果,字母W表示处理,字母X表示其他变量。

Y = ['流失', '收入']W = '礼品'X = ['月数', 'rev_old', 'rev_change']

注意,为了简单起见,我们考虑了数据的单期快照,并且只用几个变量总结了数据的面板结构。通常,我们会有更长的时间序列,但对于结果(例如客户生命周期价值)的时间范围也会更长。

我们可以用以下的有向无环图(Directed Acyclic Graph, DAG)来表示潜在的数据生成过程。节点表示变量,箭头表示潜在的因果关系。我已经用绿色突出显示了两个感兴趣的关系:礼品对流失和收入的影响。注意,流失与收入有关,因为按照定义,流失的客户不会产生收入。

数据生成过程的有向无环图,图像作者:作者

重要的是,过去的收入和收入变化是流失收入的预测因素,但与我们的干预无关。相反,干预会根据客户的总活跃月数不同地影响流失收入

尽管简单,但这个数据生成过程旨在捕捉一个重要的洞察:对流失收入有很好预测的变量,不一定是能预测流失收入提升的变量。后面我们将看到这对我们的分析有何影响。

让我们先从探索数据开始。

探索性数据分析

我们先从流失开始。公司上个月失去了多少客户?

df.churn.mean()

0.19767

公司上个月几乎失去了20%的客户!礼物有助于防止客户流失吗?

我们希望比较接收到礼物的客户和未接收到礼物的客户的流失频率。由于礼物是随机分配的,均值差估计量是礼物流失的平均处理效应(ATE)的无偏估计量。

平均处理效应,图像作者:作者

我们通过线性回归计算均值差估计量。为了提高估计量的效率,我们还包括其他协变量。

smf.ols("churn ~ " + W + " + " + " + ".join(X), data=df).fit().summary().tables[1]
流失回归表,图像作者:作者

看起来礼物使流失率下降了约11个百分点,即基线水平32%的近三分之一!它对收入也有影响吗?

与流失一样,我们在礼物,即我们的处理变量上将收入回归,以估计平均处理效应。

smf.ols("revenue ~ " + W + " + " + " + ".join(X), data=df).fit().summary().tables[1]
收入回归表,图像作者:作者

看起来礼物平均增加了0.63美元的收入,这意味着它是不盈利的。这是否意味着我们应该停止向客户发送礼物?这取决于情况。实际上,对于某些客户细分,礼物可能是有效的。我们只需要找出它们。

定位策略

在本节中,我们将尝试理解是否存在一种数据驱动的盈利方式来发送礼物,通过针对特定客户进行定位。特别是,我们将比较不同的定位策略,以增加收入为目标。

在本节中,我们将需要一些算法来预测收入流失或接收礼物的概率。我们使用lightgbm库中的梯度提升树模型。我们对所有策略使用相同的模型,以便我们不能将性能差异归因于预测准确性。

from lightgbm import LGBMClassifier, LGBMRegressor

为了评估每个以τ表示的策略,我们将其利润与没有策略Π⁽⁰⁾的利润进行比较,对每个个体在一个单独的验证数据集中进行比较。需要注意的是,通常情况下这是不可能的,因为对于每个客户,我们只观察到两个潜在结果中的一个,即有或没有礼物。然而,由于我们使用的是合成数据,我们可以进行oracle评估。如果您想了解如何使用真实数据评估提升模型的更多信息,我推荐阅读我的入门文章。

评估提升模型

因果推断在工业界中最常见的应用之一是提升建模,也称为估计…

towardsdatascience.com

首先,让我们将利润Π定义为顾客不流失C时的净收入R。

利润公式,作者提供的图片

因此,对于接受处理的个体,其对利润的整体影响由接受处理时的利润Π⁽¹⁾减去不接受处理时的利润Π⁽⁰⁾给出。

利润提升公式,作者提供的图片

未接受处理的个体的影响为零。

def evaluate_policy(policy):    data = dgp.generate_data(seed_data=4, seed_assignment=5, keep_po=True)    data['profits'] = (1 - data.churn) * data.revenue    baseline = (1-data.churn_c) * data.revenue_c    effect = policy(data) * (1-data.churn_t) * (data.revenue_t-cost) + (1-policy(data)) * (1-data.churn_c) * data.revenue_c    return np.sum(effect - baseline)

1. 针对流失客户的策略

第一个策略可以是只针对流失客户。假设我们只将礼物发送给预测的流失概率高于平均值的客户。

model_churn = LGBMClassifier().fit(X=df[X], y=df['churn'])policy_churn = lambda df : (model_churn.predict_proba(df[X])[:,1] > df.churn.mean())evaluate_policy(policy_churn)

-5497.46

该策略是不盈利的,会导致超过5000美元的亏损

您可能会认为问题在于任意的阈值,但事实并非如此。下图显示了所有可能的策略阈值的总体效果。

x = np.linspace(0, 1, 100)y = [evaluate_policy(lambda df : (model_churn.predict_proba(df[X])[:,1] > p)) for pin x]fig, ax = plt.subplots(figsize=(10, 3))sns.lineplot(x=x, y=y).set(xlabel='流失策略阈值', title='总体效果');ax.axhline(y=0, c='k', lw=3, ls='--');
按流失阈值划分的总体效果,作者提供的图片

可以看到,无论阈值如何,基本上都不可能获得任何利润。

问题在于客户可能流失的概率并不意味着礼物会对其流失概率产生任何影响。这两个指标并不完全无关(例如,我们无法减少流失概率为0%的客户的流失概率),但它们并不是同一回事。

2. 目标营收客户

现在,让我们尝试一种不同的策略:我们只向高营收客户发送礼物。例如,我们可能只向营收排名前10%的客户发送礼物。这个想法是,如果该策略确实可以减少流失,那么对于减少流失更有利可图的就是这些客户。

model_revenue = LGBMRegressor().fit(X=df[X], y=df['revenue'])policy_revenue = lambda df : (model_revenue.predict(df[X]) > np.quantile(df.revenue, 0.9))evaluate_policy(policy_revenue)

-4730.82

这个策略仍然是不赚钱的,导致了大量亏损。与之前一样,这不是选择阈值的问题,如下图所示。我们能做的最好的就是将阈值设得非常高,以至于我们不对任何人采取措施,从而获得零利润。

x = np.linspace(0, 100, 100)y = [evaluate_policy(lambda df : (model_revenue.predict(df[X]) > c)) for c in x]fig, ax = plt.subplots(figsize=(10, 3))sns.lineplot(x=x, y=y).set(xlabel='营收策略阈值', title='综合效果');ax.axhline(y=0, c='k', lw=3, ls='--');
按营收阈值的综合效果,作者提供的图片

问题在于,在我们的设置中,高营收客户的流失概率没有足够降低以使得 gift 成为有利可图的。这部分原因还在于现实中经常观察到的事实,即高营收客户也是最不容易流失的客户。

现在让我们考虑一组更相关的策略:基于提升效果(uplift)的策略。

3. 目标流失提升客户

一种更明智的方法是针对那些在收到1美元的 gift 后流失概率下降最多的客户。我们使用双重稳健估计器来估计流失提升,这是效果最好的提升模型之一。如果您对元学习者不熟悉,我建议从我的入门文章开始。

理解元学习者

在许多情况下,我们不仅对估计因果效应感兴趣,还对该效应是否存在感兴趣。

towardsdatascience.com

我们从 Microsoft 的 econml 库中导入双重稳健学习器。

from econml.dr import DRLearnerDR_learner_churn = DRLearner(model_regression=LGBMRegressor(), model_propensity=LGBMClassifier(), model_final=LGBMRegressor())DR_learner_churn.fit(df['churn'], df[W], X=df[X]);

现在我们已经估计了流失提升,我们可能会倾向于只针对具有较高负提升效果(负数,因为我们希望减少流失)的客户发送 gift。例如,我们可能将 gift 发送给所有估计提升效果大于平均流失的客户。

policy_churn_lift = lambda df : DR_learner_churn.effect(df[X]) < - np.mean(df.churn)evaluate_policy(policy_churn_lift)

-3925.24

这个策略仍然是不赚钱的,导致了将近4000美元的亏损。

问题在于我们没有考虑到策略的成本。事实上,降低流失概率只对高营收客户有益可图。以极端情况为例:避免流失一个不产生任何营收的客户对于任何干预来说都不值得。

因此,让我们只向那些流失概率乘以营收权重减少超过礼物成本的客户发送 gift

model_revenue_1 = LGBMRegressor().fit(X=df.loc[df[W] == 1, X], y=df.loc[df[W] == 1, 'revenue'])policy_churn_lift = lambda df : - DR_learner_churn.effect(df[X]) * model_revenue_1.predict(df[X]) > costevaluate_policy(policy_churn_lift)

318.03

这个策略最终是有盈利的!

然而,我们还没有考虑一个渠道:干预可能也会影响现有客户的收入。

4. 目标收入增长的客户

对于前面的方法的对称方法是只考虑对revenue的影响,忽略对流失的影响。我们可以估计非流失客户的revenue增长并只对那些净增长效果(扣除流失)大于gift成本的客户进行处理。

DR_learner_netrevenue = DRLearner(model_regression=LGBMRegressor(), model_propensity=LGBMClassifier(), model_final=LGBMRegressor())DR_learner_netrevenue.fit(df.loc[df.churn==0, 'revenue'], df.loc[df.churn==0, W], X=df.loc[df.churn==0, X]);model_churn_1 = LGBMClassifier().fit(X=df.loc[df[W] == 1, X], y=df.loc[df[W] == 1, 'churn'])policy_netrevenue_lift = lambda df : DR_learner_netrevenue.effect(df[X]) * (1-model_churn_1.predict(df[X])) > costevaluate_policy(policy_netrevenue_lift)

50.80

这个策略也是有盈利的,但忽略了对流失的影响。我们如何将这个策略与前一个策略结合起来?

5. 目标收入增长的客户

在同时考虑对流失和净收入的影响方面,最有效的方法是简单地估计总的收入增长。所暗示的最优策略是对那些总收入增长大于gift成本的客户进行处理。

DR_learner_revenue = DRLearner(model_regression=LGBMRegressor(), model_propensity=LGBMClassifier(), model_final=LGBMRegressor())DR_learner_revenue.fit(df['revenue'], df[W], X=df[X]);policy_revenue_lift = lambda df : (DR_learner_revenue.effect(df[X]) > cost)evaluate_policy(policy_revenue_lift)

2028.21

看起来这是迄今为止最好的策略,产生了超过2000美元的总利润!

如果我们比较所有不同的策略,结果非常明显。

policies = [policy_churn, policy_revenue, policy_churn_lift, policy_netrevenue_lift, policy_revenue_lift] df_results = pd.DataFrame()df_results['policy'] = ['churn', 'revenue', 'churn_L', 'netrevenue_L', 'revenue_L']df_results['value'] = [evaluate_policy(policy) for policy in policies]fig, ax = plt.subplots()sns.barplot(df_results, x='policy', y='value').set(title='Overall Incremental Effect')plt.axhline(0, c='k');
Comparing policies, image by Author

直觉和分解

如果我们比较不同的策略,很明显直接针对高收入或高流失概率的客户是最糟糕的选择。这不一定总是情况,但在我们的模拟数据中发生了这种情况,因为有两个在许多实际情况下也很常见的事实:

  1. 收入和流失概率呈负相关
  2. 对于基准值,giftchurn(或revenue)的影响没有强烈的负相关(或对revenue而言是正相关)

这两个事实中的任何一个足以使针对收入或流失的策略变得不合适。相反,应该针对具有高增量效果的客户,并且最好直接使用感兴趣的变量,本例中是revenue,如果有的话。

为了更好地理解机制,我们可以将策略对利润的总效果分解为三个部分。

利润提升分解,作者提供的图片

这意味着有三个渠道使得对待顾客是有利可图的。

  1. 如果是高收入顾客且对待降低了其流失概率
  2. 如果是非流失顾客且对待增加了其收入
  3. 如果对待对其收入和流失概率都有强烈影响

针对流失增益的定位只利用了第一个渠道,针对净收入增益的定位只利用了第二个渠道,而针对总收入增益的定位利用了所有三个渠道,使其成为最有效的方法。

奖励:加权

正如Lemmens,Gupta(2020)所强调的,有时在估计模型增益时可能值得加权观察。特别是,在估计靠近处理策略阈值的观察时,可能值得给予更多权重。

这个想法是加权通常会降低估计器的效率。然而,我们并不关心对所有观察的正确估计,而是关心正确估计策略阈值。实际上,无论你估计净利润为1美元还是1000美元都无所谓:暗示的策略是相同的:发送礼物。然而,估计净利润为1美元而不是-1美元会颠倒策略的意义。因此,远离阈值的准确性的大幅损失有时值得在阈值处获得小幅准确性的收益。

让我们尝试使用负指数权重,权重随着距离阈值的减小而减小。

DR_learner_revenue_w = DRLearner(model_regression=LGBMRegressor(), model_propensity=LGBMClassifier(), model_final=LGBMRegressor())w = np.exp(1 + np.abs(DR_learner_revenue.effect(df[X]) - cost))DR_learner_revenue_w.fit(df['revenue'], df[W], X=df[X], sample_weight=w);policy_revenue_lift_w = lambda df : (DR_learner_revenue_w.effect(df[X]) > cost)evaluate_policy(policy_revenue_lift_w)

1398.19

在我们的情况下,加权并不值得:暗示的策略仍然是有利可图的,但小于未加权模型的2028美元。

结论

在本文中,我们了解了为什么以及如何超越流失预测和流失增益建模。特别是,我们应该将重点从预测转移到增益,并将流失和收入结合为一个单一的结果。

一个重要的警告涉及可用数据的维度。我们使用了一个高度简化问题的玩具数据集,至少在两个维度上。首先,反向来看,我们通常有更长的时间序列可以用于预测和建模目的。其次,前向来看,应该将流失与更长期的顾客利润估计结合起来,通常称为顾客生命周期价值。

参考资料

  • Kennedy (2022), “Towards Optimal Doubly Robust Estimation of Heterogeneous Causal Effects”
  • Bonvini, Kennedy, Keele (2021), “Minimax Optimal Subgroup Identification”
  • Lemmens, Gupta (2020), “Managing Churn to Maximize Profits”
  • Evaluating Uplift Models
  • Understanding Meta Learners
  • Understanding AIPW, the Doubly-Robust Estimator

代码

你可以在这里找到原始的Jupyter Notebook:

Blog-Posts/notebooks/beyond_churn.ipynb at main · matteocourthoud/Blog-Posts

Code and notebooks for my VoAGI blog posts. Contribute to matteocourthoud/Blog-Posts development by creating an…

github.com

谢谢阅读!

非常感谢!🤗 如果你喜欢这篇文章并想看到更多内容,请关注我。我每周发布与因果推断和数据分析相关的主题。我试图保持我的文章简单而准确,始终提供代码、示例和模拟。

另外,一个小小的免责声明:我写作是为了学习,所以错误是正常的,尽管我已经尽力。如果你发现错误,请告诉我。我也欢迎关于新主题的建议!

Leave a Reply

Your email address will not be published. Required fields are marked *