用Logistic和隨機森林建立流失預(yù)警模型(含多個模型)


產(chǎn)品如同蓄水池骏令,用戶好比池中之水蔬捷。池子中每時每刻都有新用戶源源不斷地加入,也有一部分用戶選擇離開。如果用戶流失超過新用戶的補給周拐,且速度越來越快铡俐、規(guī)模越來越大時,產(chǎn)品如若不警惕妥粟,蓄水池遲早會干涸审丘。

不合理的周期造成預(yù)測準(zhǔn)確率低且不平衡,我們需要不斷嘗試周期劃分勾给,在保證整體準(zhǔn)確率的情況下尋求流失與留存準(zhǔn)確率最佳的平衡點滩报,才能更為準(zhǔn)確地同時預(yù)測流失及留存情況。


流失比較經(jīng)典的定義是“一段時間內(nèi)未進(jìn)行關(guān)鍵行為的用戶”播急,關(guān)鍵點在于如何界定時間周期(流失周期)和關(guān)鍵行為(流失行為)露泊。

用戶回訪率 = 回訪用戶數(shù) ÷ 流失用戶數(shù) × 100%

通過流失預(yù)警模型,我們可以獲得產(chǎn)品一系列功能模塊或指標(biāo)對流失留存的影響因子旅择,并計算出每個用戶的流失概率惭笑。通過影響因子,我們可以對流失原因有所了解生真,在此基礎(chǔ)上進(jìn)行深入研究和確認(rèn)沉噩,結(jié)合用戶反饋的頻率、專家意見等確定改版的優(yōu)先級柱蟀。

區(qū)分出可能流失的用戶是為了提高挽留策略的針對性川蒙,提高效率與減少成本,實現(xiàn)精細(xì)化運營——這也是流失模型的核心價值所在长已。

從用戶使用的輕重程度出發(fā)(如上圖)畜眨,在通過模型計算出用戶未來的流失概率后,將使用App的頻率和時長作為用戶輕重度的劃分標(biāo)準(zhǔn)术瓮,結(jié)合用戶流失留存預(yù)期康聂,將用戶劃分為高價值、重點發(fā)展胞四、重點轉(zhuǎn)化恬汁、有待挽留等幾種類型,分析每個類型用戶不同的行為特點和使用痛點辜伟,采取針對性的運營策略氓侧。

當(dāng)然,流失模型也可結(jié)合付費維度進(jìn)行研究导狡。先篩選出極有可能將會流失的用戶约巷,再根據(jù)購買頻次和付費金額來進(jìn)行細(xì)分:從未付費的用戶可通過優(yōu)惠券、促銷活動或超低價商品吸引回訪旱捧、促成首單購買独郎;少量付費且客單價低的用戶可以精準(zhǔn)推送符合個性化偏好的商品,或者推薦符合該用戶消費層次的超值商品;多次付費的老用戶囚聚,可以增加會員專屬優(yōu)惠靖榕,通過回饋激勵增強用戶粘性,延長使用周期顽铸。

以上只是流失模型的兩個層面的應(yīng)用茁计,在不同項目中還可以結(jié)合多種方式對用戶進(jìn)行精細(xì)化運營。模型準(zhǔn)確性高的話谓松,可以用更少的成本星压、對用戶更少的干擾來留住更有價值的用戶。

下面舉例:電信公司希望針對客戶的信息預(yù)測其流失可能性
從機器學(xué)習(xí)的分類來講鬼譬, 這是一個監(jiān)督問題中的分類問題娜膘。 具體來說, 是一個二分類問題优质。

數(shù)據(jù)預(yù)處理

讀取數(shù)據(jù):

from __future__ import division
import pandas as pd
import numpy as np
ds = pd.read_csv('F:\churn.csv')
col_names = ds.columns.tolist()
print("Column names:")
print(col_names)
ds.shape

變量說明:

subscriberID="個人客戶的ID"
churn="是否流失:1=流失";
Age="年齡"
incomeCode="用戶居住區(qū)域平均收入的代碼"
duration="在網(wǎng)時長"
peakMinAv="統(tǒng)計期間內(nèi)最高單月通話時長"
peakMinDiff="統(tǒng)計期間結(jié)束月份與開始月份相比通話時長增加數(shù)量"
posTrend="該用戶通話時長是否呈現(xiàn)出上升態(tài)勢:是=1"
negTrend="該用戶通話時長是否呈現(xiàn)出下降態(tài)勢:是=1"
nrProm="電話公司營銷的數(shù)量"
prom="最近一個月是否被營銷過:是=1"
curPlan="統(tǒng)計時間開始時套餐類型:1=最高通過200分鐘竣贪;2=300分鐘;3=350分鐘巩螃;4=500分鐘"
avPlan="統(tǒng)計期間內(nèi)平均套餐類型"
planChange="統(tǒng)計結(jié)束時和開始時套餐的變化:正值代表套餐檔次提升演怎,負(fù)值代表下降,0代表不變"
posPlanChange="統(tǒng)計期間是否提高套餐:1=是"
negPlanChange="統(tǒng)計期間是否降低套餐:1=是"
call_10086="撥打10086的次數(shù)"

查看前5行

ds.head()

整個數(shù)據(jù)集有3463條數(shù)據(jù)避乏, 20個維度爷耀,第二項是分類是否流失。

查看數(shù)據(jù)類型:

ds.info()

全為浮點型數(shù)據(jù)拍皮,不需要數(shù)值轉(zhuǎn)換

首先查看因變量中各類別的比例差異歹叮,通過餅圖:

import matplotlib.pyplot as plt
# 數(shù)據(jù)集中是否違約的客戶比例
# 為確保繪制的餅圖為圓形,需執(zhí)行如下代碼
plt.axes(aspect = 'equal')
# 中文亂碼和坐標(biāo)軸負(fù)號的處理
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
#重命名因變量
ds.rename(columns={'churn':'y'},inplace=True)
# 統(tǒng)計客戶是否違約的頻數(shù)
counts = ds.y.value_counts()
# 繪制餅圖
plt.pie(x = counts, # 繪圖數(shù)據(jù)
        labels=pd.Series(counts.index).map({0:'不流失',1:'流失'}), # 添加文字標(biāo)簽
        autopct='%.1f%%' # 設(shè)置百分比的格式铆帽,這里保留一位小數(shù)
       )
# 顯示圖形
plt.show()

總體來說咆耿,兩個類別的比例不算失衡。

拆分?jǐn)?shù)據(jù)

# 將數(shù)據(jù)集拆分為訓(xùn)練集和測試集
# 導(dǎo)入第三方包
from sklearn import model_selection
from sklearn import ensemble
from sklearn import metrics

# 排除數(shù)據(jù)集中的ID變量和因變量锄贼,剩余的數(shù)據(jù)用作自變量X
X = ds.drop(['y'], axis = 1)
y = ds.y
# 數(shù)據(jù)拆分
X_train,X_test,y_train,y_test = model_selection.train_test_split(X,y,test_size = 0.3, random_state = 1234)

法一:利用ROC(只涉及l(fā)ogistic和隨機森林)

Logistic模型

建模

from sklearn import linear_model
#利用訓(xùn)練集建模
sklearn_logistic=linear_model.LogisticRegression()
sklearn_logistic.fit(X_train,y_train)
#返回模型的各個參數(shù)
print(sklearn_logistic.intercept_,sklearn_logistic.coef_)

預(yù)測構(gòu)建混淆矩陣

# 模型預(yù)測
sklearn_predict = sklearn_logistic.predict(X_test)
# 預(yù)測結(jié)果統(tǒng)計
pd.Series(sklearn_predict).head()
pd.Series(sklearn_predict).value_counts()

判斷為不流失的為1039個

# 導(dǎo)入第三方模塊
from sklearn import metrics
# 混淆矩陣
cm = metrics.confusion_matrix(y_test, sklearn_predict, labels = [0,1])
cm

繪制ROC曲線

Accuracy = metrics.scorer.accuracy_score(y_test, sklearn_predict)
Sensitivity = metrics.scorer.recall_score(y_test, sklearn_predict)
Specificity = metrics.scorer.recall_score(y_test, sklearn_predict, pos_label=0)
print('模型準(zhǔn)確率為%.2f%%:' %(Accuracy*100))
print('正例覆蓋率為%.2f%%' %(Sensitivity*100))
print('負(fù)例覆蓋率為%.2f%%' %(Specificity*100))

整體的預(yù)測準(zhǔn)確率一般

# y得分為模型預(yù)測正例的概率
y_score = sklearn_logistic.predict_proba(X_test)[:,1]
# 計算不同閾值下票灰,fpr和tpr的組合值,其中fpr表示1-Specificity宅荤,tpr表示Sensitivity
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 計算AUC的值
roc_auc = metrics.auc(fpr,tpr)

# 繪制面積圖
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加邊際線
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加對角線
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x軸與y軸標(biāo)簽
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 顯示圖形
plt.show()

低于0.8,認(rèn)定回歸模型是不合理的

隨機森林模型

from sklearn import ensemble
# 構(gòu)建隨機森林
RF_class = ensemble.RandomForestClassifier(n_estimators=200, random_state=1234)
# 隨機森林的擬合
RF_class.fit(X_train, y_train)
# 模型在測試集上的預(yù)測
RFclass_pred = RF_class.predict(X_test)
# 模型的準(zhǔn)確率
print('模型在測試集的預(yù)測準(zhǔn)確率:\n',metrics.accuracy_score(y_test, RFclass_pred))
# 計算繪圖數(shù)據(jù)
y_score = RF_class.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
roc_auc = metrics.auc(fpr,tpr)
# 繪圖
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
plt.plot(fpr, tpr, color='black', lw = 1)
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
plt.show()

遠(yuǎn)遠(yuǎn)高于0.8浸策,認(rèn)為模型合理

再挑選出重要因素

# 變量的重要性程度值
importance = RF_class.feature_importances_
# 構(gòu)建含序列用于繪圖
Impt_Series = pd.Series(importance, index = X_train.columns)
# 對序列排序繪圖
Impt_Series.sort_values(ascending = True).plot('barh')
plt.show()

取出重要性比較高的變量再利用交叉驗證選擇參數(shù)建模

# 取出重要性比較高的自變量建模
predictors = list(Impt_Series[Impt_Series>0.015].index)
predictors

重新建模

# 隨機森林的擬合
RF_class.fit(X_train[predictors], y_train)
# 模型在測試集上的預(yù)測
RFclass_pred = RF_class.predict(X_test[predictors])
# 模型的準(zhǔn)確率
print('模型在測試集的預(yù)測準(zhǔn)確率:\n',metrics.accuracy_score(y_test, RFclass_pred))
# 計算繪圖數(shù)據(jù)
y_score = RF_class.predict_proba(X_test[predictors])[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
roc_auc = metrics.auc(fpr,tpr)
# 繪圖
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
plt.plot(fpr, tpr, color='black', lw = 1)
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
plt.show()

遠(yuǎn)遠(yuǎn)高于0.8且準(zhǔn)確率上升冯键,認(rèn)為模型合理

法二:利用誤差均值(多個模型循環(huán)比較)

# prepare models
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn import linear_model
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn import naive_bayes
from sklearn import svm
models = []
models.append(('LR', linear_model.LogisticRegression()))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))
models.append(('NB', naive_bayes.GaussianNB()))
models.append(('SVM', svm.SVC()))
# evaluate each model in turn
results = []
names = []
scoring = 'accuracy'
for name, model in models:
    kfold = KFold(n_splits=10, random_state=7)
    cv_results = cross_val_score(model, X_test, y_test, cv=kfold, scoring=scoring)
    results.append(cv_results)
    names.append(name)
    msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)
# boxplot algorithm comparison
fig = plt.figure()
fig.suptitle('Algorithm Comparison')
ax = fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.show()


可以看出,LDA判別效果最好
但可以利用集成學(xué)習(xí)庸汗,例如隨機森林

from sklearn.ensemble import RandomForestClassifier
num_trees = 100
max_features = 3
kfold = KFold(n_splits=10, random_state=7)
model = RandomForestClassifier(n_estimators=num_trees, max_features=max_features)
results = cross_val_score(model, X_test, y_test, cv=kfold)
print(results.mean())

則隨機森林的模型更加合理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惫确,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌改化,老刑警劉巖掩蛤,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異陈肛,居然都是意外死亡揍鸟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門句旱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阳藻,“玉大人,你說我怎么就攤上這事谈撒⌒饶啵” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵啃匿,是天一觀的道長蛔外。 經(jīng)常有香客問我,道長溯乒,這世上最難降的妖魔是什么冒萄? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮橙数,結(jié)果婚禮上尊流,老公的妹妹穿的比我還像新娘。我一直安慰自己灯帮,他們只是感情好崖技,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钟哥,像睡著了一般迎献。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上腻贰,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天吁恍,我揣著相機與錄音,去河邊找鬼播演。 笑死冀瓦,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的写烤。 我是一名探鬼主播翼闽,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洲炊!你這毒婦竟也來了感局?” 一聲冷哼從身側(cè)響起尼啡,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎询微,沒想到半個月后崖瞭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡撑毛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年书聚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片代态。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡寺惫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹦疑,到底是詐尸還是另有隱情西雀,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布歉摧,位于F島的核電站艇肴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏叁温。R本人自食惡果不足惜再悼,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望膝但。 院中可真熱鬧冲九,春花似錦、人聲如沸跟束。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冀宴。三九已至灭贷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間略贮,已是汗流浹背甚疟。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逃延,地道東北人览妖。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像真友,于是被迫代替她去往敵國和親黄痪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 每天進(jìn)步一點點點點點點點點點點點點點點點點點點點點點點點點點點點點點點~~從開始只能寫幾句話盔然、模仿別人的觀點桅打,到現(xiàn)...
    一個帥氣的名字呀閱讀 18,046評論 4 31
  • 所有的用戶運營工作,都建立在一個相同的基礎(chǔ)上愈案,即對用戶的充分了解挺尾。 用戶運營所有的工作都是圍繞著人來做,是人就繞不...
    琉璃橘閱讀 3,248評論 0 9
  • DOM站绪,BOM遭铺。 MIME:MultipurposeInternetMailExtensions,是描述消息內(nèi)容類...
    梅子_may閱讀 81評論 0 0
  • 今天下午來海印長城學(xué)習(xí)UK里里,好久沒碰魂挂,幾乎忘光了。在小白老師的指引下溫習(xí)了簡單的和弦馁筐,慢慢撿回來一些涂召。《冰雪奇...
    Amea_心清閱讀 159評論 0 0
  • 我的朋友李華的母親兩年前出了車禍成為了植物人敏沉。吃喝拉撒都在床上果正,更困難的是每次吃飯都要用豆?jié){機把食物打成糊狀,把嘴...
    LH來慧閱讀 563評論 11 17