运用逻辑回归进行违约的预测,在构建模型的过程中用到了向前法筛选模型自变量
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import os
import re
import datetime
import time
from sklearn.model_selection import train_test_split
# 导入数据
os.chdir('data')
loanfile = os.listdir()
creatVar = locals()
for i in loanfile:
if i.endswith("txt"):
creatVar[i.split('.')[0]] = pd.read_csv(i, encoding='gbk',sep=';')
#print(i.split('.')[0])
# 生成被解释变量bad_good
bad_good = {'B':1, 'D':1, 'A':0, 'C':2}
loan['bad_good'] = loan.status.map(bad_good)
#print(loan.head())
# 通过表的连接获取借款人的年龄、性别信息
data2 = pd.merge(loan, disp, on = 'account_id', how='left')
data2 = pd.merge(data2, client, on='client_id', how='left')
data2 = data2[data2.type=='OWNER']
#获取借款人居住地的经济状况
data3 = pd.merge(data2, district, left_on='district_id',
right_on='A1', how='left')
#计算变异系数
data_4temp1 = pd.merge(loan[['account_id', 'date']],
trans[['account_id', 'type', 'amount', 'balance', 'date']],
on = 'account_id')
data_4temp1.columns = ['account_id', 'date', 'type', 'amount', 'balance', 't_date']
data_4temp1 = data_4temp1.sort_values(by = ['account_id', 't_date'])
#日期格式转换
data_4temp1['date'] = data_4temp1['date'] + 19000000
data_4temp1['date'] = pd.to_datetime(data_4temp1['date'].values.astype('str'))
data_4temp1['t_date'] = data_4temp1['t_date'] + 19000000
data_4temp1['t_date'] = pd.to_datetime(data_4temp1['t_date'].values.astype('str'))
#print(data_4temp1.head())
data_4temp2 = data_4temp1[(data_4temp1.date > data_4temp1.t_date) &
(data_4temp1.date < data_4temp1.t_date + datetime.timedelta(days=365))]
#得到变异系数
data_4temp3 = data_4temp2.groupby('account_id')['balance'].aggregate(avg_balance=np.mean,std_balance=np.std)
data_4temp3['cv_balance'] = data_4temp3[['avg_balance', 'std_balance']].apply(lambda x: x[1]/x[0], axis=1)
#平均支出和收入的比例
type_dict = {'PRIJEM':'out', "VYDAJ":'income'}
data_4temp2['type1'] = data_4temp2.type.map(type_dict)
data_4temp5 = data_4temp2.pivot_table('amount', index='account_id', columns='type1')
data_4temp5.dropna(inplace=True)
data_4temp5['r_out_in'] = data_4temp5['out'] / data_4temp5['income']
data4 = pd.merge(data3, data_4temp3, left_on='account_id', right_index=True, how='left')
data4 = pd.merge(data4, data_4temp5, left_on='account_id', right_index=True, how='left')
#计算贷存比和贷收比
data4['r_lb'] = data4['amount'] / data4['avg_balance']
data4['r_lincome'] = data4['amount'] / data4['income']
#构建Logistic模型
data_model = data4[data4.status!='C']
for_predict = data4[data4.status=='C']
train, test = train_test_split(data_model, test_size=0.3, random_state=42)
#print("训练集样本量:{0} \n测试集样本量:{1}".format(len(train), len(test)))
#向前法筛选有用字段
def forward_select(data, response):
import statsmodels.api as sm
import statsmodels.formula.api as smf
remaining = set(data.columns) #字段名
remaining.remove(response)
selected = []
current_score, best_new_score = float('inf'), float('inf')
while remaining:
aic_with_candidates=[]
for candidate in remaining:
formula = "{} ~ {}".format(
response,' + '.join(selected + [candidate]))
aic = smf.glm(formula=formula, data=data).fit().aic
aic_with_candidates.append((aic, candidate))
aic_with_candidates.sort(reverse=True)
best_new_score, best_candidate=aic_with_candidates.pop()
if current_score > best_new_score:
remaining.remove(best_candidate)
selected.append(best_candidate)
current_score = best_new_score
#print('aic is {},continuing!'.format(current_score))
else:
#print('forward selection over!')
break
formula = "{} ~ {}".format(response,' + '.join(selected))
print("final formula is {}".format(formula))
model = smf.glm(formula = formula, data=data
).fit()
return (model)
candidates = ['bad_good', 'A1', 'A3', 'A4', 'A10', 'A11', 'A12','amount', 'duration',
'A13', 'A14', 'A15', 'A16', 'avg_balance', 'std_balance',
'cv_balance', 'income', 'out', 'r_out_in', 'r_lb', 'r_lincome']
data_for_select = train[candidates]
lg_model = forward_select(data=data_for_select, response='bad_good')
#print(lg_model.summary().tables[1])
#模型验证
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
fpr, tpr, threshold = roc_curve(test.bad_good, lg_model.predict(test))
rocauc = auc(fpr, tpr)
plt.plot(fpr, tpr, 'b', label='AUC={}'.format(rocauc))
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.title('ROC curve')
plt.xlabel('False position rate')
plt.ylabel('True position rate')
#plt.show()
# 运用模型进行预测
for_predict['prob'] = lg_model.predict(for_predict)
print(for_predict['prob'].describe())
通过ROC曲线评估模型的拟合能力