每一行数据,都代表了之前的一次贷款信息。你琢磨了很久,终于弄明白了每一列究竟代表什么意思:
下面我们开始动手实践。用Python做个决策树出来,辅助我们判断贷款风险。
你需要loans.csv这个文件。如果一切正常,请把它移动到咱们的工作目录里面。
首先,我们新建一个Python 笔记本,起名叫做loans-tree。
In [1]:
#为了让Python能够高效率处理表格数据,我们使用一个非常优秀的数据处理框架Pandas。
import pandas as pd
#然后我们把loans.csv里面的内容全部读取出来,存入到一个叫做df的变量里面。
df = pd.read_csv('loans.csv')
#我们看看df这个数据框的前几行,以确认数据读取无误。因为表格列数较多,屏幕上显示不完整,我们向右拖动表格,看表格最右边几列是否也正确读取。
df.tail()
Out[1]:
In [2]:
#统计一下总行数,看是不是所有行也都完整读取进来了。
df.shape
Out[2]:
运行结果如下:(46508, 13)
每一条数据的最后一列safe_loans是个标记,告诉我们之前发放的这笔贷款是否安全。我们把这种标记叫做目标(target),把前面的所有列叫做“特征”(features)。
下面我们就分别把特征和目标提取出来。依照机器学习领域的习惯,我们把特征叫做X,目标叫做y。
In [3]:
X = df.drop('safe_loans', axis=1)
y = df.safe_loans
#我们看一下特征数据X的形状:(46508, 12)除了最后一列,其他行列都在。符合我们的预期。我们再看看“目标”列。
#特征数据Y的形状:执行后显示如下结果:(46508,)逗号后面没有数字,指的是只有1列。:
print(X.shape,y.shape)
注意这里有一个问题。Python下做决策树的时候,每一个特征都应该是数值(整型或者实数)类型的。但是我们一眼就可以看出,grade, sub_grade, home_ownership等列的取值都是类别(categorical)型。所以,必须经过一步转换,把这些类别都映射成为某个数值,才能进行下面的步骤。
那我们就开始映射吧: 这里,我们使用了LabelEncoder函数,成功地把类别变成了数值。小测验:在grade列下面,B被映射成了什么数字?
In [4]:
from sklearn.preprocessing import LabelEncoder
from collections import defaultdict
d = defaultdict(LabelEncoder)
X_trans = X.apply(lambda x: d[x.name].fit_transform(x))
X_trans.tail()
Out[4]:
下面我们需要做的事情,是把数据分成两部分,分别叫做训练集和测试集。
为什么这么折腾?
因为有道理。
想想看,如果期末考试之前,老师给你一套试题和答案,你把它背了下来。然后考试的时候,只是从那套试题里面抽取一部分考。你凭借超人的记忆力获得了100分。请问你学会了这门课的知识了吗?不知道如果给你新的题目,你会不会做呢?答案还是不知道。
所以考试题目需要和复习题目有区别。同样的道理,我们用数据生成了决策树,这棵决策树肯定对已见过的数据处理得很完美。可是它能否推广到新的数据上呢?这才是我们真正关心的。就如同在本例中,你的公司关心的,不是以前的贷款该不该贷。而是如何处理今后遇到的新贷款申请。
把数据随机拆分成训练集和测试集,在Python里只需要2条语句就够了。
In [5]:
from sklearn.model_selection import train_test_split #原教程这里需要修改,sklearn.cross_validation该模块在0.18版本中被弃用,支持所有重构的类和函数都被移动到的model_selection模块。 另请注意,新的CV迭代器的接口与本模块的接口不同。 此模块将在0.20中删除。
X_train, X_test, y_train, y_test = train_test_split(X_trans, y, random_state=1)
#我们看看训练数据集和测试集的形状:
print(X_train.shape,X_test.shape)
至此,一切数据准备工作都已就绪。我们开始呼唤Python中的scikit-learn软件包。决策树的模型,已经集成在内。只需要3条语句,直接调用就可以,非常方便。
In [6]:
from sklearn import tree
clf = tree.DecisionTreeClassifier(max_depth=3)
clf = clf.fit(X_train, y_train)
好了,你要的决策树已经生成完了。
就是这么简单。任性吧?
可是,我怎么知道生成的决策树是个什么样子呢?眼见才为实!
这个……好吧,咱们把决策树画出来吧。注意这一段语句内容较多。以后有机会咱们再详细介绍。此处你把它直接抄进去执行就可以了。
见证奇迹的时刻到了:
In [7]:
with open("safe-loans.dot", 'w') as f:
f = tree.export_graphviz(clf,
out_file=f,
max_depth = 3,
impurity = True,
feature_names = list(X_train),
class_names = ['not safe', 'safe'],
rounded = True,
filled= True )
from subprocess import check_call
check_call(['dot','-Tpng','safe-loans.dot','-o','safe-loans.png'])
from IPython.display import Image as PImage
from PIL import Image, ImageDraw, ImageFont
img = Image.open("safe-loans.png")
draw = ImageDraw.Draw(img)
img.save('output.png')
PImage("output.png")
Out[7]:
In [8]:
test_rec = X_test.iloc[1,:]
print('电脑告诉我们,它调查后风险结果是这样的:',clf.predict([test_rec]),'之前提到过,1代表这笔贷款是安全的。实际情况如何呢?我们来验证一下。从测试集目标里面取出对应的标记:',y_test.iloc[1])
In [9]:
#下面我们验证一下,根据训练得来的决策树模型,贷款风险类别判断准确率究竟有多高。
from sklearn.metrics import accuracy_score
accuracy_score(y_test, clf.predict(X_test))
Out[9]:
In [10]:
#模型才61%多的准确率啊,我修改一下,max_depth=4决策树深度为4看看效果
from sklearn import tree
clf2 = tree.DecisionTreeClassifier(max_depth=4)
clf2 = clf2.fit(X_train, y_train)
with open("safe-loans.dot", 'w') as f:
f = tree.export_graphviz(clf2,
out_file=f,
max_depth = 4,
impurity = True,
feature_names = list(X_train),
class_names = ['not safe', 'safe'],
rounded = True,
filled= True )
from subprocess import check_call
check_call(['dot','-Tpng','safe-loans.dot','-o','safe-loans.png'])
from IPython.display import Image as PImage
from PIL import Image, ImageDraw, ImageFont
img = Image.open("safe-loans.png")
draw = ImageDraw.Draw(img)
img.save('output.png')
PImage("output.png")
Out[10]:
In [11]:
#下面我们验证一下,根据max_depth=4决策树深度为4的决策树模型,贷款风险类别判断准确率究竟有多高。
from sklearn.metrics import accuracy_score
accuracy_score(y_test, clf2.predict(X_test))
Out[11]:
才从61%增加到了63%没啥进步啊。。。。。改成5\6\7\8\9\10试试看?要不我1~10全部都做一下试试看
In [12]:
from sklearn import tree
from sklearn.metrics import accuracy_score
clfi=[0]*21
k_range = range(1,20)
test_accuracy = []
for i in k_range:
test_accuracy.append(accuracy_score(y_test, tree.DecisionTreeClassifier(max_depth=i).fit(X_train, y_train).predict(X_test)))
# 然后画图,看运行正确率多少
import matplotlib.pyplot as plt
plt.plot(k_range, test_accuracy)
plt.xlabel("决策树深度")
plt.ylabel("准确率")
plt.show()
In [13]:
from sklearn.neighbors import KNeighborsClassifier
# K=5
knn5 = KNeighborsClassifier(n_neighbors=5)
knn5.fit(X_train, y_train)
y_pred = knn5.predict(X_test)
from sklearn.metrics import accuracy_score
print(accuracy_score(y_test, y_pred))
In [14]:
k_range = range(1, 26)
test_accuracy = []
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
test_accuracy.append(accuracy_score(y_test, y_pred))
# 然后画图,看运行正确率多少
import matplotlib.pyplot as plt
plt.plot(k_range, test_accuracy)
plt.xlabel("Value of K for KNN")
plt.ylabel("Testing Accuracy")
plt.show()
In [15]:
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X_trans, y, random_state=1)
y_train=0.5*(y_train+1) # y输出范围从0到1
y_test=0.5*(y_test+1) # y输出范围从0到1
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
model = Sequential() #建立模型,快速开始序贯(Sequential)模型,序贯模型是多个网络层的线性堆叠,也就是“一条路走到黑”。
model.add(Dense(input_dim = 12, output_dim = 96)) #添加输入层、隐藏层的连接
model.add(Activation('tanh')) #以Tanh函数为激活函数
model.add(Dense(input_dim = 96, output_dim = 48)) #添加隐藏层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dropout(0.1))
model.add(Dense(input_dim = 48, output_dim = 48)) #添加隐藏层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dense(input_dim = 48, output_dim = 36)) #添加隐藏层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dropout(0.15))
model.add(Dense(input_dim = 36, output_dim = 36)) #添加隐藏层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dense(input_dim = 36, output_dim = 36)) #添加隐藏层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dense(input_dim = 36, output_dim = 12)) #添加隐藏层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dense(input_dim = 12, output_dim = 1)) #添加隐藏层、输出层的连接
model.add(Activation('sigmoid')) #以sigmoid函数为激活函数
#编译模型,损失函数为binary_crossentropy(之前是mean_squared_error),用adam法求解
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x_train.values, y_train.values, epochs=170, batch_size = 2000, verbose=False) #训练模型,epochs训练170次
Out[15]:
In [16]:
r = pd.DataFrame(model.predict_classes(x_test.values))
'''
r = pd.DataFrame(model.predict(x_test.values))
rr=r.values
tr=rr.flatten()
for i in range(tr.shape[0]):
if tr[i]>0.5:
tr[i]=1
else:
tr[i]=0
'''
from sklearn.metrics import accuracy_score
print('# 模型评分,正确率:',accuracy_score(y_test,r))
In [17]:
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
#画出模型结构图,并保存成图片
SVG(model_to_dot(model).create(prog='dot', format='svg'))
from keras.utils import plot_model
plot_model(model, to_file='model.png')
In [18]:
y_train.tail()
Out[18]:
In [19]:
y_test.tail()
Out[19]:
In [20]:
model.evaluate(x=x_test.values, y=y_test.values, batch_size=200, verbose=1, sample_weight=None)
Out[20]:
In [21]:
model.metrics_names
Out[21]:
In [ ]: