【风控】评分卡模型的代码实践 超详细可运行

本文详细介绍了评分卡模型的构建过程,包括数据预处理(处理缺失值和异常值)、特征选择(使用WOE和IV)、模型建立及评分卡转换。通过Kaggle的Give Me Some Credit数据集,展示了如何应用WOE编码提升模型预测效果,选取RevolvingUtilizationOfUnsecuredLines等特征,并给出了完整的可运行代码。
摘要由CSDN通过智能技术生成

写了好久,整理了好久,可运行,超详细的评分卡模型实践。
跟着做一遍一定大有收获!

数据集:Kaggle上的Give Me Some Credit的数据

1、了解变量

在这里插入图片描述

2、数据集分析与预处理

查看缺失值

df = pd.read_csv("./GiveMeSomeCredit/cs-training.csv").drop("Unnamed: 0", axis=1)
df.info()

在这里插入图片描述
可知, 月收入 与 家属数量 存在 缺失值。

# 详细查看每个变量的情况与缺失率
df.describe().T.assign(missing_rate = df.apply(lambda x: (len(x)-x.count())/float(len(x))))

在这里插入图片描述

缺失值处理

原则:缺失值较少可以直接删除(也可以进行一些其他的填补操作。此例中删除),若较多则根据变量之间存在的关系来填补缺失值(此处采用随机森林的方法)。

此处源码中有一个小报错,我这边有做修改:

from sklearn.ensemble import RandomForestRegressor
# 用随机森林对'月收入'缺失值预测填充函数
def set_missing(df):
    # 把已有的数值型特征取出来
    process_df = df.iloc[:, [5,0,1,2,3,4,6,7,8,9]]
    # 分成已知该特征和未知该特征两部分
    known = process_df[process_df.MonthlyIncome.notnull()]
    unknown = process_df[process_df.MonthlyIncome.isnull()]
    # X为特征属性值
    X = known.iloc[:, 1:]
    # y为结果标签值
    y = known.iloc[:, 0]
    # fit到RandomForestRegressor之中
    rfr = RandomForestRegressor(random_state=0, n_estimators=200, max_depth=3, n_jobs=-1)
    rfr.fit(X, y)
    # 用得到的模型进行未知特征值预测
    predicted = rfr.predict(unknown.iloc[:, 1:]).round(0)
    print("预测值: ", predicted)
    # 用得到的预测结果填补原缺失数据
    df.loc[(df.MonthlyIncome.isnull()), 'MonthlyIncome'] = predicted
    return df
df = set_missing(df)

# 删除所剩空值
df = df.dropna()
# 删除重复值
df = df.drop_duplicates()

查看并处理异常值

异常值:偏离大多数抽样数据的数值,通常指测定值中与平均值的偏差超过两倍标准差的测定值。
通常采用离群值检测的方法对异常值进行检测

此处也在源代码的基础上增加了不同的展示(直方图+箱线图):

# 1.RevolvingUtilizationOfUnsecuredLines
f,[ax1,ax2]=plt.subplots(1,2,figsize=(12,5))
sns.distplot(df['RevolvingUtilizationOfUnsecuredLines'],ax=ax1)
sns.boxplot(y='RevolvingUtilizationOfUnsecuredLines',data=df,ax=ax2)
plt.show()
print(df['RevolvingUtilizationOfUnsecuredLines'].describe())

在这里插入图片描述
可知,数据分布及其不正常,中位数和四分之三位数都小于1,但是最大值确达到了50708,可用额度比值应该小于1,所以后面将大于1的值当做异常值剔除。

len(df[df['RevolvingUtilizationOfUnsecuredLines']>1]) # 3260条
df = df[df['RevolvingUtilizationOfUnsecuredLines']<=1]
# 2、年龄分布
f,[ax1,ax2]=plt.subplots(1,2,figsize=(12,5))
sns.distplot(df['age'],ax=ax1)
sns.boxplot(y='age',data=df,ax=ax2)
plt.show()
print(df['age'].describe())

# 存在小于0的情况,明显异常可去除。 大于100的较多且连续,可保留
print('count >100:', len(df[df.age>100]))

df = df[df.age>0]

在这里插入图片描述

# 3、逾期30-59天 | 60-89天 | 90天笔数分布:
f,[[ax1,ax2],[ax3,ax4],[ax5,ax6]] = plt.subplots(3,2,figsize=(24,10))
sns.distplot(df['NumberOfTime30-59DaysPastDueNotWorse'],ax=ax1)
sns.boxplot(y='NumberOfTime30-59DaysPastDueNotWorse',data=df,ax=ax2)
sns.distplot(df['NumberOfTime60-89DaysPastDueNotWorse'],ax=ax3)
sns.boxplot(y='NumberOfTime60-89DaysPastDueNotWorse',data=df,ax=ax4)
sns.distplot(df['NumberOfTimes90DaysLate'],ax=ax5)
sns.boxplot(y='NumberOfTimes90DaysLate',data=df,ax=ax6)
plt.show()

在这里插入图片描述
不够清晰,换一种:


df.boxplot(column=["NumberOfTime30-59DaysPastDueNotWorse", "NumberOfTime60-89DaysPastDueNotWorse", "NumberOfTimes90DaysLate"], 
            rot=30)

在这里插入图片描述
上面的箱线图可以看出 NumberOfTime30-59DaysPastDueNotWorse,NumberOfTime60-89DaysPastDueNotWorse,NumberOfTimes90DaysLate三个特征都存在两个异常值,下面使用 unique() 方法查看具体的异常值:


print("NumberOfTime30-59DaysPastDueNotWorse:", df["NumberOfTime30-59DaysPastDueNotWorse"].unique())
print("NumberOfTime60-89DaysPastDueNotWorse:", df["NumberOfTime60-89DaysPastDueNotWorse"].unique())
print("NumberOfTimes90DaysLate:", df["NumberOfTimes90DaysLate"].unique())

在这里插入图片描述
此处可以直接删除,也可以用中位数等来代替,可以自行考虑并选择。

若想删除:

df = df[df["NumberOfTime30-59DaysPastDueNotWorse"]<95]
df = df[df["NumberOfTime60-89DaysPastDueNotWorse"]<95]
df = df[df["NumberOfTimes90DaysLate"]<95]

此处用中位数代替:

# 用中位数替代异常值
def replaceOutlier(data):
    New = []
    med = data.median()
    for val in data:
        if ((val == 98) | (val == 96)):
            New.append(med)
        else:
            New.append(val)
    return New

df["NumberOfTime30-59DaysPastDueNotWorse"] = replaceOutlier(df["NumberOfTime30-59DaysPastDueNotWorse"])
df["NumberOfTime60-89DaysPastDueNotWorse"] = replaceOutlier(df["NumberOfTime60-89DaysPastDueNotWorse"])
df["NumberOfTimes90DaysLate"] = replaceOutlier(df["NumberOfTimes90DaysLate"])

# 替换后的箱线图
df.boxplot(column=["NumberOfTime30-59DaysPastDueNotWorse", "NumberOfTime60-89DaysPastDueNotWorse", "NumberOfTimes90DaysLate"],
            rot=30)
plt.show()

在这里插入图片描述
正常多了,下一个:

#4、DebtRatio负债率特征分布
f,[ax1,ax2] = plt.subplots(1,2,figsize=(12,5)</
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值