天天看點

整個模組化流程

今天梳理一下最近總結的邏輯回歸評分卡模組化流程,大差不差,慢慢補充

文章目錄

      • 1. 導入包
      • 2. 資料及預處理
      • 3. 資料描述
      • 4. 特征工程
      • 5. 模組化
      • 5. 制作評分卡以及分數評估
      • 6. 分析穩定性
      • 7. 儲存結果

1. 導入包

:除了基礎的包,其他的就是同僚大佬總結的以及我參照後改成自己的風格的包

import pandas as pd
import numpy as np
import statsmodels.api as sm # 添加常數項
import matplotlib.pyplot as plt # 畫分布圖
import seaborn as sns
import importlib #重新導入包
import warnings
warnings.filterwarnings('ignore')

from pandas.io.excel import ExcelWriter #寫入excel
# 開發包
from riskmodels import detector, evalueate, models, scorecard,utils
           

2. 資料及預處理

:首先需要導入資料,這裡如果資料量比較大可以存為csv格式,但是csv格式有時候會改變變量的類型,是以我現在就是将從hive裡面下載下傳下來的資料存儲為pickle格式。

這裡的資料滿足的要求可能需要包括:時間(month),産品(product_no),主鍵(id), 标簽target

接着,可以考慮是否去掉灰樣本,有時候可能需要分析,如果不需要的話,在讀入資料之前就可以處理掉

其次,就是資料的空值替換,比如-999, None等

再次,就是某些特别的資料的類型轉換

或者,可能涉及修改變量名

total_data=pd.read_pickle('data.pkl')
total_data=detector.data_pro(total_data)
total_data.rename(columns={'a.create_date':'create_date'})
           

3. 資料描述

這裡主要是一些描述性的東西,比如資料按月分布,按産品分布情況,資料集的劃分情況等

# 按月描述
t_m=detector.sample_stats(total_data,'month',target='y')

# 劃分資料
total_data['month']=pd.to_datetime(total_data['month']

# 按照不同的月份來劃分train和oot得到的一個結果
split_stat_dat=detector.split_stat(total_data,'month',target='y')
# 檢視哪個月份劃分是最合理的,然後進行劃分
train_df, test_df,oot_df=detector.train_test_oot(total_data,'month',oot_date='2022-02-01')

# 想要一個完整的資料,友善後面對總資料進行分析:分布、分數排序性等
train_df['tto']=1
test_df['tto']=2
oot_df['tto']=3
t_data=pd.concat([train_df,test_df,oot_df],axis=0)
t_data.sort_index(inplace=True)

# 檢視資料集的分布
set_stat=detector.sample_stat(t_data,'tto',target='y']
           

4. 特征工程

這裡主要是特征的篩選,包括單一值、缺失值、分箱、iv值、PSI、風險一緻性、相關性等

# X數值型變量清單,注意是數值型
fea_0=total_data.drop([],axis=1).columns.to_list()
# 加一個資料的描述性統計
det_data=detector.detect(total_data[fea_0])
# 缺失率和單一值率篩選
na_repeat,na_stat,repeat_stat=evaluate.distribution_statistics(total_data,fea_0)
fea_1=evalueate.na_select(na_repeat,fea_0)
fea_2=evaluate.repeat_select(na_repeat,fea_1)

#woe分箱
bins=scorecard.woebin(train_df,x=fea_2,y='y',method=['hist','chi2']) #這個是修改了内部參數的
brks,spe=scorecard.woebin_breaks(bins) #擷取分箱結果
woe_df,iv_df=scorecard.sc_bins_to_df(bins)

#iv和單調性篩選
fea_3=iv_df[iv_df['IV']>0.02 & iv_df['單調性'].isin(['increasing','decreasing'])].index.to_list()

# psi篩選
var_psi=scorecard.woebin_psi(train_df,oot_df,bins={k:v for k,v in bins.items() if k in fea_3})
var_psi_t=var_psi[['variable','psi']].groupby('variable').mean().reset_index()
fea_4=[var_psi_t[x,0] for x in range(var_psi_t.shape[0]) if var_psi_t.iloc[x,1]<0.1]

#風險一緻性篩選
var_risk_consist=var_select.risk_trends_consistency(oot_df,sc_bins={v:bins[v] for v in fea_4},target='y')

fea_5=[k for k,v in var_risk_consist.items() if v==1]

# 相關性篩選
fea_6=var_select.correlation_select(train_df, fea_5)
           

5. 模組化

模組化部分主要用到的是逐漸邏輯回歸

train_X=scorecard.woebin_ply(train_df[fea_6],bins,value='woe')
train_y=train_df['y']
test_X=scorecard.woebin_ply(test_df[fea_6],bins,value='woe')
test_y=test_df['y']
oot_X=scorecard.woebin_ply(oot_df[fea_6],bins,value='woe')
oot_y=oot_df['y']

# 逐漸邏輯回歸
_, fea_7=models.stepwise_lr(train_X,train_y.values,kfold=5,features=[f+'woe' for f in fea_6],selection_criterion=1,watch_sample(test_X,test_y.values))
# selection_criterion是模型評價準則,一般選擇的是auc

# 邏輯回歸及調整,包括去掉p值大于門檻值的,并輸出模型表達結果+vif+變量的相關系數
lr_mdoel_result,selected_variables,model_perf,cor_f=models.lr_select(train_X,train_y,f_7,p_limit=0.5)

# 檢視模型效果 測試集和OOT
model_ef,train_pred,test_pred,oot_pred=models.model_effect(lr_model_result,seelcted_variables,train_X,test_X,oot_X,train_y,test_y,oot_y)

# model_ef是在訓練測試和OOT上的效果表現,通常三個資料集的ks應該盡可能接近,最好不超過3個點,并且KS最好在0.2以上,如果效果不好的話需要繼續傳回調整


           

模型效果不好調整的地方,目前想到的是單調性那裡少一些限制,然後修改分箱,使其保持單調,滿足業務單調性

5. 制作評分卡以及分數評估

模型建立好了之後,需要轉換成評分卡并觀察各種情況下的一些名額,比如說分數分布,分數排序性,按月表現如何等

# 制作評分卡
score_card=scorecard.make_scorecard(bins,lr_model_result.params.to_dict())

# 初步看一下排序性
train_split,test_split,oot_split=utils.score_badrate(lr_model_result,selected_feaures,train_pred,test_pred,oot_pred,train_y,test_y,oot_y)
           

這裡如果排序性不好也需要倒回去調整,直到OOT上的壞賬率有排序性

6. 分析穩定性

如果模型确認好了,在OOT上排序性也比較好了,接下來就要看一下模型的穩定性,主要是将整個資料集拿來分析,包括其分布是否滿足正态性,好壞樣本分布是否有區分度,按月的模型的效果是否穩定

tt_data=scorecard.woebin_ply(t_data[var[:-4] for var in selected_variables]
tt_data=sm.add_constant()
tt_data['pred']=lr_model_result.predict(tt_data)
tt_data['score']=utils.pfk(lr_model_result,tt_data['pred'])
tt_data['y']=t_data['y']
tt_data['month']=t_data['month']
# 如果有産品号的話最好加上,便于後面對産品進行分析

# 總體分數的排序性
t_split,sp_breaks=utils.split_performance_table(tt_data['y'],tt_data['score'])

# 總體資料的分布
df_fig,ax1=plt.subplots(figsize=(12,9))
sns.displot(tt_data[tt_data['y']==1]['score'],ax=ax1,hist=True,kde=True,norm_hist=True,bins=10,color='green',label='bad')
sns.displot(tt_data[tt_data['y']==0]['score'],ax=ax1,hist=True,kde=True,norm_hist=True,bins=10,color='red',label='good')
ax1.legend()
plt.savefig('總體資料分布')
# 按月的模型效果,主要是Ks
month_ks=evaluate.anyue_ks(tt_data,'y')

# 有多個産品的話也可以看看在産品上的模型效果表現情況
           

一般如果有多個産品的話,那麼做的就是一個通用模型,通常由于多個項目的客群會不一樣,是以會導緻通用模型的效果會很不好,此時就需要去将客群一樣的項目建立通用模型,單個項目建立專屬模型了

到這裡的話如果滿足正态性、穩定性的話,這個模型開發工作基本上就完成了一大半,接下來就是驗證這個模型在其他标簽上的效果就OK啦

7. 儲存結果

writer=ExcelWriter('模型開發結果彙總')
t_m.to_excel(writer,sheet_name='樣本',startrow=1)
na_stat.to_excel(writer,sheet_name='變量統計',startrow=1)
...
writer.close()