数据集说明
金融数据,预测贷款用户是否会逾期。“status”是结果标签,0表示未逾期,1表示逾期。
模型构建
1.首先读入数据集,并分成X和y,简单看一下数据的分布。
data = pd.read_csv('./data_all.csv', engine='python')
y = data['status']
X = data.drop(['status'],axis = 1)
print('The shape of X: ', X.shape)
print('Numbers of label 1: ', len(y[y==1]), ' Numbers of label 0: ', len(y[y==0]))
输出结果:
The shape of X: (4754, 84)
Numbers of label 1: 1193 Numbers of label 0: 3561
即一共有4754条样本,84个特征。其中标签为1的为1193条,标签为0的为3561条,比例约为1:3。
由于特征太多,这里就不一一展示了。
2.划分训练集和测试集。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2018)
print('For train, Numbers of label 1: ', len(y_train[y_train==1]), ' Numbers of label 0: ', len(y_train[y_train==0]))
print('For test, Numbers of label 1: ', len(y_test[y_test==1]), ' Numbers of label 0: ', len(y_test[y_test==0]))
输出:
For train, Numbers of label 1: 834 Numbers of label 0: 2493
For test, Numbers of label 1: 359 Numbers of label 0: 1068
这里按7/3的比例划分训练集和测试集,划分后,训练集和测试集的正负标签比例均维持在1:3左右。
3. 模型构建及评估。简单构建逻辑回归、SVM和决策树3个模型并对模型进行评分,用accuracy和AUC两个评价指标。
逻辑回归代码:
# 逻辑回归
clf_lr = LogisticRegression(solver='liblinear').fit(X_train, y_train)
y_test_pred = clf_lr.predict(X_test)
acc_lr = metrics.accuracy_score(y_test, y_test_pred)
y_test_proba = clf_lr.predict_proba(X_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_test_proba[:,1])
auc_lr = metrics.auc(fpr, tpr)
第一行代码是构建模型并用训练数据拟合。这里指定了求解器是“liblinear”,关于求解器可以看官方文档说明,也可以看我的这篇文章:
codingling:logistic 回归的sklearn实践
然后用训练好的模型预测测试集的标签,计算accuracy,sklearn有直接计算常见指标的函数。
为了计算AUC值(ROC曲线下的面积,ROC曲线的XY轴分别为fpr和tpr,可以看这篇文章),我们还需要预测属于每个标签的概率,即函数predict_proba。然后用roc_curve函数计算出fpr和tpr,再用auc函数计算出AUC值。注意这里的概率是一个二维矩阵,有两列,分别代表属于标签0和标签1的概率。因此在计算时,需要根据实际情况选取具体的列。因为我们这里更关心逾期的样本,也就是标签为1的样本,所以选取了第2列。
SVM和决策树的代码也差不多,只需要改一下模型。
SVM:
# SVM
clf_svm = SVC(gamma='auto', probability=True).fit(X_train, y_train)
y_test_pred = clf_svm.predict(X_test)
acc_svm = metrics.accuracy_score(y_test, y_test_pred)
y_test_proba = clf_svm.predict_proba(X_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_test_proba[:,1])
auc_svm = metrics.auc(fpr, tpr)
只需要注意一点,如果需要计算属于每个标签的概率,SVM模型的参数probability需要设为True。
决策树:
# 决策树
clf_dt = DecisionTreeClassifier().fit(X_train, y_train)
y_test_pred = clf_dt.predict(X_test)
acc_dt = metrics.accuracy_score(y_test, y_test_pred)
y_test_proba = clf_dt.predict_proba(X_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_test_proba[:,1])
auc_dt = metrics.auc(fpr, tpr)
最后,三个模型的评估效果如下:
Model Accuracy AUC
0 LR 0.748423 0.567455
1 SVM 0.748423 0.500000
2 DT 0.672740 0.585353
可以看到,逻辑回归和SVM的准确率是一样的,逻辑回归的AUC值比SVM稍高,0.5的AUC其实相当于随机猜测。而决策树虽然准确率最低,但AUC值却最高。其实这里LR和SVM的准确率一样不是巧合,而是因为这两个模型都把所有测试集中的样本分为“0”类了,而测试集中“0”类样本的比例正好是0.748423。或许LR和SVM不适合类别不均衡的情况,又或许需要利用其它调参手段才能改善模型效果。
对于这种类别不平衡的数据集,准确率其实不是一个很好的评估模型的指标,相对来说AUC更可靠一些。所以初步来看,决策树模型的效果最好。
附上完整代码:
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
data = pd.read_csv('./data_all.csv', engine='python')
y = data['status']
X = data.drop(['status'],axis = 1)
print('The shape of X: ', X.shape)
print('Numbers of label 1: ', len(y[y==1]), ' Numbers of label 0: ', len(y[y==0]))
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2018)
print('For train, Numbers of label 1: ', len(y_train[y_train==1]), ' Numbers of label 0: ', len(y_train[y_train==0]))
print('For test, Numbers of label 1: ', len(y_test[y_test==1]), ' Numbers of label 0: ', len(y_test[y_test==0]))
df_result = pd.DataFrame(columns=('Model', 'Accuracy', 'AUC'))
row = 0
# 逻辑回归
clf_lr = LogisticRegression(solver='liblinear').fit(X_train, y_train)
y_test_pred = clf_lr.predict(X_test)
acc_lr = metrics.accuracy_score(y_test, y_test_pred)
y_test_proba = clf_lr.predict_proba(X_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_test_proba[:,1])
auc_lr = metrics.auc(fpr, tpr)
df_result.loc[row] = ['LR', acc_lr, auc_lr]
row += 1
# SVM
clf_svm = SVC(gamma='auto', probability=True).fit(X_train, y_train)
y_test_pred = clf_svm.predict(X_test)
acc_svm = metrics.accuracy_score(y_test, y_test_pred)
y_test_proba = clf_svm.predict_proba(X_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_test_proba[:,1])
auc_svm = metrics.auc(fpr, tpr)
df_result.loc[row] = ['SVM', acc_svm, auc_svm]
row += 1
# 决策树
clf_dt = DecisionTreeClassifier().fit(X_train, y_train)
y_test_pred = clf_dt.predict(X_test)
acc_dt = metrics.accuracy_score(y_test, y_test_pred)
y_test_proba = clf_dt.predict_proba(X_test)
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_test_proba[:,1])
auc_dt = metrics.auc(fpr, tpr)
df_result.loc[row] = ['DT', acc_dt, auc_dt]
row += 1
print(df_result)
期待后续的改进吧~
参考资料:
sklearn官方文档