作者:Barış KaramanFollow      编译:ronghuaiyang

正文共:8484 字 13 图

预计阅读时间:25 分钟

导读

前一篇文章我们对客户进行了分群,但是我们还希望对每个客户有一个量化的指标来评价,而终生价值就是一个非常好指标,今天给大家介绍什么是终生价值,如何构建机器学习模型来预测客户的终生价值。

前文回顾:

用机器学习来提升你的用户增长:第一步,了解你的目标

用机器学习来提升你的用户增长:第二步,客户分群

第三部分: 预测客户的终生价值

在前一篇文章中,我们对客户进行了细分,找出了最好的客户。现在是时候衡量我们应该密切跟踪的最重要的指标之一了:客户终生价值。

我们对客户进行投资(收购成本、线下广告、促销、折扣等)以产生收入和盈利。当然,这些行动使一些客户的终身价值超级有价值,但总有一些客户拉低了利润率。我们需要识别这些行为模式,对客户进行细分并采取相应的行动。

计算终生价值是比较容易的部分。首先,我们需要选择一个时间窗口。可以是3,6,12,24个月。由下式可知,在特定的时间段内,我们可以得到每个客户的终身价值:

终身价值:总收入 - 总成本

这个等式给出了历史的终生价值。如果我们看到一些客户在历史上具有非常高的负终生价值,那么采取行动可能就太晚了。在这一点上,我们需要用机器学习来预测未来:

我们将建立一个简单的机器学习模型来预测我们客户的终生价值

终生价值预测

对于这个例子,我们也将继续使用我们的在线零售数据集。让我们找到正确的道路:

  • 为客户终生价值的计算定义一个合适的时间框架

  • 确定我们将用于预测未来的特征并构造这些特征

  • 计算用于训练机器学习模型的终生价值(LTV)

  • 构建并运行机器学习模型

  • 检查模型是否有用

确定时间框架实际上取决于你的行业、商业模式、战略等等。对于一些行业来说,1年是很长的一段时间,而对于另一些行业来说,1年是很短的一段时间。在我们的例子中,我们将继续使用6个月。

每个客户ID的RFM得分,我们在前一篇文章中计算过,是特征集的完美候选。为了正确实现它,我们需要对数据集进行划分。我们使用3个月的数据,计算RFM并使用它来预测未来6个月。因此,我们需要首先创建两个dataframes并将RFM分数加到它们里面。

#import libraries
from datetime import datetime, timedelta,date
import pandas as pd
%matplotlib inline
from sklearn.metrics import classification_report,confusion_matrix
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from __future__ import division
from sklearn.cluster import KMeansimport plotly.plotly as py
import plotly.offline as pyoff
import plotly.graph_objs as goimport xgboost as xgb
from sklearn.model_selection import KFold, cross_val_score, train_test_splitimport xgboost as xgb#initate plotly
pyoff.init_notebook_mode()#read data from csv and redo the data work we done before
tx_data = pd.read_csv('data.csv')
tx_data['InvoiceDate'] = pd.to_datetime(tx_data['InvoiceDate'])
tx_uk = tx_data.query("Country=='United Kingdom'").reset_index(drop=True)#create 3m and 6m dataframes
tx_3m = tx_uk[(tx_uk.InvoiceDate < date(2011,6,1)) & (tx_uk.InvoiceDate >= date(2011,3,1))].reset_index(drop=True)
tx_6m = tx_uk[(tx_uk.InvoiceDate >= date(2011,6,1)) & (tx_uk.InvoiceDate < date(2011,12,1))].reset_index(drop=True)#create tx_user for assigning clustering
tx_user = pd.DataFrame(tx_3m['CustomerID'].unique())
tx_user.columns = ['CustomerID']#order cluster method
def order_cluster(cluster_field_name, target_field_name,df,ascending):new_cluster_field_name = 'new_' + cluster_field_namedf_new = df.groupby(cluster_field_name)[target_field_name].mean().reset_index()df_new = df_new.sort_values(by=target_field_name,ascending=ascending).reset_index(drop=True)df_new['index'] = df_new.indexdf_final = pd.merge(df,df_new[[cluster_field_name,'index']], on=cluster_field_name)df_final = df_final.drop([cluster_field_name],axis=1)df_final = df_final.rename(columns={"index":cluster_field_name})return df_final#calculate recency score
tx_max_purchase = tx_3m.groupby('CustomerID').InvoiceDate.max().reset_index()
tx_max_purchase.columns = ['CustomerID','MaxPurchaseDate']
tx_max_purchase['Recency'] = (tx_max_purchase['MaxPurchaseDate'].max() - tx_max_purchase['MaxPurchaseDate']).dt.days
tx_user = pd.merge(tx_user, tx_max_purchase[['CustomerID','Recency']], on='CustomerID')kmeans = KMeans(n_clusters=4)
kmeans.fit(tx_user[['Recency']])
tx_user['RecencyCluster'] = kmeans.predict(tx_user[['Recency']])tx_user = order_cluster('RecencyCluster', 'Recency',tx_user,False)#calcuate frequency score
tx_frequency = tx_3m.groupby('CustomerID').InvoiceDate.count().reset_index()
tx_frequency.columns = ['CustomerID','Frequency']
tx_user = pd.merge(tx_user, tx_frequency, on='CustomerID')kmeans = KMeans(n_clusters=4)
kmeans.fit(tx_user[['Frequency']])
tx_user['FrequencyCluster'] = kmeans.predict(tx_user[['Frequency']])tx_user = order_cluster('FrequencyCluster', 'Frequency',tx_user,True)#calcuate revenue score
tx_3m['Revenue'] = tx_3m['UnitPrice'] * tx_3m['Quantity']
tx_revenue = tx_3m.groupby('CustomerID').Revenue.sum().reset_index()
tx_user = pd.merge(tx_user, tx_revenue, on='CustomerID')kmeans = KMeans(n_clusters=4)
kmeans.fit(tx_user[['Revenue']])
tx_user['RevenueCluster'] = kmeans.predict(tx_user[['Revenue']])
tx_user = order_cluster('RevenueCluster', 'Revenue',tx_user,True)#overall scoring
tx_user['OverallScore'] = tx_user['RecencyCluster'] + tx_user['FrequencyCluster'] + tx_user['RevenueCluster']
tx_user['Segment'] = 'Low-Value'
tx_user.loc[tx_user['OverallScore']>2,'Segment'] = 'Mid-Value'
tx_user.loc[tx_user['OverallScore']>4,'Segment'] = 'High-Value' 

我们已经创建好了我们的RFM评分,现在我们的特征集合如下:

既然我们的特征集已经准备好了,我们为每个客户计算6个月的LTV,我们将使用这些LTV来训练我们的模型。

数据集中没有成本。这就是为什么收入直接成为我们的LTV。

#calculate revenue and create a new dataframe for it
tx_6m['Revenue'] = tx_6m['UnitPrice'] * tx_6m['Quantity']
tx_user_6m = tx_6m.groupby('CustomerID')['Revenue'].sum().reset_index()
tx_user_6m.columns = ['CustomerID','m6_Revenue']#plot LTV histogram
plot_data = [go.Histogram(x=tx_user_6m.query('m6_Revenue < 10000')['m6_Revenue'])
]plot_layout = go.Layout(title='6m Revenue')
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

这段代码计算LTV并绘制它的直方图:

直方图清楚地显示我们有客户的LTV为负。我们也有一些异常值。过滤掉异常值对于建立一个合适的机器学习模型是有意义的。

好的,下一个步骤。我们将合并我们的3个月和6个月的dataframes,以查看LTV和我们的特征集之间的相关性。

tx_merge = pd.merge(tx_user, tx_user_6m, on='CustomerID', how='left')
tx_merge = tx_merge.fillna(0)tx_graph = tx_merge.query("m6_Revenue < 30000")plot_data = [go.Scatter(x=tx_graph.query("Segment == 'Low-Value'")['OverallScore'],y=tx_graph.query("Segment == 'Low-Value'")['m6_Revenue'],mode='markers',name='Low',marker= dict(size= 7,line= dict(width=1),color= 'blue',opacity= 0.8)),go.Scatter(x=tx_graph.query("Segment == 'Mid-Value'")['OverallScore'],y=tx_graph.query("Segment == 'Mid-Value'")['m6_Revenue'],mode='markers',name='Mid',marker= dict(size= 9,line= dict(width=1),color= 'green',opacity= 0.5)),go.Scatter(x=tx_graph.query("Segment == 'High-Value'")['OverallScore'],y=tx_graph.query("Segment == 'High-Value'")['m6_Revenue'],mode='markers',name='High',marker= dict(size= 11,line= dict(width=1),color= 'red',opacity= 0.9)),
]plot_layout = go.Layout(yaxis= {'title': "6m LTV"},xaxis= {'title': "RFM Score"},title='LTV')
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

下面的代码合并了我们的特征集和LTV数据,并绘制了LTV与总体RFM评分:

正相关是很明显的。高RFM分数意味着高LTV。

在建立机器学习模型之前,我们需要确定这个机器学习问题的类型。LTV本身是一个回归问题。机器学习模型可以预测LTV的值。但在这里,我们想要LTV分群。因为它更可行,更容易与他人沟通。通过应用K-means聚类,我们可以识别现有的LTV组并构建分群。

考虑到这个分析的业务部分,我们需要根据预测的LTV来区别对待客户。对于这个例子,我们将使用聚类,并聚成3个部分(部分的数量真的取决于你的业务动态和目标):

  • 低LTV

  • 中等LTV

  • 高LTV

我们将使用K-means聚类来确定分群并观察它们的特征:

#remove outliers
tx_merge = tx_merge[tx_merge['m6_Revenue']<tx_merge['m6_Revenue'].quantile(0.99)]#creating 3 clusters
kmeans = KMeans(n_clusters=3)
kmeans.fit(tx_merge[['m6_Revenue']])
tx_merge['LTVCluster'] = kmeans.predict(tx_merge[['m6_Revenue']])#order cluster number based on LTV
tx_merge = order_cluster('LTVCluster', 'm6_Revenue',tx_merge,True)#creatinga new cluster dataframe
tx_cluster = tx_merge.copy()#see details of the clusters
tx_cluster.groupby('LTVCluster')['m6_Revenue'].describe()

我们已经完成了LTV聚类,下面是每个分群的特点:

2是最好的,平均LTV为8.2k,而0是最差的,为396。

在训练机器学习模型之前还有几个步骤:

  • 需要做一些特征工程。

  • 我们应该把类别列转换成数字列。

  • 我们会根据我们的标签(LTV分群)检查特征的相关性。

  • 我们把我们的特征集和标签(LTV)分解为X和y,我们使用X来预测y。

  • 创建训练和测试数据集。

  • 训练集将用于构建机器学习模型。

  • 我们将把我们的模型应用到测试集,看看它的实际性能。

下面的代码为做了这些:

#convert categorical columns to numerical
tx_class = pd.get_dummies(tx_cluster)#calculate and show correlations
corr_matrix = tx_class.corr()
corr_matrix['LTVCluster'].sort_values(ascending=False)#create X and y, X will be feature set and y is the label - LTV
X = tx_class.drop(['LTVCluster','m6_Revenue'],axis=1)
y = tx_class['LTVCluster']#split training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.05, random_state=56)

我们从第一行开始。**get_dummies()**方法将类别列转换为0-1。用个例子看看它具体做了什么:

这是get_dummies()之前的数据集。我们有一个类别列,叫做segment。应用get_dummies()后会发生什么:

segment列没有了,但我们有新的数字列来表示它。我们已经将它转换为3个不同的列,其中包含0和1,并使其可用于我们的机器学习模型。

行的相关性我们有以下数据:

我们发现,3个月的Revenue, Frequency和RFM分数将有助于我们的机器学习模型。

既然我们有了训练和测试集,我们可以构建我们的模型。

#XGBoost Multiclassification Model
ltv_xgb_model = xgb.XGBClassifier(max_depth=5, learning_rate=0.1,objective= 'multi:softprob',n_jobs=-1).fit(X_train, y_train)print('Accuracy of XGB classifier on training set: {:.2f}'.format(ltv_xgb_model.score(X_train, y_train)))
print('Accuracy of XGB classifier on test set: {:.2f}'.format(ltv_xgb_model.score(X_test[X_train.columns], y_test)))y_pred = ltv_xgb_model.predict(X_test)
print(classification_report(y_test, y_pred))

我们使用了一个强大的ML库XGBoost来为我们进行分类。它是一个多分类模型,因为我们有3个组,让我们看看最初的结果:

测试集的正确率为84%,看起来非常好。是吗?

首先,我们需要检查基准测试。最大的cluster 是0号cluster,占总数的76.5%。如果我们盲目地说每个客户都属于cluster 0,那么我们的准确率将达到76.5%。84%对76.5%告诉我们,我们的机器学习模型是有用的,但肯定需要改进。我们应该找出模型的不足之处。我们可以通过查看分类报告来识别:

0号分群的精确度和召回是可以接受。例如,对于0号群体(低LTV),如果模型告诉我们该客户属于0号分群,那么100个客户中有90个将是正确的(精确度)。该模型成功识别了93%的实际cluster 0的客户(召回)。但是我们确实需要改进其他分群的模型。例如,我们只检测到56%的中端LTV客户。可能采取的行动:

  • 增加更多的特征,改进特征工程

  • 尝试XGBoost以外的不同的模型

  • 对当前模型使用超参数调整

  • 如有可能,向模型中添加更多数据

好了!现在我们有一个机器学习模型,可以预测未来客户的LTV细分情况。我们可以很容易地在此基础上调整我们的行动。例如,我们绝对不想失去高LTV的客户。因此,我们将在下一部分中关注客户流失预测。

—END—

英文原文:https://towardsdatascience.com/data-driven-growth-with-python-part-3-customer-lifetime-value-prediction-6017802f2e0f

往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习在线手册深度学习在线手册AI基础下载(pdf更新到25集)本站qq群1003271085,加入微信群请回复“加群”获取一折本站知识星球优惠券,复制链接直接打开:https://t.zsxq.com/yFQV7am喜欢文章,点个在看

【实战】用机器学习来提升你的用户增长:(三、预测客户的终生价值)相关推荐

  1. 【实战】用机器学习来提升你的用户增长(二)

    作者:Barış KaramanFollow  编译:ronghuaiyang 正文共: 9230 字 18 图 预计阅读时间: 27 分钟 导读 今天给大家介绍客户分群方面的内容,为什么要对客户进行 ...

  2. 英文书《用unreal来学习c++》_用机器学习来提升你的用户增长:第四步,客户流失预测

    作者:Barış KaramanFollow 编译:ronghuaiyang 正文共:8484 字 13 图 预计阅读时间:25 分钟 导读 我们通过客户分群和终生价值的预测得到了我们的最好的客户,对 ...

  3. 用机器学习来提升你的用户增长:第七步,构建市场响应模型

    点击上方"AI公园",关注公众号,选择加"星标"或"置顶" 作者:Barış KaramanFollow 编译:ronghuaiyang 正 ...

  4. 【实战】用机器学习来提升你的用户增长

    作者:Barış KaramanFollow  编译:ronghuaiyang 正文共:10130 字 24 图 预计阅读时间:29 分钟 导读 这一系列的文章通过了一个实际的案例,向大家介绍了如何使 ...

  5. 新书推荐 |《用户增长方法论:找到产品长盛不衰的增长曲线》

    新书推荐 <用户增长方法论:找到产品长盛不衰的增长曲线> 长按二维码 了解及购买 BAT 10余年用户增长经验总结,操盘5款日活过亿产品,1套系统的.循环的.全链路的方法论,50余方法,1 ...

  6. 【用户增长】用户增长方法论及增长思维

    用户增长方法论及增长思维 1.什么是用户增长 1.1 用户增长的概念及内涵 用户增长不是简单的用户数量的增长. 用户增长是一个系统化,综合化的体系. 用户增长包含三个阶段的增长. 综上三点,我们可以简 ...

  7. 自然语言处理实战:机器学习常见工具与技术

    许多自然语言处理都涉及机器学习,所以理解机器学习的一些基本工具和技术是有益处的.有些工具已经在前几章中讨论过,有些还没有,但这里我们会讨论所有这些工具. D.1 数据选择和避免偏见 数据选择和特征工程 ...

  8. TensorFlow深度学习算法原理与编程实战 人工智能机器学习技术丛书

    作者:蒋子阳 著 出版社:中国水利水电出版社 品牌:智博尚书 出版时间:2019-01-01 TensorFlow深度学习算法原理与编程实战 人工智能机器学习技术丛书 ISBN:97875170682 ...

  9. 仿联想商城laravel实战---7、lavarel中如何给用户发送邮件

    仿联想商城laravel实战---7.lavarel中如何给用户发送邮件 一.总结 一句话总结: 设置邮件服务器,比如163邮箱 lavarel中配置邮件服务,在.env中 控制器中使用Mail对象发 ...

最新文章

  1. 在分页状态下删除纪录的问题
  2. 扩展Jquery插件处理mouseover时内部有子元素时发生样式闪烁
  3. 给IT新人的15个建议:程序员的辛酸反省与总结!
  4. python中的以简单例子解释函数参数、函数定义、函数返回值、函数调用
  5. 监督学习 | 决策树之网络搜索
  6. 容器编排技术 -- Kubernetes 为 Namespace 设置最小和最大内存限制
  7. Eclipse中SVN标记,提交人,时间等版本信息消失
  8. 18b20温度检测及其lcd显示_单片机使用DS18B20测量温度的程序
  9. 使用反射获得jar包中的类、方法、参数、返回值类型,然后动态加载jar包运行方法
  10. FFmpeg之wav转mp3(二十四)
  11. 深度学习高速路上,PaddlePaddle正在弯道超车
  12. winform 打印快递电子面单_电子面单接口说明文档-(附C#源码)
  13. 并查集算法最全最详细讲解
  14. linux嵌入式主要学什么软件,嵌入式软件工程师需要学什么?嵌入式Linux开发的工作内容...
  15. 1-15 Burpsuite Sequencer介绍
  16. 机器学习之——泛化能力
  17. Kotlin中val和var的区别
  18. 联邦学习论文阅读:Variational Federated Multi-Task Learning
  19. windows xp 系统CMD命令大全
  20. 关于宋词频率统计(R语言)

热门文章

  1. xml web service
  2. c# 中的as,is
  3. BZOJ1951 [Sdoi2010]古代猪文 【费马小定理 + Lucas定理 + 中国剩余定理 + 逆元递推 + 扩展欧几里得】...
  4. flask的日志输出current_app.logger.debug
  5. Java基础之IDE
  6. 将程序添加到自动启动
  7. Android开发(七)——判断网络状态
  8. How to not show unnecessary zeros when given integers but still have float answers when needed
  9. crontab详解-如何让脚本自动定时运行,设置、启动 linux定时器
  10. 【分享】【养生】消灭小肚腩