機器學習:怎樣用模型預測使用者的生命週期價值?

語言: CN / TW / HK

持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第4天,點選檢視活動詳情

定義問題

預測下使用者在未來能帶來的收益。

LTV

這個被稱為使用者的生命週期價值(CLV:Customer Lifetime Value)或稱為LTV(Lifetime Value),指的是每個使用者(購買者、會員、使用者)在未來可能為該服務帶來的收益總和。

image.png

適用領域

對以廣告、銷售等動態現金流入的服務(例如App服務、會員網站、電子商務)是相當重要的營運參考資料。 1. 瞭解產品使用者實際價值。 2. 基於大資料的CLV管理方法,最大化有價值使用者的利潤,對有潛力的使用者提升銷售,甚至挖掘其他“有價值的使用者”。 3. 給予行銷人員廣告投放方向。例如:取得一個使用者的成本不可高於CLV。

資料預處理

預測收益當然需要使用者的交易資料,所以繼續繼續使用《機器學習:從資料中找到使用者的RFM值》中的資料。

``` import pandas as pd # 匯入Pandas

df_sales=pd.read_csv('/Users/wanghaifeng/Documents/零基礎實戰機器學習/geektime-main/獲客關05/易速鮮花訂單記錄.csv') df_sales.head() ```

image.png

跟著課程中使用頭三個月的R、F、M這三個數值作為特徵,一年的總消費額作為標籤,做一個迴歸模型預測出LTV。(這個是課程作者選的,至於為啥以後再研究

資料清洗

``` df_sales.drop_duplicates() #刪除重複的資料行

df_sales=df_sales.loc[df_sales['數量']>0] # 清洗掉數量小於等於0的資料

df_sales.describe()

``` 這裡說下問題:課程裡的沒有清洗數量小於0的髒資料,下面使用模型預測出來的值比較好看,但是清洗掉就不好了,這個先擱置,筆者學這個課程也是先對機器學習有個感覺,太糾結就走不下去了。

加上總價

df_sales['總價'] = df_sales['數量'] * df_sales['單價'] # 計算每單的總價

整理資料集記錄的時間範圍

import numpy as np # 匯入NumPy print('日期範圍: %s ~ %s' % (df_sales['消費日期'].min(), df_sales['消費日期'].max())) df_sales['消費日期'] = pd.to_datetime(df_sales['消費日期']) #轉換日期格式 print('日期範圍: %s ~ %s' % (df_sales['消費日期'].min(), df_sales['消費日期'].max())) 輸出: 日期範圍: 1/1/2021 10:11 ~ 9/9/2020 9:20 日期範圍: 2020-06-01 09:09:00 ~ 2021-06-09 12:31:00 資料集中的時間跨度是2020-06-01到2021-06-09,我們想要的是一年的消費總額,所以剔除: df_sales=df_sales.loc[df_sales['消費日期'] < '2021-06-01'] print('日期範圍: %s ~ %s' % (df_sales['消費日期'].min(), df_sales['消費日期'].max())) 輸出: 日期範圍: 2020-06-01 09:09:00 ~ 2021-05-31 17:37:00

構建特徵和標籤

構建特徵

特徵只需要前三個月的資料: df_sales_3m=df_sales[(df_sales.消費日期 > '2020-06-01')&(df_sales.消費日期 <= '2020-08-30')] df_sales_3m.reset_index(drop=True) 特徵提取: df_user_LTV = pd.DataFrame(df_sales['使用者碼'].unique()) #生成以使用者碼為主鍵的結構 df_user_LTV.columns=['使用者碼'] #設定欄位名 df_user_LTV.head() df_R_value=df_sales_3m.groupby('使用者碼').消費日期.max().reset_index() #找到每個使用者的最近消費日期,構建df_R_value物件 df_R_value.columns=['使用者碼','最近購買日期'] df_R_value['R值']=(df_R_value['最近購買日期'].max()-df_R_value['最近購買日期']).dt.days #計算最近日期與上次消費日期的天數 df_user_LTV=pd.merge(df_user_LTV,df_R_value[['使用者碼','R值']],on='使用者碼') #把上次消費距最新日期的天數(R值)合併至df_user_LTV df_F_value=df_sales_3m.groupby('使用者碼').消費日期.count().reset_index() df_F_value.columns=['使用者碼','F值'] df_user_LTV=pd.merge(df_user_LTV,df_F_value[['使用者碼','F值']],on='使用者碼') df_M_value=df_sales_3m.groupby('使用者碼').總價.sum().reset_index() df_M_value.columns=['使用者碼','M值'] df_user_LTV = pd.merge(df_user_LTV, df_M_value, on='使用者碼') #把消費總額整合至df_user結構 df_user_LTV #顯示使用者表結構

image.png

構建標籤

df_user_ly=df_sales.groupby('使用者碼')['總價'].sum().reset_index() #計算每個使用者整年消費總額,構建df_user_ly df_user_ly.columns=['使用者碼','年度LTV'] df_user_ly.head() df_LTV=pd.merge(df_user_LTV,df_user_ly,how='left') df_LTV

image.png

建立特徵集和標籤集

建立特徵集

X=df_LTV.drop(['使用者碼','年度LTV'],axis=1) #特徵集 X.head() image.png

建立標籤集

y=df_LTV['年度LTV'] y.head()

image.png

拆分訓練集、驗證集和測試集

``` from sklearn.model_selection import train_test_split

先拆分訓練集和其它集

X_train,X_rem,y_train,y_rem=train_test_split(X,y,train_size=0.7,random_state=36)

再把其它集拆分成驗證集和測試集

X_valid,X_test,y_valid,y_test=train_test_split(X_rem,y_rem,test_size=0.5,random_state=36) ```

選擇演算法建立模型

image.png

課程中使用最基本的線性迴歸模型、決策樹模型和隨機森林模型。

  • 線性迴歸:通過梯度下降找到最優的權重和模型偏置的最基本的迴歸演算法。裡,我會用它作為一個基準模型,把其它模型的結果與其相比較,來確定優劣。
  • 決策樹演算法:簡單地說是從樣本資料的特徵屬性中,通過學習簡單的決策規則,也就是我們耳熟能詳的IF ELSE規則,來預測目標變數的值。這個演算法的核心是劃分點的選擇和輸出值的確定。

image.png 可以看到,這種演算法是根據兩個特徵x1和x2的值,以及標籤y的取值,對二維平面上的區域進行精準分割,以確定從特徵到標籤的對映規則。根據樹的深度和分叉時所選擇的特徵的不同,我們可以訓練出很多顆不一樣的樹來。

  • 隨機森林:就是由多棵決策樹構成的整合學習演算法。它既能用於分類問題,也能用於迴歸問題。而且無論是哪類問題,它都是相對優秀的演算法。在訓練模型的過程中,隨機森林會構建多個決策樹,如果解決的是分類問題,那麼它的輸出類別是由個別樹輸出的類別的眾數而定;如果解決的是迴歸問題,那麼它會對多棵樹的預測結果進行平均。隨機森林糾正了決策樹過度擬合其訓練集的問題,在很多情況下它都能有不錯的表現。這裡的“過擬合”,其實就是說模型對訓練集的模擬過頭了,反而不太適合驗證集和測試集。

from sklearn.linear_model import LinearRegression #匯入線性迴歸模型 from sklearn.tree import DecisionTreeRegressor #匯入決策樹迴歸模型 from sklearn.ensemble import RandomForestRegressor #匯入隨機森林迴歸模型 model_lr=LinearRegression() #建立線性迴歸模型 model_dtr=DecisionTreeRegressor() # 建立決策樹迴歸模型 model_rfr=RandomForestRegressor() #建立隨機森林迴歸模型

訓練模型

model_lr.fit(X_train,y_train) # 擬合線性迴歸模型 model_dtr.fit(X_train,y_train) # 擬合決策樹模型 model_rfr.fit(X_train,y_train) # 擬合隨機森林模型

評估模型

X_valid.iloc[2] # 隨便選擇一個數據 輸出: R值 1.00 F值 154.00 M值 1427.73 Name: 163, dtype: float64

print('真值:', y_valid.iloc[2]) #線性迴歸模型預測值 print('線性迴歸預測值:', y_valid_preds_lr[2]) #線性迴歸模型預測值 print('決策樹預測值:', y_valid_preds_dtr[2]) #決策樹模型預測值 print('隨機森林預測值:', y_valid_preds_rfr[2]) #隨機森林模型預測值 輸出: 真值: 4432.43 線性迴歸預測值: 7474.4181424883545 決策樹預測值: 4074.57 隨機森林預測值: 4282.643300000004 我們還要用$R2$、MSE等評估指標在驗證集上做整體評估,選使用$R2$: from sklearn.metrics import r2_score,mean_absolute_error print('驗證集上的R平方-線性迴歸:%0.4f' % r2_score(y_valid,model_lr.predict(X_valid))) print('驗證集上的R平方分數-決策樹: %0.4f' % r2_score(y_valid, model_dtr.predict(X_valid))) print('驗證集上的R平方分數-隨機森林: %0.4f' % r2_score(y_valid, model_rfr.predict(X_valid))) 輸出: 驗證集上的R平方-線性迴歸:0.4410 驗證集上的R平方分數-決策樹: 0.1209 驗證集上的R平方分數-隨機森林: 0.4538 可以看出隨機森林樹預測能力好點。

但是0.4幾說明擬合的其實不咋樣。 import matplotlib.pyplot as plt #匯入Matplotlib的pyplot模組 y_test_preds_rfr = model_rfr.predict(X_test) #用模型預隨機森林模型預測驗證集 plt.scatter(y_test, y_test_preds_rfr) #預測值和實際值的散點圖 plt.plot([0, max(y_test)], [0, max(y_test_preds_rfr)], color='gray', lw=1, linestyle='--') #繪圖 plt.xlabel('實際值') #X軸 plt.ylabel('預測值') #Y軸 plt.title('實際值 vs. 預測值') #標題

image.png

參考/來源

客戶生命週期價值

07|迴歸分析:怎樣用模型預測使用者的生命週期價值?