# 模型预测概率的修正

1

01

1、数据集data：已经过处理，只保留目标变量和7个特征，下面主要看如何修正预测概率，对于建模的过程和建模效果不做过多处理。(data数据集可公众号消息留言，提供下载链接)。

```import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
data.info()```
`data.y.value_counts()`

2、数据集model：从data数据集中剔除掉y=0.5的灰色样本，生成model数据集，其发生比为2008/14170：

```model = data[data.y!=0.5]
model.y.value_counts()```

3、数据集train：对model中y=0样本采取欠抽样提高0样本比例，生成train数据集，其发生比为2008/7085：

```good_indx = model.index[model.y==0]
np.random.seed(1111)
smp_good_indx = np.random.choice(good_indx, int(round(0.5*len(good_indx))), replace=False)
train = model.loc[smp_indx, :]
train.y.value_counts()```

1

02

```### 分箱
bin_dict = ContVarChi2BinBatch(train, 'cus_num', 'y', BinMax=5, BinPcntMin=0.05, SplitNum=100, spe_attri=[-1], singleIndicator = False)
train_bin = txtContVarBin(train, 'cus_num', 'y', bin_dict, testIndicator=0)
### 计算woe
train_woe, woe_dict = CalcWoe(train_bin, 'cus_num', 'y')
###
x_train = train_woe.drop(['cus_num', 'y'], axis=1)
y_train = train_woe['y']
### statstrains.api 逻辑回归
logit_result = logit.fit()
logit_result.summary()```

1

03

1、根据train数据集上训练的模型结果，生成标准评分卡：

```### 评分卡
def scorecard(df):
df_p = df.copy()

df_p['x1_woe'] = np.nan
df_p['x1_woe'][df_p['x1']<=5.03] = -1.610462
df_p['x1_woe'][(df_p['x1']>5.03) & (df_p['x1']<=10.3)] = -0.883790
df_p['x1_woe'][(df_p['x1']>10.3) & (df_p['x1']<=16.19)] = -0.259779
df_p['x1_woe'][(df_p['x1']>16.19) & (df_p['x1']<=21.15)] = 0.218075
df_p['x1_woe'][df_p['x1']>21.15] = 0.806426

df_p['x2_woe'] = np.nan
df_p['x2_woe'][df_p['x2']<=0.01] = -0.097708
df_p['x2_woe'][df_p['x2']>0.01] = 1.142635

df_p['x3_woe'] = np.nan
df_p['x3_woe'][df_p['x3']<=-1] = -0.198114
df_p['x3_woe'][(df_p['x3']>-1) & (df_p['x3']<=20.38)] = 0.506548
df_p['x3_woe'][(df_p['x3']>20.38) & (df_p['x3']<=83.08)] = 0.064844
df_p['x3_woe'][df_p['x3']>83.08] = -0.293702

df_p['x4_woe'] = np.nan
df_p['x4_woe'][df_p['x4']<=0.4954] = -0.349128
df_p['x4_woe'][(df_p['x4']>0.4954) & (df_p['x4']<=0.5505)] = 0.155449
df_p['x4_woe'][(df_p['x4']>0.5505) & (df_p['x4']<=1.9816)] = -0.193918
df_p['x4_woe'][df_p['x4']>1.9816] = 0.330673

df_p['x5_woe'] = np.nan
df_p['x5_woe'][df_p['x5']<=22.18] = -0.428135
df_p['x5_woe'][(df_p['x5']>22.18) & (df_p['x5']<=26.17)] = -0.023622
df_p['x5_woe'][(df_p['x5']>26.17) & (df_p['x5']<=28.07)] = 0.310403
df_p['x5_woe'][(df_p['x5']>28.07) & (df_p['x5']<=35.1)] = 0.108008
df_p['x5_woe'][df_p['x5']>35.1] = -0.177175

df_p['x6_woe'] = np.nan
df_p['x6_woe'][df_p['x6']<=-1] = -0.038834
df_p['x6_woe'][(df_p['x6']>-1) & (df_p['x6']<=0.0024)] = -0.180664
df_p['x6_woe'][df_p['x6']>0.0024] = 0.293899

df_p['x7_woe'] = np.nan
df_p['x7_woe'][df_p['x7']<=621.62] = 0.055095
df_p['x7_woe'][df_p['x7']>621.62] = -0.749705

df_p['lnodds'] = -1.260650 + 0.854068*df_p['x1_woe'] + 0.513575*df_p['x2_woe'] + \
0.329542*df_p['x3_woe'] + 0.650766*df_p['x4_woe'] + \
0.563031*df_p['x5_woe'] + 0.664592*df_p['x6_woe'] + \
0.664559*df_p['x7_woe']

# 计算预测概率
df_p['p'] = 1/(1+np.exp(-df_p['lnodds']))
# 转换评分：特定比率1:10，特定分值600，翻番分数60：
A=400.68431431
B=86.56170245
df_p['score'] = A - B*df_p['lnodds']
df_p['score'] = df_p['score'].astype(int)

return df_p```

2、用标准评分卡对train数据集打分：

`train_p = scorecard(train)`

```train_p = train_p.sort_values('p', ascending=False)
train_p['cut'] = pd.cut(train_p['score'], bins=[0, 370, 420, 470, 520, 570, 620, 670, 1000])
train_p_distr1 = train_p.groupby('cut').size()
train_p_distr2 = train_p.groupby('cut')['y', 'p'].mean()
fig = plt.figure()
train_p_distr1.plot(kind='bar', ax=ax1)
ax2 = ax1.twinx()
train_p_distr2.plot(ax=ax2)```

1

04

1、将数据集model数据集当作新样本(为方便演示先忽略和train数据集的关系)，先用上述标准评分卡对其进行打分，然后根据新样本和原样本的发生比对预测概率进行修正，对比一下修正前后的差别。

```def scorecard_adjust1(df_p):

# 修正 np.log(2008/14170) - np.log(2008/7085)
df_p['ad_lnodds'] = np.log(df_p['p']/(1-df_p['p'])) + np.log(2008/14170) - np.log(2008/7085)

# 计算修正的预测概率

return df_p```

```model_p = scorecard(model)

```model_p = model_p.sort_values('p', ascending=False)
model_p['cut'] = pd.cut(model_p['score'], bins=[0, 370, 410, 450, 490, 530, 570, 610, 650, 690, 1000])
model_p_distr1 = model_p.groupby('cut').size()
fig = plt.figure()
model_p_distr1.plot(kind='bar', ax=ax1)
ax2 = ax1.twinx()
model_p_distr2.plot(ax=ax2)```

2、 同理，将数据集data数据集作为新样本，data数据集是更接近实际业务的数据分布，其中y=0.5的灰色样本定义为未违约客户，看其修正前后的预测概率对比。

```def scorecard_adjust2(df_p):

# 修正 np.log(2008/17758) - np.log(2008/7085)
df_p['ad_lnodds'] = np.log(df_p['p']/(1-df_p['p'])) + np.log(2008/17758) - np.log(2008/7085)

# 计算修正的预测概率

return df_p

data['y2'] = data['y']
data['y2'][data['y2']==0.5] = 0
data['y2'].value_counts(normalize=True)

data_p = scorecard(data)

data_p = data_p.sort_values('p', ascending=False)
data_p['cut'] = pd.cut(data_p['score'], bins=[0, 370, 410, 450, 490, 530, 570, 610, 650, 690, 1000])
data_p_distr1 = data_p.groupby('cut').size()
fig = plt.figure()
data_p_distr1.plot(kind='bar', ax=ax1)
ax2 = ax1.twinx()
data_p_distr2.plot(ax=ax2)```

1

05

0 条评论

• ### 算法 | 决策树

决策树是一种基本学习方法，可用于回归和分类。回归树的分割准则一般是平均误差，而分类树的分割准则有信息增益、信息增益率、基尼指数等，下面简单梳理决策...

• ### 算法 | 随机森林

随机森林是集成学习的一种方法，是将多棵树进行集成的算法，随机是指训练每棵树的样本和变量具有随机性，而多棵树组合在一起就像“森林”一样。

• ### 徒手撸算法 | 逻辑回归

逻辑回归是线性回归的改进，通过特定的连接函数将实数范围压缩到(0, 1)范围内，从而实现分类的目的。

• ### 涨姿势！看骨灰级程序员如何玩转Python

每个人都知道这个命令。但如果你要读取很大的数据，尝试添加这个参数：nrows = 5，以便在实际加载整个表之前仅读取表的一小部分。然后你可以通过选择错误的分隔符...

• ### 帮助数据科学家理解数据的23个pandas常用代码

返回给定轴缺失的标签对象，并在那里删除所有缺失数据（’any’：如果存在任何NA值，则删除该行或列。）。

• ### Python 数据分析初阶

这里可以单独查看其中的内容 data['nick']，计算其中的大小则使用 data['nick'].value_counts()。

• ### 2 个数据处理的小功能，非常实用！

0.25 版本开始支持 query 方法，可读性上又获得大幅提升，类似 sql 查询数据的写法，更加人性化。

• ### 用 Pandas 进行数据处理系列 二

获取行操作df.loc[3:6]获取列操作df['rowname']取两列df[['a_name','bname']] ，里面需要是一个 list 不然会报错增...

• ### pandas模块(很详细归类),pd.concat(后续补充)

https://pandas.pydata.org/pandas-docs/stable/?v=20190307135750