目录
一、数据读取及预处理
1、数据读取
2、数据预处理
二、模型构建及评估
三、划重点
少走10年弯路
数据来源某比赛网站(下图仅为部分字段),数据集中包含银行借贷订单的金额、利息、账期、担保等基本信息,还有历史授信情况,数据类型同样包含数值型、类别型、日期等变量,同时存在缺失问题,适合初学者入门练习。文末获取数据
(1)无效特征剔除:数据集中存在部分无效数据,唯一值数量仅为1、不包含有效信息,可以直接剔除;
(2)日期、编码剔除:如下图,部分日期为脏数据,为方便处理直接剔除日期字段
(4)类别型变量处理:使用xgb时特征输入需要为数值型,所以复制一份xgb建模数据集对类别型变量使用目标编码、即使用训练集(避免穿越)每类类别型变量对应的y均值进行编码;而对于lgb可以直接转为category类型输入。
(5)FM交叉特征:针对lgb,数据集中存在部分类别型变量可以衍生二阶交叉特征、后续测试效果
def init_data():
df_fea=pd.read_excel('原始数据/trainX.xlsx')
df_y=pd.read_excel('原始数据/trainY.xlsx')
df=pd.concat([df_fea.drop(['id'],axis=1),df_y.drop(['id'],axis=1)],axis=1)
return df
df=init_data()
def drop_useless_col(data):
df_sta=data.nunique(dropna=False).to_frame()
df_sta.columns=['unique_cnt']
drop_col=list(df_sta[df_sta.unique_cnt<2].index)
return data[[col for col in data.columns if col not in drop_col]]
def data_pred(data):
df=data.copy()
df=df.pipe(drop_useless_col)
drop_col=['jieju_next_anew_pricing_dt']
drop_tmp=['kehu_tm_dpst_early_open_acct_dt','kehu_open_cust_tm','kehu_open_cust_dt']
return df[[col for col in df.columns if col not in drop_col+drop_tmp]]
df_pre=df.pipe(data_pred)
from itertools import combinations
def combine(df_pre,cate_col):
df=df_pre.copy()
comb=list(combinations(cate_col,2))
cate_col_add=[]
for col1,col2 in comb:
df[col1+'_'+col2]=df[col1].astype('string').str.cat(df[col2],sep='&')
cate_col_add.append(col1+'_'+col2)
df[cate_col+cate_col_add]=df[cate_col+cate_col_add].astype('category')
return df,cate_col_add
df_pre_comb,cate_col_add=df_pre.pipe(combine,cate_col)
def get_xgb_data(df_pre,y='jieju_dubil_status_desc',fea_list=cate_col+float_col):
df=df_pre.copy()
cate_col=df.select_dtypes(include=['category','string','object'])
map_dict={}
for col in cate_col:
col_map=df.groupby([col])[y].mean().to_dict()
df[col]=df[col].map(col_map)
map_dict[col]=col_map
df[fea_list]=df[fea_list].astype('float')
return df,map_dict
df_xgb,map_dict=get_xgb_data(df_pre,fea_list=cate_col+float_col)
分别使用lgb、xgb构建二分类模型,其中lgb分别训练是否添加FM交叉特征版本用于对比,使用ks、auc进行评估
def init_params(model_select='lgb'):
params_xgb={
'objective':'binary:logistic',
'eval_metric':'auc',
# 'silent':0,
'nthread':4,
'n_estimators':500,
'eta':0.02,
# 'num_leaves':10,
'max_depth':4,
'min_child_weight':20,
'scale_pos_weight':1,
'gamma':0,
'reg_alpha':0,
'reg_lambda':0,
'subsample':0.8,
'colsample_bytree':0.8,
'seed':123
}
params_lgb={
'boosting_type': 'gbdt',
'objective': 'binary',
'metric':'auc',
'n_jobs': 4,
'n_estimators':500,
'learning_rate': 0.03,
'max_depth':4,
'num_leaves': 12,
'max_bin':255,
'subsample_for_bin':100000, # 构建直方图的样本量
'min_split_gain':0,
'min_child_samples':30,
'colsample_bytree': 0.8,
'subsample': 0.8,
'subsample_freq': 1, # 每 k 次迭代执行bagging
'feature_fraction_seed':2,
'bagging_seed': 1,
'reg_alpha':0,
'reg_lambda':0,
'scale_pos_weight':1, # 等价于is_unbalance=False
'silent':True,
'random_state':1,
'verbose':-1, # 控制模型训练过程的输出信息,-1为不输出信息
}
if model_select=='xgb':
return params_xgb
elif model_select=='lgb':
return params_lgb
def ks_auc_value(y_value,df,model):
y_pred=model.predict_proba(df)[:,1]
fpr,tpr,thresholds= roc_curve(list(y_value),list(y_pred))
ks=max(tpr-fpr)
auc= roc_auc_score(list(y_value),list(y_pred))
return ks,auc
def model_train_sklearn(model_label,train,y_name,model_var,model_select='lgb',params=None):
if params is None:
params=init_params(model_select)
x_train,x_test, y_train, y_test =train_test_split(train[model_var],train[y_name],test_size=0.2, random_state=123)
if model_select=='xgb':
model=XGBClassifier(**params)
elif model_select=='lgb':
model=lgb.LGBMClassifier(**params)
model.fit(x_train,y_train,eval_set=[(x_train, y_train),(x_test, y_test)],verbose=False) # 调参时设verbose=False
train_ks,train_auc=ks_auc_value(y_train,x_train,model)
test_ks,test_auc=ks_auc_value(y_test,x_test,model)
# model_sklearn=model.fit(train[model_var],train[y_name]) # 全集数据训练
all_ks,all_auc=ks_auc_value(train[y_name],train[model_var],model)
dic={
'model_label':model_label,
'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(),
'all_good':train[train[y_name]==0].shape[0],'all_bad':train[train[y_name]==1].shape[0],
'train_ks':train_ks,'train_auc':train_auc,
'test_ks':test_ks,'test_auc':test_auc,
'all_ks':all_ks,'all_auc':all_auc,
}
return dic,model
关注威信公众号 Python风控模型与数据分析,回复 银行风控实战 获取本篇数据及代码
还有更多理论、代码分享等你来拿