一、背景
信用卡评分是以大量数据的统计结果为基础,根据客户提供的资料和历史数据对客户的信用进行评估,评分卡模型一般分为三类:A卡:申请评分卡,B卡:行为评分卡,C卡:催收评分卡。
本文主要涉及的为申请评分卡,申请评分卡的目标主要是区分好客户和坏客户,评分卡的结果为高分数的申请人意味着比低分数的申请人的风险低。
二、项目流程
数据源分析
数据源自于kaggle Give Me Some Credit 15万条样本数据,10个影响客户好坏的特征值,特征属性主要包括:
==基本特征==:借款人的年龄
==偿还债务能力==:借款人收入,负债率等
==信用往来==:两年内35-59天逾期次数,60-89天逾期次数等;
==财产状况==:包括了开放式信贷和贷款数量、不动产贷款或额度数量;
==其他因素==:借贷人的家属数量;
三、数据预处理
1.首先导入数据,对数据集相关情况进行了解,是否存在缺失值;
datasets = pd.read_csv('./cs_training.csv')
del datasets['Unnamed: 0']
#查看缺失值
print(datasets.info())
#查看数据集的详细信息
print(datasets.describe())
其中MonthlyIncome和NumberOfDependents存在缺失值
2.对异常值进行分析,发现年龄和逾期还款次数存在异常值过滤掉为0 的数据,删除逾期还款次数异常值;
#对年纪进行分析发现其中有为0的异常值,将其过滤
fig,ax = plt.subplots(figsize=(5,4))
ax.boxplot(datasets['age'])
plt.xlabel('Age')
plt.ylabel('Values')
plt.show()
datasets = datasets[datasets['age']>0]
逾期还款次数
columns_worse = ['NumberOfTime30-59DaysPastDueNotWorse','NumberOfTimes90DaysLate','NumberOfTime60-89DaysPastDueNotWorse']
datasets.boxplot(column=columns_worse)
plt.xticks(rotation=90)
plt.show()
#剔除异常值后数值分布
datasets = datasets.drop(datasets[datasets['NumberOfTime30-59DaysPastDueNotWorse']>80].index)
columns_worse = ['NumberOfTime30-59DaysPastDueNotWorse','NumberOfTimes90DaysLate','NumberOfTime60-89DaysPastDueNotWorse']
datasets.boxplot(column=columns_worse)
plt.xticks(rotation=90)
plt.show()
3.对缺失值进行处理,对于NumberOfDependents数据,确实值相对较少,直接删除不影响整体数据,对于MonthlyIncome缺失值较多,采用随机森林预测的方法对缺失值进行填补;
#删除NumberOfDependents为空的数据
datasets = datasets.drop(datasets[datasets['NumberOfDependents'].isnull()].index)
#对MonthlyIncome缺失值预测
#数据集 剔除因变量
df = datasets.iloc[:,[1,2,3,4,5,6,7,8,9,10]]
#需要进行预测的数据集
uknown = df[df['MonthlyIncome'].isnull()].iloc[:,[0,1,2,3,5,6,7,8,9]]
#训练集数据
known = df[~df['MonthlyIncome'].isnull()]
#自变量数据
known_X = known.iloc[:,[0,1,2,3,5,6,7,8,9]]
#因变量数据
known_Y = known['MonthlyIncome']
#采用随机森林算法,首先是进行参数的选取
def params_fit(train_X,train_Y):
s_list = []
i_lists = []
for i in range(100,200,10):
rf = RandomForestRegressor(n_estimators=i,random_state=42)
scores = cross_val_score(rf,train_X,train_Y,cv=3).mean()
s_list.append(scores)
i_lists.append(i)
max_scores = max(s_list)
max_es = s_list.index(max_scores)*10+100
print(s_list)
print('====分割线=====')
# 获取最大深度
paras = {'max_depth':np.arange(3,10,1)}
rfs = RandomForestRegressor(n_estimators=max_es,random_state=42)
gs = GridSearchCV(rfs,param_grid=paras,cv=3)
fun = g