您當前的位置:首頁 > 動漫

客戶購買預測【分類模型的運用】

作者:由 薄執玖 發表于 動漫時間:2020-12-02

和鯨社群的一個新人賽,主要考察的是分類模型的運用。

主要嘗試了SVC,Logistic迴歸,隨機森林,LightGBM,透過網格搜尋調參,最終使用了隨機森林作為預測模型。線上第四期rank:27,AUC得分:0。91364870。

目前只提交了一次結果,還有很多提升最佳化的空間。

客戶購買預測【分類模型的運用】

和鯨排行榜

以下是具體的分析處理過程。

案例背景說明

案例資料與一次葡萄牙銀行機構的營銷活動相關。銀行的客服人員至少需要聯絡客戶一次,以確認客戶是否有意願購買該銀行的產品(定期存款)。

任務是基本型別為分類任務,即透過客戶的一些行為特徵,來預測客戶是否購買該銀行的產品。

資料集說明

共18個可用欄位,其中y是因變數。資料說明來自網站截圖。

客戶購買預測【分類模型的運用】

和鯨線上截圖資料說明

EDA,資料預處理,特徵工程

一、簡單的探索性分析

客戶購買預測【分類模型的運用】

訓練集資訊一覽

載入資料後,簡單的看了一下,並沒有缺失資料。接下來,按照資料型別來分別觀察資料。

首先來看看分類資料

這邊我選擇了透過檢視每個分類變數的IV值。手動添加了一個signal值來表示變數更能預測0類還是1類

#定義了IV值計算的函式,並且把計算過程打印出來

def

woe_iv_compute

df

):

groups

=

df

iloc

[:,

0

labels

=

df

iloc

[:,

1

variables

=

np

unique

groups

groupname

=

df

columns

0

labelname

=

df

columns

1

all_0_count

=

df

labelname

==

0

sum

0

all_1_count

=

df

labelname

==

1

sum

0

woe_group

=

0

iv_group

=

0

iv_list

=

[]

for

item

in

variables

signal

=

‘+’

df_item

=

df

df

groupname

==

item

df_item_0_count

=

df_item

labelname

==

0

sum

0

df_item_1_count

=

df_item

labelname

==

1

sum

0

pi_0

=

df_item_0_count

/

all_0_count

pi_1

=

df_item_1_count

/

all_1_count

woe_i

=

np

log

pi_1

/

pi_0

iv_i

=

pi_1

-

pi_0

*

woe_i

woe_group

=

woe_group

+

woe_i

iv_group

=

iv_group

+

iv_i

if

pi_1

-

pi_0

<=

0

signal

=

‘-’

print

f

{item}

_iv:’

signal

iv_i

iv_list

append

iv_i

print

‘woe:’

woe_group

print

‘iv:’

iv_group

return

iv_group

#探索分類變數的IV值

object_list

=

train_data

select_dtypes

“object”

for

item

in

object_list

print

f

{item}

print

train_data

item

value_counts

())

woe_iv_compute

train_data

[[

item

‘y’

]])

print

‘-’

*

20

客戶購買預測【分類模型的運用】

部分分類變數的IV值計算結果一覽

透過計算IV值,可以看到一些有趣的現象:retire的職業人群更可能購買產品;婚姻預測性較弱,單身非離異人群更可能購買產品;初等教育更不可能購買產品,預測能力比婚姻更強;是否違約的預測能力很弱;住房貸款強能預測是否會購買產品,其中沒有貸款的更可能購買……。

而每個分類變數的iv得分都在0.1以上,

於是我最終都保留了這些分類變數進入模型。

接下來,是對int型變數的一些探索:

首先是一個簡單的描述統計:

客戶購買預測【分類模型的運用】

int型變數描述統計一覽

從Q1,Q2,Q3的取值來看,上述int型變數基本上都存在右偏。

還是具體的一個個來看。

age

利用y的取值,分開age資料,分別繪製age分佈圖

age_0 = train_data[train_data。y == 0][[‘age’]]

age_1 = train_data[train_data。y == 1][[‘age’]]

age_0。age。plot(kind= ‘kde’,label = ‘0’)

age_1。age。plot(kind= ‘kde’,label =‘1’)

plt。legend()

客戶購買預測【分類模型的運用】

0/1人群的各自age分佈圖

從圖上也能看到,主要差距出現在20-60代更不可能購買,而60-80代更可能購買。

然後,我對age進行了分箱處理。為了找到age的最佳分箱,我這裡將分箱後的區間進行了IV值計算,選擇了分箱數折中但依然有較好的預測能力的箱子數。

#探索age的最佳分箱

bin_count = np。arange(4,12,1)

iv_s = []

#等頻分箱

‘’‘

for bin_c in bin_count:

age_y = pd。DataFrame(pd。qcut(train_data。age,bin_c))

age_y[’y‘] = train_data[’y‘]

print(’當前分箱數:‘,bin_c)

bin_c_iv = woe_iv_compute(age_y_2)

iv_s。append(bin_c_iv)

woe_iv_compute(age_y)

’‘’

#等距分箱

for bin_c in bin_count:

age_y_2 = pd。DataFrame(pd。cut(train_data。age,bin_c))

age_y_2[‘y’] = train_data[‘y’]

print(‘當前分箱數:’,bin_c)

bin_c_iv = woe_iv_compute(age_y_2)

iv_s。append(bin_c_iv)

sns。scatterplot(x = bin_count,y= iv_s)

客戶購買預測【分類模型的運用】

分箱探索過程,和不同分箱的IV得分

客戶購買預測【分類模型的運用】

9等距分箱得分

可以看到,9等距分箱具有比較好的預測能力,同時可以看到,60-77這個區間裡的人群,更容易購買活動產品。

balance【每年賬戶的平均餘額】

和age一樣的處理方式。

train_data。balance。plot(kind=‘box’)

客戶購買預測【分類模型的運用】

balance箱線圖

可以看到,balance大部分值都集中在0-10000以內。

客戶購買預測【分類模型的運用】

balance不同等頻分箱IV得分

客戶購買預測【分類模型的運用】

8等頻分箱IV得分

最終,透過8等頻分箱,得到了比較好的結果。同時可以看到,隨著年餘額的增多,更可能購買產品,年餘額為負的更不可能購買產品。

其他int型變數,用上述的方式進行了處理。

此處省略過程,只給出部分可以得出的結論:

1、通訊時長【duration】在0-113的更不可能購買,在449以上的更可能購買

2、在本次活動中,與該客戶交流過的次數【campaign】,大於18次的,幾乎全部沒有購買可能。

建模調參

因為資料集是不平衡的資料集,於是採用了分層抽樣來得到訓練集和驗證集。

from sklearn。model_selection import StratifiedShuffleSplit

ss = StratifiedShuffleSplit(n_splits=1,train_size=0。75,random_state=42)

X_train_v = X_train。values

X_test_v = X_test。values

y_train_v = y_train。values

#先將訓練集分成訓練子集和驗證子集

for train_code,validate_code in ss。split(X_train,y_train):

train_x = X_train_v[train_code]

validate_x = X_train_v[validate_code]

train_y = y_train_v[train_code]

validate_y = y_train_v[validate_code]

接下來,就是呼叫多個模型調參的過程。

from sklearn。model_selection import GridSearchCV

import lightgbm as lgb

from sklearn。linear_model import LogisticRegression

from sklearn。tree import DecisionTreeClassifier

from sklearn。ensemble import RandomForestClassifier

from sklearn。svm import SVC

from sklearn。neighbors import KNeighborsClassifier

#邏輯迴歸

param = {“penalty”: [“l1”, “l2”, ], “C”: [0。1, 1,5,10], “solver”: [“liblinear”,“saga”]}

gs = GridSearchCV(estimator=LogisticRegression(), param_grid=param, cv=5, scoring=“roc_auc”)

gs。fit(X_train_v,y_train_v)

#隨機森林

param = {‘n_estimators’:list(np。arange(10,100,10)),

‘min_samples_leaf’:[2,3,4]}

gs = GridSearchCV(estimator=RandomForestClassifier(), param_grid=param, cv=2, scoring=“roc_auc”)

gs。fit(train_x,train_y)

print(gs。best_params_)

y_pred = gs。best_estimator_。predict(validate_x)

print(classification_report(validate_y,y_pred))

#lightGBM

param = {

‘learning_rate’: [0。01,0。03,0。05,0。1,0。3,0。5],

‘num_leaves’: [15,30,45,80],

‘n_estimators’: [30,60,90,120]}

gs = GridSearchCV(estimator=LGBMClassifier(), param_grid=param, cv=5, scoring=“roc_auc”)

gs。fit(train_x,train_y)

print(gs。best_params_)

y_pred = gs。best_estimator_。predict(validate_x)

print(classification_report(validate_y,y_pred))

寫了一個畫ROC曲線的方法,因為本次提交比對的是AUC值

#畫roc-auc曲線

def roc_auc_curve(X,y,model):

FPR,TPR,thresholds=roc_curve(y,model。predict_proba(X)[:,1],pos_label=1)

auc=roc_auc_score(y,model。predict_proba(X)[:,1])

plt。figure()

plt。plot(FPR,TPR,color=‘red’,label=‘ROC curve (auc = %0。2f)’%auc)

plt。plot([0,1],[0,1],color=‘black’,linestyle=‘——’)

plt。xlim([-0。05,1。05])

plt。ylim([-0。05,1。05])

plt。xlabel(‘False Positive Rate’)

plt。ylabel(‘Recall’)

plt。title(‘ROC-Curve’)

plt。legend(loc=‘lower right’)

下面是隨機森林的roc曲線圖

客戶購買預測【分類模型的運用】

隨機森林roc

下面是隨機森林的各變數的重要性得分圖

客戶購買預測【分類模型的運用】

隨機森林feature_importance圖

#樹的視覺化程式碼

estimator = best_tree。estimators_[5]

from sklearn。tree import export_graphviz

# 匯出為dot 檔案

export_graphviz(estimator, out_file=‘yourpath/tree。dot’,

feature_names = X_train。columns,

class_names = [‘0’,‘1’],

rounded = True, proportion = False,

precision = 2, filled = True)

結。

標簽: train  AGE  iv  df  分箱