风控评分卡建模全流程
前言
本文将通过 python 代码演示传统评分卡建模的全流程,比较通用的一个版本。评分卡已经发展得非常成熟了,对于不同业务或者不同建模人员下的模型构建过程可以称得上是大同小异。
微信阅读可选择点击前往:风控评分卡建模全流程
个人水平有限,py coding 这块着实造诣不深,目前多是"照葫芦画瓢",站在前辈们的肩膀上前行。由于代码篇幅较长,先提前在这里感谢锋大、翟锟老师等在建模方面给予的极大帮助定。
正文
评分卡实现主要使用自定义函数以及谢博士的 scorecardpy 包进行处理,建模过程如下:
- 样本准备
Kaggle&自定义样本 - 建模变量探索和预处理
缺失值、异常值识别和替代
IV值、VIF共线性、相关系数、逐步回归筛选
变量分箱处理 - 模型构建
逻辑回归 - 模型评估
KS、AUC、PSI
模型得分分布、区分度曲线 - 评分卡
1.样本准备
选取 Kaggle 官网提供的经典二分类样本,原数据集都是数值型变量,为了更完整地展示建模流程,在此基础上增加两列分类变量。
通过以下链接,可获取到样本数据(training2.0)以及建模过程需要的两个自定义py包(PlotModel和FeatureSelection)。
链接:https://pan.baidu.com/s/171aFTxWn9jxSn1fYPe21Mg
提取码:wvj2
2.建模代码
2.1 读取数据
########################################
#1.读取数据
########################################
##########读取数据
import warnings
warnings.filterwarnings("ignore")
import pandas as pd
import os
os.chdir('D:\zzl\lr0531/')
data=pd.read_csv('give me some credit/training2.0.csv',encoding = 'gb2312',index_col=0)
data.tail()
##########变量重命名
#target:0/1分类目标变量
#注意名称避免出现-,不然后面stepwise过程会报错
column={'ID':'用户ID',
'SeriousDlqin2yrs':'target',
'RevolvingUtilizationOfUnsecuredLines':'可用额度比值',
'age':'年龄',
'NumberOfTime30-59DaysPastDueNotWorse':'逾期30_59天笔数',
'DebtRatio':'负债率',
'MonthlyIncome':'月收入',
'NumberOfOpenCreditLinesAndLoans':'信贷数量',
'NumberOfTimes90DaysLate':'逾期90天笔数',
'NumberRealEstateLoansOrLines':'固定资产贷款量',
'NumberOfTime60-89DaysPastDueNotWorse':'逾期60_89天笔数',
'NumberOfDependents':'家属数量',
'gender':'性别',
'ostype':'客户端类型'}
data.rename(columns=column,inplace=True)
##########变量list
allFeatures = list(data.copy().columns)
allFeatures
样本示例:data
2.2 数据探索和预处理
########################################
#2.数据探索和预处理1
#######################################
##########坏样本浓度
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid',{'font.sans-serif':['simhei','Arial']})
def Pic_Target(col, data=None):
for i in col:
plt.figure(figsize = (10,5))
plt.subplot(1,2,1) #1行2列,第1个图
data[i].dropna().value_counts().plot(kind='pie', autopct='%1.2f%%')
plt.title(str(i)+' 各水平数量比例')
plt.subplot(1,2,2) #1行2列,第2个图
sns.countplot(x=i, data=data) #数值变量显示的是均值/比例,竖线表示波动范围
plt.title(str(i)+' 各水平数量')
plt.xticks(rotation='vertical')
plt.show()
col=['target']
Pic_Target(col, data)
输出示例:坏样本比例6.68%
##########删除常数变量/重复变量
print(data.shape) #原始
#data = data.drop_duplicates() #去重,样本减少
data = data.loc[:,data.apply(pd.Series.nunique)!=1] #删除常数变量,变量减少
len(set(list(data.columns)))==data.shape[1] #判断变量是否重复,如果不重复,就为True
print(data.shape) #预处理后
##########删除缺失比例过高的变量
import missingno
missingno.matrix(data,labels=True)
check_null = data.isnull().sum(axis=0).sort_values(ascending=False)/float(data.shape[0])
check_null[check_null > 0.2] #展示缺失比例>=0.2的特征
data = data.dropna(thresh=data.shape[0]*0.2, axis=1) #删除缺失比例(1-0.2)以上的变量
##########变量缺失值或者异常值替代
string_var = list(data.select_dtypes(include=['object']).columns)
data[string_var].head()
data['客户端类型'].value_counts()
data['客户端类型'].value_counts(normalize=True)
'''字符类型变量 异常值和缺失值均赋值为-99'''
string_var = list(data.select_dtypes(include=['object']).columns)
data[string_var].head()
for i in string_var:
data[i]=data[i].apply(lambda x: '-99' if x=='0' else x)
data[i]=data[i].fillna('-99')
'''非字符类型变量 异常值和缺失值均赋值为-99'''
allFeatures = list(data.columns)
allFeatures.remove('target')
string_var = list(data.select_dtypes(include=['object']).columns)
num_var = [i for i in allFeatures if i not in string_var]
for i in num_var:
data[i]=data[i].apply(lambda x: -99 if x==-99998 else x)
data[i]=data[i].fillna(-99)
输出示例