任务要求
某银联用户数据有y:表示是否逾期,另存在199个用户相关信息变量,记为x_001,x_002……x_199。要求通过机器学习方法对用户进行是否逾期的分类。
1.数据处理
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
from sklearn.impute import KNNImputer
from sklearn.tree import DecisionTreeClassifier
data=pd.read_csv("model_sample.csv",header=0)
data=data.drop('user_id',axis=1)#把没有用的用户ID列去掉
display(data.head())
发现数据有缺失值,对所有缺失值进行统计
#缺失值处理部分
dfsum=[]#存储缺失值记录
c=data.columns#返回数据列索引
#找每一个属性的缺失值
for i in c:
summax=0
for x in range(len(data['y'])):
if math.isnan(data[i][x]):#用于检查给定数字是否为“ NaN”
summax+=1
dfsum.append(summax)
#作图
plt.plot(dfsum,color = "orange")
把缺失值的个数从小到大排列,并且按需求进行缺失值的处理
本文中认为属性里缺失值超过数据记录数50%的属性可以删去,每一条数据里损失超过50%属性的,需要删除
dfsum.sort()
plt.plot(dfsum,color = "orange")
#我们认为缺失值超过数据记录数50%的属性可以删去
m=0
for i in range(50,201,1):
if dfsum[i]>5509:
break
m=i
print(m+1)
#留下126个属性
#删除过程
c=data.columns
for i in c:
nansum=0
for y in data[i]:
if math.isnan(y):
nansum+=1
if nansum>5509:
data=data.drop(i,axis=1)
#去除大量缺失的,125个属性里,损失超过50%即63个属性的,需要删除
c=data.columns
nan=[]
dropnan=[]#滤除缺失数据
num_of_attribute=len(c)-1
for i in range(len(data['y'])):
nansum=0
for j in range(1,len(c)):
if math.isnan(data[c[j]][i]):
nansum+=1
nan.append(nansum/num_of_attribute)
if (nan[i]>0.5):
dropnan.append(i)
#print(dropnan)
#去除缺失值
data=data.drop(dropnan)
最后得到9701行126列的数据,并对连续属性用KNN处理,进行插值
imputer = KNNImputer(n_neighbors=3)
data2 = imputer.fit_transform(data2)
对分类数据进行one-hot编码
data2 = pd.get_dummies(data2)
数据规模过大,需要对数据进行降维处理
scaler = StandardScaler()
scaler.fit(X)
X_scaled = scaler.transform(X)
pca = PCA(n_components=6)
X_pca = pca.fit_transform(X_scaled)
print("原始数据规模: {}".format(str(X_scaled.shape)))
print("降维后数据规模: {}".format(str(X_pca.shape)))
通过SMOTE方法进行抽样
#利用SMOTE方法进行抽样
from imblearn.over_sampling import SMOTE
#定义SMOTE模型
smo = SMOTE(random_state=42,sampling_strategy=0.83)
X_smo, y_smo = smo.fit_resample(X_pca, y)
# print(Counter(y_smo))
y_smo["y"].value_counts()
2.模型构建
构建训练集和测试集,并构建决策树进行训练调参。通过熵调参,确定参数最大深度为12,最小分裂叶节点为0.008时,模型预测效果较好,其在测试集上的准确率达到了0.676
X_train, X_test, y_train, y_test = train_test_split( X_smo, y_smo, random_state=42)
#定义决策树,用熵调参
tree = DecisionTreeClassifier(criterion='entropy',random_state=0,max_depth=12,min_samples_split=5,min_samples_leaf=0.008)
tree.fit(X_train, y_train)
y_pred=tree.predict(X_test)
print("Accuracy on training set: {:.3f}".format(tree.score(X_train, y_train)))
print("Accuracy on test set: {:.3f}".format(tree.score(X_test, y_test)))
得到结果:
3.结果评测
计算precision、recall 和f1-score,发现成功预测逾期还款的精确率达到0.63,召回率达到0.66,f1-score达到0.64
#精确率 召回率 F1-score
print(classification_report(y_test, y_pred))
#混淆矩阵
confusion = confusion_matrix(y_test, y_pred)
print("混淆矩阵Confusion matrix:\n{}".format(confusion))
绘制ROC曲线,其AUC的面积为0.71797
# ROC
fpr, tpr, thresholds = roc_curve(y_test,y_pred)#,pos_label=0)
plt.plot(fpr, tpr, label="ROC Curve",color = "green")
plt.xlabel("FPR")
plt.ylabel("TPR (recall)")
plt.legend(loc=4)
xx=np.arange(0,1,0.01)
yy=np.arange(0,1,0.01)
plt.plot(xx,yy)
绘制KS线,KS值越大,表示模型能够将正、负客户区分开的程度越大。KS值的取值范围是[0,1] ,得到ks值为0.2317,可见模型是可用的(大于0.2)
#K-S
y_test=np.array(y_test)
y_pred=np.array(y_pred)
sum0=0
sum1=0
for i in range(len(y_pred)):
if y_pred[i]==0:
if y_test[i]==0:
sum0+=1
else:
sum1+=1
print(format((sum0-sum1)/len(y_pred),".2%"))
plt.plot(['0-1','1-2'],[sum0/len(y_pred),1])
plt.plot(['0-1','1-2'],[sum1/len(y_pred),1],color = "red")
plt.plot(['0-1'],[sum0/len(y_pred)],'o', markersize=10, c='blue',label="0")
plt.plot(['0-1'],[sum1/len(y_pred)],'o', markersize=10, c='red',label="1")
plt.plot(['1-2'],[1],'o', markersize=10, c='blue')
plt.plot(['1-2'],[1],'o', markersize=10, c='red')
plt.legend(loc="best")
plt.title("K-S")
其所有代码已上传至资源银联数据分类练习模型-机器学习-jupyternotebook