您當前的位置:首頁 > 體育

【風控建模】基於邏輯迴歸的評分卡開發(I)

作者:由 蜀道難 發表于 體育時間:2020-03-29

前言:

建立風控模型的一般流程是【業務定義】——【風險定義】——【風險化解】——【風險策略】。此處僅討論【風險化解】部分,即用演算法訓練評分卡,使用邏輯迴歸(LogisticRegression)模型討論評分卡的建模。

一。邏輯迴歸算法理解

邏輯迴歸是在資料服從伯努利分佈的假設下,透過極大似然方法,運用梯度下降法來求解引數,從而達到將資料二分類的目的。

算法理解可參考這篇文章:

二。

評分卡建模流程

基於Logistic迴歸的申請評分卡模型開發:

①資料準備:收集並整合在庫客戶的資料,定義目標變數,排除特定樣本。

②探索性資料分析:評估每個變數的值分佈情況,處理異常值和缺失值。

③資料預處理:變數篩選,變數分箱,WOE轉換、樣本抽樣。

④模型開發:邏輯迴歸擬合模型。

⑤模型評估:常見幾種評估方法,ROC、KS、AUC等。

⑥生成評分卡

資料清洗需要注意的點:

【目標變數定義】:信用評分卡和反欺詐評分卡對Y值的定義是不同的;應根據滾動率情況確定壞樣本的逾期天數;樣本的表現期應一致。

【變數和樣本篩選】:剔除缺失率嚴重的變數和樣本。

【缺失值填充】:缺失值填充方法有均值填充、固定值填充、隨機森林方法填充等,具體方法的選用要同時考慮缺失比率和業務實質。

如下圖,整體建模分為四個部分:1。整理在庫基礎資料(01_InputSQL

); 2。合併基礎資料

(02_LongFeatureList);3。探索性資料分析(03_Exploratory_Data

Analysis);4。評分卡模型開發(

04_Scorecard)。

【風控建模】基於邏輯迴歸的評分卡開發(I)

專案結構

三。評分卡模型開發

著重講下模型開發部分(04_Scorecard),內容包括特徵分箱、WOE單調性調整、WOE轉換、模型擬合、模型評估。

分享模型開發部分Python指令碼。

GitHub連結:

1.特徵分箱

特徵分箱方法有等頻分箱、等距分箱、Best KS分箱、類別分箱、卡方分箱。特徵分箱過程中常常需要同時使用多種分箱方法。以卡方分箱為例:

#卡方分箱,對於數值變數用卡方分箱

def

graphforbestbin

DF

X

Y

n

=

5

q

=

20

graph

=

False

):

‘’‘

自動最優分箱函式,基於卡方檢驗的分箱

引數:

DF: 需要輸入的資料

X: 需要分箱的列名

Y: 分箱資料對應的標籤 Y 列名

n: 保留分箱個數

q: 初始分箱的個數

graph: 是否要畫出IV影象

區間為前開後閉 (]

’‘’

DF

=

DF

[[

X

Y

]]

copy

()

bins_df

=

pd

DataFrame

()

DF

“qcut”

],

bins

=

pd

qcut

DF

X

],

retbins

=

True

q

=

q

duplicates

=

“drop”

coount_y0

=

DF

loc

DF

Y

==

0

groupby

by

=

“qcut”

count

()[

Y

coount_y1

=

DF

loc

DF

Y

==

1

groupby

by

=

“qcut”

count

()[

Y

num_bins

=

*

zip

bins

bins

1

:],

coount_y0

coount_y1

)]

for

i

in

range

q

):

if

0

in

num_bins

0

][

2

:]:

num_bins

0

2

=

[(

num_bins

0

][

0

],

num_bins

1

][

1

],

num_bins

0

][

2

+

num_bins

1

][

2

],

num_bins

0

][

3

+

num_bins

1

][

3

])]

continue

for

i

in

range

len

num_bins

)):

if

0

in

num_bins

i

][

2

:]:

num_bins

i

-

1

i

+

1

=

[(

num_bins

i

-

1

][

0

],

num_bins

i

][

1

],

num_bins

i

-

1

][

2

+

num_bins

i

][

2

],

num_bins

i

-

1

][

3

+

num_bins

i

][

3

])]

break

else

break

def

get_woe

num_bins

):

columns

=

“min”

“max”

“count_0”

“count_1”

df

=

pd

DataFrame

num_bins

columns

=

columns

df

“total”

=

df

count_0

+

df

count_1

df

“percentage”

=

df

total

/

df

total

sum

()

df

“bad_rate”

=

df

count_1

/

df

total

df

“good%”

=

df

count_0

/

df

count_0

sum

()

df

“bad%”

=

df

count_1

/

df

count_1

sum

()

df

“woe”

=

np

log

df

“good%”

/

df

“bad%”

])

return

df

def

get_iv

df

):

rate

=

df

“good%”

-

df

“bad%”

iv

=

np

sum

rate

*

df

woe

return

iv

IV

=

[]

axisx

=

[]

while

len

num_bins

>

n

pvs

=

[]

for

i

in

range

len

num_bins

-

1

):

x1

=

num_bins

i

][

2

:]

x2

=

num_bins

i

+

1

][

2

:]

pv

=

scipy

stats

chi2_contingency

([

x1

x2

])[

1

pvs

append

pv

i

=

pvs

index

max

pvs

))

num_bins

i

i

+

2

=

[(

num_bins

i

][

0

],

num_bins

i

+

1

][

1

],

num_bins

i

][

2

+

num_bins

i

+

1

][

2

],

num_bins

i

][

3

+

num_bins

i

+

1

][

3

])]

bins_df

=

pd

DataFrame

get_woe

num_bins

))

axisx

append

len

num_bins

))

IV

append

get_iv

bins_df

))

if

graph

plt

figure

()

plt

plot

axisx

IV

plt

xticks

axisx

plt

xlabel

“number of box”

plt

ylabel

“IV”

plt

show

()

return

bins_df

畫出各特徵在不同分箱個數下的學習曲線,選擇IV值斜率變化最大的分箱點作為最佳分箱個數。如下圖:該特徵變數隨著分箱個數越多,IV值越大。該特徵IV值在箱數為3~4處變化明顯,因此可以選擇3或4作為最佳分箱個數。

【風控建模】基於邏輯迴歸的評分卡開發(I)

特徵分箱學習曲線

2.WOE單調性調整

一般篩選的變數WOE與違約機率都是單調的,如果出現U型,或者其他曲線形狀,則需要重新看下變數是否有問題。由於目的是為了可解釋性,那麼一些業務上可解釋的變數,U型時也是可以的,比如說年齡變數。

#調整WOE單調性

#————————————————————————————————————-

def judge_increasing(L):

“”“

:param L: list

:return: 判斷一個List是否單調遞增

”“”

return all(x < y for x, y in zip(L,L[1:]))

def judge_decreasing(L):

“”“

:param L: list

:return: 判斷一個list是否單調遞減

”“”

return all(x > y for x, y in zip(L, L[1:]))

col = list(iv_final[iv_final。IV > 0。05]。col。unique())

bins_of_final_rewoe = bins_of_final。copy()

for cc in col:

cut = bins_of_final[cc]

woe_lst = iv_final[iv_final[‘col’]==cc]。woe

if woe_lst[0] > 0:

while not judge_decreasing(woe_lst):

judge_list = [x > y for x, y in zip(woe_lst, woe_lst[1:])]

index_list = [i+1 for i, j in enumerate(judge_list) if j == False]

new_cut = [j for i,j in enumerate(cut) if i not in index_list]

bins_of_final_rewoe[cc] = new_cut

bin_df_cc,iv_value_cc = binning_self(train_data,cc,‘target’,cut=new_cut)

woe_lst = bin_df_cc[‘woe’]。tolist()

cut = new_cut

elif woe_lst[0] < 0:

while not judge_increasing(woe_lst):

judge_list = [x < y for x, y in zip(woe_lst, woe_lst[1:])]

index_list = [i+1 for i, j in enumerate(judge_list) if j == False]

new_cut = [j for i,j in enumerate(cut) if i not in index_list]

bins_of_final_rewoe[cc] = new_cut

bin_df_cc,iv_value_cc = binning_self(train_data,cc,‘target’,cut=new_cut)

woe_lst = bin_df_cc[‘woe’]。tolist()

cut = new_cut

3.WOE轉換

將基礎資料對映為WOE值。

def get_woe(df, col, y, bins):

df = df[[col, y]]。copy()

df[“cut”] = pd。cut(df[col], bins)

bins_df = df。groupby(“cut”)[y]。value_counts()。unstack()

woe = bins_df[“woe”] = np。log((bins_df[0] / bins_df[0]。sum()) / (bins_df[1] / bins_df[1]。sum()))

return woe

# 將所有特徵的WOE儲存到字典當中

woeall = {}

for col in bins_of_final:

woeall[col] = get_woe(model_data, col, “target”, bins_of_final[col])

#把所有WOE對映到原始資料中

model_woe = pd。DataFrame(index=model_data。index)

for col in bins_of_final:

model_woe[col] = pd。cut(model_data[col],bins_of_final[col])。map(woeall[col])

4.訓練模型

使用sklearn中的Logistic Regression演算法進行例項化、訓練資料、輸出模型係數。

#例項化

lr = LR()

#用訓練資料擬合模型

lr = lr。fit(X,y)

lr。score(vali_X,vali_y)

‘’‘

lr = LR(penalty=’l1‘,solver=’liblinear‘,C=0。5,max_iter=100)

#用訓練資料擬合模型

lr = lr。fit(X,y)

lr。score(vali_X,vali_y)

’‘’

‘’‘

#嘗試使用C和max_iter的學習曲線把邏輯迴歸的效果調上去

c_1 = np。linspace(0。01,10,20)

score = []

for i in c_1:

lr = LR(solver=’liblinear‘,C=i)。fit(X,y)

score。append(lr。score(vali_X,vali_y))

plt。figure()

plt。plot(c_1,score)

plt。show()

’‘’

#看模型在ROC曲線上的效果

vali_proba_df = pd。DataFrame(lr。predict_proba(vali_X))

skplt。metrics。plot_roc(vali_y, vali_proba_df,

plot_micro=False,figsize=(6,6),

plot_macro=False)

5.評價模型效果

透過ROC曲線、KS曲線,評價模型效果。

AUC值為0。67,KS值為0。27,整體模型效果一般。

skplt。metrics。plot_roc(vali_y, vali_proba_df,

plot_micro=False,figsize=(6,6),

plot_macro=False)

def plot_model_ks(y_label, y_pred):

“”“

繪製ks曲線

param:

y_label —— 真實的y值 list/array

y_pred —— 預測的y值 list/array

return:

ks曲線

”“”

pred_list = list(y_pred)

label_list = list(y_label)

total_bad = sum(label_list)

total_good = len(label_list) - total_bad

items = sorted(zip(pred_list, label_list), key=lambda x: x[0])

step = (max(pred_list) - min(pred_list)) / 200

pred_bin = []

good_rate = []

bad_rate = []

ks_list = []

for i in range(1, 201):

idx = min(pred_list) + i * step

pred_bin。append(idx)

label_bin = [x[1] for x in items if x[0] < idx]

bad_num = sum(label_bin)

good_num = len(label_bin) - bad_num

goodrate = good_num / total_good

badrate = bad_num / total_bad

ks = abs(goodrate - badrate)

good_rate。append(goodrate)

bad_rate。append(badrate)

ks_list。append(ks)

fig = plt。figure(figsize=(6, 4))

ax = fig。add_subplot(1, 1, 1)

ax。plot(pred_bin, good_rate, color=‘green’, label=‘good_rate’)

ax。plot(pred_bin, bad_rate, color=‘red’, label=‘bad_rate’)

ax。plot(pred_bin, ks_list, color=‘blue’, label=‘good-bad’)

ax。set_title(‘KS:{:。3f}’。format(max(ks_list)))

ax。legend(loc=‘best’)

return plt。show()

y_pred = lr。predict_proba(vali_X)[:,1]

plot_model_ks(vali_y, y_pred=y_pred)

【風控建模】基於邏輯迴歸的評分卡開發(I)

【風控建模】基於邏輯迴歸的評分卡開發(I)

6.製作評分卡

B

=

20

/

np

log

2

A

=

600

+

B

*

np

log

1

/

60

base_score

=

A

-

B

*

lr

intercept_

# lr。intercept_:截距

file

=

r

“D:\Scorecard\ScoreData。csv”

with

open

file

“w”

as

fdata

fdata

write

“base_score,

{}

\n

format

base_score

))

for

i

col

in

enumerate

X

columns

):

# [*enumerate(X。columns)]

score

=

woeall

col

*

-

B

*

lr

coef_

0

][

i

])

score

name

=

“Score”

score

index

name

=

col

score

to_csv

file

header

=

True

mode

=

“a”

【風控建模】基於邏輯迴歸的評分卡開發(I)

訓練集好壞樣本得分分佈

【風控建模】基於邏輯迴歸的評分卡開發(I)

測試集好壞樣本得分分佈

四.總結

1。相比於xgboost等機器學習演算法,邏輯迴歸演算法效能一般,但勝在可解釋性強,在評分卡領域應用廣泛。在不調整引數情況下,xgboost模型效果AUC達到0。65,與精心調整過的邏輯迴歸的效果AUC值0。67相差不多。

2。根據模型結果,分析該模型應用效果還有較大提升空間,未來需改善的地方有:1)嚴格定義目標變數,並使樣本表現期一致。 2)使用更多的特徵變數,此次IV大於0。05的候選入模變數近20出頭,是導致模型效果不好的重要原因。 3)特徵分箱需更細緻,此次強制要求所有變數WOE單調,未來應結合實際業務考慮特徵分箱。 4)模型最終迴歸係數有正有負,說明存在多重共線性問題,未來應考慮解決模型的共線性問題。5)改善選取樣本,一方面選取更多的有效樣本,另一方面提高樣本中bad rate比例,此次選取的樣本bad rate不足3%。

標簽: bins  df  num  list  分箱