【实战】用机器学习来提升你的用户增长:(三、预测客户的终生价值)
作者:Bar?? KaramanFollow? ? ??編譯:ronghuaiyang
正文共:8484 字 13 圖
預計閱讀時間:25 分鐘
導讀
前一篇文章我們對客戶進行了分群,但是我們還希望對每個客戶有一個量化的指標來評價,而終生價值就是一個非常好指標,今天給大家介紹什么是終生價值,如何構建機器學習模型來預測客戶的終生價值。
前文回顧:
用機器學習來提升你的用戶增長:第一步,了解你的目標
用機器學習來提升你的用戶增長:第二步,客戶分群
第三部分: 預測客戶的終生價值
在前一篇文章中,我們對客戶進行了細分,找出了最好的客戶。現(xiàn)在是時候衡量我們應該密切跟蹤的最重要的指標之一了:客戶終生價值。
我們對客戶進行投資(收購成本、線下廣告、促銷、折扣等)以產生收入和盈利。當然,這些行動使一些客戶的終身價值超級有價值,但總有一些客戶拉低了利潤率。我們需要識別這些行為模式,對客戶進行細分并采取相應的行動。
計算終生價值是比較容易的部分。首先,我們需要選擇一個時間窗口。可以是3,6,12,24個月。由下式可知,在特定的時間段內,我們可以得到每個客戶的終身價值:
終身價值:總收入 - 總成本
這個等式給出了歷史的終生價值。如果我們看到一些客戶在歷史上具有非常高的負終生價值,那么采取行動可能就太晚了。在這一點上,我們需要用機器學習來預測未來:
我們將建立一個簡單的機器學習模型來預測我們客戶的終生價值
終生價值預測
對于這個例子,我們也將繼續(xù)使用我們的在線零售數據集。讓我們找到正確的道路:
為客戶終生價值的計算定義一個合適的時間框架
確定我們將用于預測未來的特征并構造這些特征
計算用于訓練機器學習模型的終生價值(LTV)
構建并運行機器學習模型
檢查模型是否有用
確定時間框架實際上取決于你的行業(yè)、商業(yè)模式、戰(zhàn)略等等。對于一些行業(yè)來說,1年是很長的一段時間,而對于另一些行業(yè)來說,1年是很短的一段時間。在我們的例子中,我們將繼續(xù)使用6個月。
每個客戶ID的RFM得分,我們在前一篇文章中計算過,是特征集的完美候選。為了正確實現(xiàn)它,我們需要對數據集進行劃分。我們使用3個月的數據,計算RFM并使用它來預測未來6個月。因此,我們需要首先創(chuàng)建兩個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'?我們已經創(chuàng)建好了我們的RFM評分,現(xiàn)在我們的特征集合如下:
既然我們的特征集已經準備好了,我們?yōu)槊總€客戶計算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聚類,我們可以識別現(xiàn)有的LTV組并構建分群。
考慮到這個分析的業(yè)務部分,我們需要根據預測的LTV來區(qū)別對待客戶。對于這個例子,我們將使用聚類,并聚成3個部分(部分的數量真的取決于你的業(yè)務動態(tài)和目標):
低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。
創(chuàng)建訓練和測試數據集。
訓練集將用于構建機器學習模型。
我們將把我們的模型應用到測試集,看看它的實際性能。
下面的代碼為做了這些:
#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()后會發(fā)生什么:
segment列沒有了,但我們有新的數字列來表示它。我們已經將它轉換為3個不同的列,其中包含0和1,并使其可用于我們的機器學習模型。
行的相關性我們有以下數據:
我們發(fā)現(xiàn),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以外的不同的模型
對當前模型使用超參數調整
如有可能,向模型中添加更多數據
好了!現(xiàn)在我們有一個機器學習模型,可以預測未來客戶的LTV細分情況。我們可以很容易地在此基礎上調整我們的行動。例如,我們絕對不想失去高LTV的客戶。因此,我們將在下一部分中關注客戶流失預測。
—END—
英文原文:https://towardsdatascience.com/data-driven-growth-with-python-part-3-customer-lifetime-value-prediction-6017802f2e0f
往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習在線手冊深度學習在線手冊AI基礎下載(pdf更新到25集)本站qq群1003271085,加入微信群請回復“加群”獲取一折本站知識星球優(yōu)惠券,復制鏈接直接打開:https://t.zsxq.com/yFQV7am喜歡文章,點個在看
總結
以上是生活随笔為你收集整理的【实战】用机器学习来提升你的用户增长:(三、预测客户的终生价值)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 跟优秀的人一起进步:四月组队学习
- 下一篇: 解决Github速度太慢的几种方案