本篇文章我们来做一个信用卡违约率分析的实战项目,这个数据集是台湾某银行 2005 年 4 月到 9 月的信用卡数据,数据集一共包括 25 个字段,具体含义如下 :

现在我们的目标是要针对这个数据集构建一个分析信用卡违约率的分类器。具体选择哪个分类器,以及分类器的参数如何优化,我们可以用 GridSearchCV 这个工具跑一遍。
先梳理下整个项目的流程 :

  1. 加载数据;
  2. 准备阶段:探索数据,采用数据可视化方式可以让我们对数据有更直观的了解,比如我们想要了解信用卡违约率和不违约率的人数。因为数据集没有专门的测试集,我们还需要使用train_test_split 划分数据集。
  3. 分类阶段:之所以把数据规范化放到这个阶段,是因为我们可以使用 Pipeline 管道机制,将数据规范化设置为第一步,分类为第二步。因为我们不知道采用哪个分类器效果好,所以我们需要多用几个分类器,比如 SVM、决策树、随机森林和 KNN。然后通过 GridSearchCV 工具,找到每个分类器的最优参数和最优分数,最终找到最适合这个项目的分类器和该分类器的参数 。

基于以上流程,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 信用卡违约率分析
import pandas as pd
from sklearn.model_selection import learning_curve, train_test_split,GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from matplotlib import pyplot as plt
import seaborn as sns
# 数据加载
data = pd.read_csv('./UCI_Credit_Card.csv')
# 数据探索
print(data.shape) # 查看数据集大
print(data.describe()) # 数据集概览
# 查看下一个月违约率的情况
next_month = data['default.payment.next.month'].value_counts()
print(next_month)
df = pd.DataFrame({'default.payment.next.month': next_month.index,'values': next_month.values})
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.figure(figsize = (6,6))
plt.title('信用卡违约率客户\n (违约:1,守约:0)')
sns.set_color_codes("pastel")
sns.barplot(x = 'default.payment.next.month', y="values", data=df)
locs, labels = plt.xticks()
plt.show()
# 特征选择,去掉ID字段、最后一个结果字段即可
data.drop(['ID'], inplace=True, axis =1) #ID这个字段没有用
target = data['default.payment.next.month'].values
columns = data.columns.tolist()
columns.remove('default.payment.next.month')
features = data[columns].values
# 30%作为测试集,其余作为训练集
train_x, test_x, train_y, test_y = train_test_split(features, target, test_size=0.30, stratify = target, random_state = 1)

# 构造各种分类器
classifiers = [
SVC(random_state = 1, kernel = 'rbf'),
DecisionTreeClassifier(random_state = 1, criterion = 'gini'),
RandomForestClassifier(random_state = 1, criterion = 'gini'),
KNeighborsClassifier(metric = 'minkowski'),
]
# 分类器名称
classifier_names = [
'svc',
'decisiontreeclassifier',
'randomforestclassifier',
'kneighborsclassifier',
]
# 分类器参数
classifier_param_grid = [
{'svc__C':[1], 'svc__gamma':[0.01]},
{'decisiontreeclassifier__max_depth':[6,9,11]},
{'randomforestclassifier__n_estimators':[3,5,6]} ,
{'kneighborsclassifier__n_neighbors':[4,6,8]},
]

# 对具体的分类器进行GridSearchCV参数调优
def GridSearchCV_work(pipeline, train_x, train_y, test_x, test_y, param_grid, score = 'accuracy'):
response = {}
gridsearch = GridSearchCV(estimator = pipeline, param_grid = param_grid, scoring = score)
# 寻找最优的参数 和最优的准确率分数
search = gridsearch.fit(train_x, train_y)
print("GridSearch最优参数:", search.best_params_)
print("GridSearch最优分数: %0.4lf" %search.best_score_)
predict_y = gridsearch.predict(test_x)
print("准确率 %0.4lf" %accuracy_score(test_y, predict_y))
response['predict_y'] = predict_y
response['accuracy_score'] = accuracy_score(test_y,predict_y)
return response

for model, model_name, model_param_grid in zip(classifiers, classifier_names, classifier_param_grid):
pipeline = Pipeline([
('scaler', StandardScaler()),
(model_name, model)
])
result = GridSearchCV_work(pipeline, train_x, train_y, test_x, test_y, model_param_grid , score = 'accuracy')

运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
30000, 25)
ID LIMIT_BAL ... PAY_AMT6 default.payment.next.month
count 30000.000000 30000.000000 ... 30000.000000 30000.000000
mean 15000.500000 167484.322667 ... 5215.502567 0.221200
std 8660.398374 129747.661567 ... 17777.465775 0.415062
min 1.000000 10000.000000 ... 0.000000 0.000000
25% 7500.750000 50000.000000 ... 117.750000 0.000000
50% 15000.500000 140000.000000 ... 1500.000000 0.000000
75% 22500.250000 240000.000000 ... 4000.000000 0.000000
max 30000.000000 1000000.000000 ... 528666.000000 1.000000

[8 rows x 25 columns]
0 23364
1 6636
Name: default.payment.next.month, dtype: int64
GridSearch最优参数: {'svc__C': 1, 'svc__gamma': 0.01}
GridSearch最优分数: 0.8174
准确率 0.8172
GridSearch最优参数: {'decisiontreeclassifier__max_depth': 6}
GridSearch最优分数: 0.8186
准确率 0.8113
GridSearch最优参数: {'randomforestclassifier__n_estimators': 6}
GridSearch最优分数: 0.7998
准确率 0.7994
GridSearch最优参数: {'kneighborsclassifier__n_neighbors': 8}
GridSearch最优分数: 0.8040
准确率 0.8036

1564390117814

从结果中,我们能看到 SVM 分类器的准确率最高,测试准确率为 0.8172。

在决策树分类中,我设置了 3 种最大深度,当最大深度 =6 时结果最优,测试准确率为0.8113;在随机森林分类中,设置了3个决策树个数的取值,取值为6时结果最优,测试准确率为0.7998;在KNN分类中,我设置了3个n的取值,取值为8时,结果最优,测试准确率为0.8036。