变量分箱是评分卡建模流程中的关键环节,可以说是评分卡的核心环节。合理的分箱可以消除变量的量纲影响,而且能减少异常值等噪声数据的影响,有效避免模型过拟合。此外,分箱可以给模型实现业务上的可解释性,可以说是评分卡的核心了。
下面开始实现评分卡建立中的分箱操作。
首先,变量需要分为数值型变量和类别型变量。对于这两种类型的变量分箱过程中需要注意的点如下:
- 类别型变量
- 如果不超过5个,无需进行分箱;
- 超过5个,有两种方法。一,如果类别很多,可以对其进行bad_rate编码之后划入数值型变量;二,类别不是很多,对其进行降基处理,缩小至5个以内。
- 数值型变量
有无监督和有监督分箱两种方法。无监督分箱有等比分箱、等宽分箱、聚类分箱等。有监督分箱有卡方分箱、最优分箱等等。
num_features = ['int_rate_clean', 'emp_length_clean', 'annual_inc', 'dti', 'delinq_2yrs', 'earliest_cr_to_app',
'inq_last_6mths', \
'mths_since_last_record_clean', 'mths_since_last_delinq_clean', 'open_acc', 'pub_rec', 'total_acc',
'limit_income', 'earliest_cr_to_app']
cat_features = ['home_ownership', 'verification_status', 'desc_clean', 'purpose', 'zip_code', 'addr_state']
一共有14个数值型变量和6个类别型变量。‘zip_code’、'addr_state’两个变量的类别很多,进行bad_rate编码后划入数值型变量。另外4个变量单独进行分箱。
def binning_cate(df,col_list,target):
"""
df:数据集
col_list:变量list集合
target:目标变量的字段名
return:
bin_df :list形式,里面存储每个变量的分箱结果
iv_value:list形式,里面存储每个变量的IV值
"""
total = df[target].count()
bad = df[target].sum()
good = total-bad
all_odds = good*1.0/bad
bin_df =[]
iv_value=[]
for col in col_list:
d1 = df.groupby([col],as_index=True)
d2 = pd.DataFrame()
d2['min_bin'] = d1[col].min()
d2['max_bin'] = d1[col].max()
d2['total'] = d1[target].count()
d2['totalrate'] = d2['total']/total
d2['bad'] = d1[target].sum()
d2['badrate'] = d2['bad']/d2['total']
d2['good'] = d2['total'] - d2['bad']
d2['goodrate'] = d2['good']/d2['total']
d2['badattr'] = d2['bad']/bad
d2['goodattr'] = (d2['total']-d2['bad'])/good
d2['odds'] = d2['good']/d2['bad']
GB_list=[]
for i in d2.odds:
if i>=all_odds:
GB_index = str(round((i/all_odds)*100,0))+str('G')
else:
GB_index = str(round((all_odds/i)*100,0))+str('B')
GB_list.append(GB_index)
d2['GB_index'] = GB_list
d2['woe'] = np.log(d2['badattr']/d2['goodattr'])
d2['bin_iv'] = (d2['badattr']-d2['goodattr'])*d2['woe']
d2['IV'] = d2['bin_iv'].sum()
iv = d2['bin_iv'].sum().round(3)
print('变量名:{}'.format(col))
print('IV:{}'.format(iv))
print('\t')
bin_df.append(d2)
iv_value.append(iv)
return bin_df,iv_value
注意,如果类别型变量的某一箱只有好样本/坏样本,将造成变量的IV值为inf/-inf,此时就需要对变量进行降基处理或者重新分箱。
接着看一下每一箱的明细情况。
IV值一般大于0.01,就可以入模使用。IV值不宜过高,如果过高说明变量的预测能力过强,其实可以单独拿出来作为一条策略。评分卡的变量最好还是弱变量。此外,每一箱的WOE值也不宜大于1,因为大于1说明这一箱至少有65%以上的好坏样本,其实可以单独作为一条规则了。
下面利用条形图将分箱结果可视化展示。
# woe的可视化
def plot_woe(bin_df,hspace=0.4,wspace=0.4,plt_size=None,plt_num=None,x=None,y=None):
"""
bin_df:list形式,里面存储每个变量的分箱结果
hspace :子图之间的间隔(y轴方向)
wspace :子图之间的间隔(x轴方向)
plt_size :图纸的尺寸
plt_num :子图的数量
x :子图矩阵中一行子图的数量
y :子图矩阵中一列子图的数量
return :每个变量的woe变化趋势图
"""
plt.figure(figsize=plt_size)
plt.subplots_adjust(hspace=hspace,wspace=wspace)
for i,df in zip(range(1,plt_num+1,1),bin_df):
col_name = df.index.name
df = df.reset_index()
plt.subplot(x,y,i)
plt.title(col_name)
sns.barplot(data=df,x=col_name,y=