python风控建模_风控建模之特征筛选与建模(python)

特征筛选

在建模之前的一步就是将特征工程做好的变量进行筛选,在风控项目中筛选分为两步:初步筛选、逐步回归筛选以及稳定性筛选。

初步筛选

通常评分卡模型的特征筛选主要从以下4个角度出发: 缺失率(一般变量较少时可以可以相对放宽,使用一些方法,如插值等,来填充缺失值) 好坏区分能力(即IV值) 相关性(一般使用皮尔逊相关系数) 分箱后的单调性

信息量(IV)

信息量(Information Value,IV)定义为特征WOE编码的加权求和,woe的计算公式(前面章节有详细介绍:风控建模之特征转换):

其中pyi和pni的定义与WOE编码中完全相同。单个特征的IV等于该特征每个取值对应的ivi的累加。

从公式上看,IV衡量的是变量不同取值样本标签的分布差异,可以从一定程度上反映单特征对标签区分的贡献度。

对于特征的IV筛选标准:特征整体的IV值不高时,可以将筛选的阀值调低,如在项目中一般调低至0.01,去寻找有效特征;而当特征的IV值大于0.5时,说明该特征具有显著好坏区分能力,因而可以作为前置的策略规则,提前拒绝高风险人群,对于规则阀值的确定可以依据bad_rate以及业务需要进行设置。

python代码:

import toad

import pandas as pd

file_path = r'C:\Users\jiaxiong.he\Desktop\智能风控\book_data_code\ppd.xlsx'

data = pd.read_excel(file_path)

ex_list = ['Idx', 'ListingInfo']

# (1)empyt=0.9: 若变量的缺失值大于0.9被删除

# (2)iv=0.02: 若变量的iv值小于0.02被删除

# (3)corr=0.7: 若两个相关性高于0.7时,iv值低的变量被删除

# (4)return_drop=False: 若为True,function将返回被删去的变量列

# (5)exclude=None: 明确不被删去的列名,输入为list格式

df_select, drop_list = toad.selection.select(

data, data['target']

,empty=0.9,iv=0.01,corr=0.7

,return_drop=True,exclude=ex_list)

# df_select返回的被筛选数据,drop_list返回被各个条件删除的变量

逐步回归筛选

逐步回归(Stepwise Regression)是一种线性回归模型自变量选择方法,其基本思想是,贪心地遍历所有变量最优组合,以保证最终模型的变量组合为最优。该过程涉及多次F检验。分为:向前逐步回归、向后逐步回归、双向逐步回归。在风控建模项目中,是在特征转换成woe编码时,进行逐步回归筛选特征。

向前逐步回归

初始情况下,模型中只有一个F检验显著性最高的变量,之后尝试加入另一个F检验显著性最高的变量。上述过程不断迭代,直至没有变量满足放入模型的条件。

向后逐步回归

与前向选择相反。首先将所有变量同时放入模型,然后将其中F检验显著性最低的变量从模型中剔除。上述过程不断迭代,直至没有变量满足剔出模型的条件。

双向逐步回归

将前向选择与后向消除同时进行。模型中每加入一个自变量,可能使得某个已放入模型的变量显著性减小。当其显著性小于阈值时,可将该变量从模型中剔除。双向消除即每增加一个新的显著变量的同时,检验整个模型中所有变量的显著性,将不显著变量剔除,从而得到最优的变量组合。

在实际项目实践中,双向逐步回归的表现较好。

combiner = toad.transform.Combiner()

combiner.fit(df_select, data['target'], method='chi',

min_samples=0.05,empty_separate=True,exclude=ex_list+['target'])

transer = toad.transform.WOETransformer()

data_woe = transer.fit_transform(combiner.transform(df_select, labels=False), data['target'], exclude=ex_list+['target'])

import warnings

warnings.filterwarnings("ignore")

# - estimator: 用于拟合的模型,支持'ols', 'lr', 'lasso', 'ridge'

# - direction: 逐步回归的方向,支持'forward', 'backward', 'both' (推荐)

# - criterion: 评判标准,支持'aic', 'bic', 'ks', 'auc'

# - max_iter: 最大循环次数

# - return_drop: 是否返回被剔除的列名

# - exclude: 不需要被训练的列名,比如ID列和时间列

stepwise_rt = toad.selection.stepwise(data_woe, data['target'],estimator='lr'

,direction='both',criterion='aic'

,exclude=ex_list+['target'])

print(stepwise_rt.shape) # (5000, 47)从100多个变量中筛选出47个

经验证,direction = ‘both’效果最好。estimator = ‘ols’以及criterion = ‘aic’运行速度快且结果对逻辑回归建模有较好的代表性

stepwise_rt_list = [i for i in stepwise_rt.columns if i not in ex_list+['target']]

稳定性筛选(PSI)

在实际业务中,最后决定模型是否能够上线的标准是模型及变量的PSI(模型表现KS只要达到30以上就具备区分好坏能力),不然可能出现的情况就是在训练集里模型表现良好,而在测试集以及时间外样本验证中KS跌如狗,那么之前的工作前功尽弃,少侠请重新再来吧!所以特征稳定性筛选是十分必要的,一般而言特征整体稳定,那么模型就稳定,KS不会波动太大。

PSI介绍

群体稳定性指标(Population Stability Index,PSI)衡量特征及模型的稳定性。其基本含义为:计算同一指标在两个不同数据集上的分布差异,作为当前指标的稳定性指标。PSI公式定义为:

其中pitarget为目标分布上第i箱中样本占总比,pibase为基础分布上第i箱中样本占总比。首先将基础分布按照等频分箱策略进行10等分,然后对目标分布使用相同的阈值进行分箱。分别计算第i箱的pitarget和pibase,带入PSI公式即可得到两个分布的稳定性差异。

PSI一般而言越小越好,当其等于0时标明没有差异,而当其大于0.01时说明特征不稳定需要查明原因

python代码:

# 读取测试集数据

test_file_path = r'C:\Users\jiaxiong.he\Desktop\智能风控\book_data_code\ppd_test.xlsx'

data_test = pd.read_excel(test_file_path)

# 测试集数据转换

data_test_woe = transer.fit_transform(combiner.transform(data_test[df_select.columns], labels=False),

data_test['target'], exclude=ex_list+['target'])

# 计算逐步回归后训练集与测试集PSI

df_PSI = toad.metrics.PSI(data_woe[stepwise_rt_list], data_test_woe[stepwise_rt_list])

# 筛选PSI小于0.01的变量

psi_list = list(df_PSI[df_PSI<0.01].index)

建模

下面将使用传统评分卡的逻辑回归建模以及作为对比的XGBOOST建模

逻辑回归建模

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression()

lr.fit(data_woe[psi_list], data['target'])

# 预测训练集和以及测试集

pred_train = lr.predict_proba(data_woe[psi_list])[:,1]

pred_test = lr.predict_proba(data_test_woe[psi_list])[:,1]

# 使用KS,ROC评价模型好坏

from toad.metrics import KS, AUC

print('训练集结果')

print('train KS',KS(pred_train, data['target']))

print('train AUC',AUC(pred_train, data['target']))

print('测试集结果')

print('test KS',KS(pred_test, data_test['target']))

print('test AUC',AUC(pred_test, data_test['target']))

# 将预测等频分箱,观测每组的区别

toad.metrics.KS_bucket(pred_train, data['target'], bucket=10, method = 'quantile')

从bad_rate上看,模型排序性还行,只是在3,4行时出现波动

from sklearn.metrics import roc_auc_score,roc_curve,auc

from matplotlib import pyplot as plt

# 划roc曲线

fpr_train,tpr_train,_ = roc_curve(data['target'], pred_train)

fpr_test,tpr_test,_ = roc_curve(data_test['target'], pred_test)

plt.plot(fpr_train,tpr_train, label='train')

plt.plot(fpr_test,tpr_test, label='test')

plt.plot([0,1], [0,1], 'k--')

plt.xlabel('False positive rate')

plt.ylabel('True positive rate')

plt.title('ROC Curve')

plt.legend(loc='best')

plt.show()

XGBOOST建模

import xgboost as xgb

model = xgb.XGBClassifier(learning_rate=0.05,

n_estimators=400,

max_depth=2,

class_weight='balanced',

min_child_weight=1,

subsample=1,

nthread=-1,

scale_pos_weight=1,

random_state=1,

n_jobs=-1,

reg_lambda=300)

model.fit(data_woe[psi_list], data['target'])

pred_train = model.predict_proba(data_woe[psi_list])[:,1]

pred_test = model.predict_proba(data_test_woe[psi_list])[:,1]

# 使用KS,ROC评价模型好坏

from toad.metrics import KS, AUC

print('训练集结果')

print('train KS',KS(pred_train, data['target']))

print('train AUC',AUC(pred_train, data['target']))

print('测试集结果')

print('test KS',KS(pred_test, data_test['target']))

print('test AUC',AUC(pred_test, data_test['target']))

# 训练集结果

# train KS 0.5071609424051782

# train AUC 0.8339465507977667

# 测试集结果

# test KS 0.2578754578754579

# test AUC 0.674981684981685

# 划roc曲线

fpr_train,tpr_train,_ = roc_curve(data['target'], pred_train)

fpr_test,tpr_test,_ = roc_curve(data_test['target'], pred_test)

plt.plot(fpr_train,tpr_train, label='train')

plt.plot(fpr_test,tpr_test, label='test')

plt.plot([0,1], [0,1], 'k--')

plt.xlabel('False positive rate')

plt.ylabel('True positive rate')

plt.title('ROC Curve')

plt.legend(loc='best')

plt.show()

通过模型结果可以看出,XGBoost模型的效果并没有明显高于逻辑回归模型,但在测试集上表现较差,由于没有进行分箱调整,因此逻辑回归建模训练集合测试集的KS波动较大,挖个坑,下一章把模型调好吧!

评分卡模型输出

接下来就是评分卡离线建模的最后一步生成标准评分卡:

from toad.scorecard import ScoreCard

# 将之前分箱和编码对象输入,base_odds和pdo后面会专门写一章介绍

card = ScoreCard(combiner=combiner,

transer=transer, C=0.1,

class_weight='balanced',

base_score=600,

base_odds=35,

pdo=60,

rate=2)

card.fit(data_woe[psi_list],data['target'])

final_card = card.export(to_frame=True)

# final_card

留下两个坑,1)手动调整分箱使其符合业务要求以及KS在训练集合测试集相对稳定,2)关于base_odds和pdo写一章介绍

你可能感兴趣的:(python风控建模)