目录
之前写过一篇银行信贷风控实战了,但是包括之前其它信贷风控的实战内容在内,实际上和工作中完整项目之间还存在很多差距,这篇银行信贷风控实战2所使用数据更接近工作中的真实数据,需要自行从原始借贷还款记录中提取逾期标签用于分析建模、而不是简简单单地直接给你处理好的Y标签(实际工作时需要自行处理的)。所以重点推荐本文原始数据、以及逾期标签的打标方法。
一、数据介绍及逾期标签处理
1、数据介绍
(1)订单信息及特征表
第一部分数据集中包含银行借贷订单的金额、利息、账期等信息,还有年龄、性别等个人基本信息,历史借款、还款信息,以及户口、学历、视频等认证审核结果,但是不包括逾期信息。文末获取数据集

(2)还款记录表
还款记录表包括订单ID、不同期数、还款金额、到期日、还款时间等信息,这也基本是实际工作中真实数据的样子了。可以看到每笔订单分12期,每一期都有对应的还款行为/是否逾期,所以需要我们自行定义标签、以及确定相应的标签逻辑,如dpd30_mob3为前三期最大逾期天数是否超过30天。

2、标签定义及生成
还款记录表中提供了还款状态字段(分布见下图),其中1代表准时还款、2代表逾期、0中既有未到期又有逾期、3代表提前还款、4也代表逾期,还款状态字段含义混乱、且无法确定逾期程度(订单到底逾期了多少天),所以我们需要自己根据到期日期、还款日期、观测日期来计算每一期的逾期天数,然后再计算每笔订单的逾期标签(如dpd30_mob3)。

(1)计算每期逾期天数
首先剔除观测时间尚未到期的数据,然后计算每一期的逾期天数:有还款日期(实际发生了还款行为才会有还款日期数据,没有还款日期的代表一直未还款)的期数用还款日减去到期日,一直未还款的用观测日减去到期日;同时还要把逾期天数小于0(提前还款)的逾期天数置为0。

计算得到结果如下

def df_lp_pred(df_lp):
df=df_lp[df_lp['recorddate']>df_lp['到期日期']].reset_index(drop=True)
df.loc[df['还款日期']!='\\N','due_date']=df['还款日期']
df.loc[df['还款日期']=='\\N','due_date']=df['recorddate']
df['duedays']=(pd.to_datetime(df['due_date'])-pd.to_datetime(df['到期日期'])).dt.days
df['duedays']=np.where(df['duedays']>=0,df['duedays'],0)
return df
df_lp_copy=df_lp_pred(df_lp)
df_lp_copy.head(20)
(2)计算订单下各观测周期的最大逾期天数
对订单的各期数据做聚合、计算不同观测周期下的最大逾期天数,分别得到mob1-mob12的最大逾期天数。

mob1-mob12的最大逾期天数分布情况如下,可见大部分是未逾期的,为了控制逾期标签比例,本文使用dpd1_mob(n)作为标签

def get_mob_k_maxduedays(df_lp_copy,k):
return (
df_lp_copy
[df_lp_copy.ListingId.isin(list(df_lp_copy[df_lp_copy['期数']==k].ListingId))]
[df_lp_copy['期数']<=k]
.groupby(['ListingId'])
.duedays
.max()
)
mob_k_list=[1,2,3,4,5,6,7,8,9,10,11,12]
df_maxduedays=pd.concat([get_mob_k_maxduedays(df_lp_copy,k) for k in mob_k_list],axis=1)
df_maxduedays.columns=['mob{}_duedays'.format(k) for k in mob_k_list]
df_maxduedays
(3)计算dpd1_mob(n)标签
根据mob1-mob12的最大逾期天数计算dpd1_mob(n)标签,如mob1逾期天数大于0则dpd1_mob1的值为1,计算完成后统计各标签的样本量和逾期率情况如下,本文使用dpd1_mob3建模、其他标签也可尝试。注意这里的样本量递减是在观测日时,订单还没到相应的期数

def get_label(value):
if value==0:
return 0
if value>0:
return 1
return np.nan
for i in mob_k_list:
df_maxduedays['dpd1_mob{}'.format(i)]=df_maxduedays['mob{}_duedays'.format(i)].apply(get_label)
df_maxduedays
二、模型构建及评估
使用lightGBM构建二分类模型,按照8:2的比例划分训练集、测试集,然后使用ks、auc进行效果评估,结果如下、auc达到0.66

def init_params():
params_lgb={
'boosting_type': 'gbdt',
'objective': 'binary',
'metric':'auc',
'n_jobs': 8,
'n_estimators':150,
'learning_rate': 0.03,
'max_depth':4,
'num_leaves': 12,
'max_bin':255,
'subsample_for_bin':100000,
'min_split_gain':0,
'min_child_samples':300,
'colsample_bytree': 0.8,
'subsample': 0.8,
'subsample_freq': 1,
'feature_fraction_seed':2,
'bagging_seed': 1,
'reg_alpha':1,
'reg_lambda':1,
'scale_pos_weight':1,
'silent':True,
'random_state':1,
'verbose':-1, # 控制模型训练过程的输出信息,-1为不输出信息
}
return params_lgb
def ks_auc_value(y_true,df,model):
y_pred=model.predict_proba(df)[:,1]
fpr,tpr,thresholds= roc_curve(list(y_true),list(y_pred))
ks=max(tpr-fpr)
auc= roc_auc_score(list(y_true),list(y_pred))
return ks,auc
def model_train_sklearn(train,y_name,fea_list):
params=init_params()
x_train,x_test, y_train, y_test =train_test_split(train[fea_list],train[y_name],test_size=0.2, random_state=123)
model=lgb.LGBMClassifier(**params)
model.fit(x_train,y_train,eval_set=[(x_train, y_train),(x_test, y_test)])
train_ks,train_auc=ks_auc_value(y_train,x_train,model)
test_ks,test_auc=ks_auc_value(y_test,x_test,model)
dic={
'train_good':(y_train.count()-y_train.sum()),
'train_bad':y_train.sum(),
'test_good':(y_test.count()-y_test.sum()),
'test_bad':y_test.sum(),
'train_ks':train_ks,
'train_auc':train_auc,
'test_ks':test_ks,
'test_auc':test_auc,
}
return dic,model
y='dpd1_mob3'
df_lc_copy[cate_fea]=df_lc_copy[cate_fea].astype('category')
model_result,model=model_train_sklearn(df_lc_copy[df_lc_copy[y].isin([0,1])],y,fea_list)
model_result
三、划重点
少走10年弯路
关注威信公众号 Python风控模型与数据分析,回复 银行风控实战2 获取本篇数据及代码
还有更多理论、代码分享等你来拿

1122


被折叠的 条评论
为什么被折叠?



