接下来我们开始使用决策树来预测泰坦尼克号的辛存者名单。
其中的数据集是在kaggle上下载的taitanic的训练数据集。
以下一些特征为此人是否幸存做出了贡献。
PassengerId:乘客的ID号,这是个顺序编号,用来唯一地标识一名乘客。这个特征和幸存与否无关,不使用这个特征。
Survived:1 表示幸存,0 表示遇难。这是我们标注的数据
Pclass:仓位等级,是很重要的特征。高仓位等级的乘客能更快地到达甲板,从而更容易获救
Name:乘客名字,这个特征和幸存与否无关,丢弃
Sex:乘客性别,船长让妇女和儿童先上,很重要的特征
Age:乘客年龄,儿童会优先上船
SibSp:兄弟姐妹同在船上的数量
Parch:同船的父辈人员数量
Ticket:乘客票号,不使用这个特征
Fare:乘客体热指标
Cabin:乘客所在的船舱号。实际上这个特征和幸存与否有一定关系,比如最早被水淹没的船舱位置,其乘客的幸存概率要低一些。但由于这个特征由大量丢失数据,所以丢弃这个特征
Embarked:乘客登船的港口,需要把港口数据转换为数值型数据
但是这些特征里面有一些特征是没用的,所以我们把它删除掉,以此来减少数据的运算。
import pandas as pd
def read_dataset(fname):#定义读取数据函数
data=pd.read_csv('train.csv')#读取csv数据
data.drop(['Name','Ticket','Cabin'],axis=1,inplace=True)#删除‘’Name','Ticket','Cabin'这三个数据
data['Sex']=(data['Sex']=='male').astype('int')#将性别转换为0,1
labels=data['Embarked'].unique().tolist()#港口号转换为int,将unique转换成list,
data['Embarked']=data['Embarked'].apply(lambda n:labels.index(n))#使用索引进行数字替换
data=data.fillna(0)#填充缺失数据
return data
train=read_dataset('train.csv')#获得一个(891, 8)的数据集
以下代码块是进行数据集的划分
from sklearn.model_selection import train_test_split
y=train['Survived'].values#获取到最后是否幸存到y
X=train.drop(['Survived'],axis=1).values#获取到最后除是否幸存的其他数据到X
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2)#划分数据集,20%给test集
print('trian dataset:{0};test dataset:{1}'.format(X_train.shape,X_test.shape))
输出如下:
train dataset:(712, 7);test dataset:(179, 7);
以下代码块是训练模型
from sklearn.tree import DecisionTreeClassifier
clf=DecisionTreeClassifier()#声明决策树模型
clf.fit(X_train,y_train)#将X_train,y_train扔进决策树模型
train_score=clf.score(X_train,y_train)#train分数
test_score=clf.score(X_test,y_test)#test分数
print('train score:{0};test score:{1}'.format(train_score,test_score))#输出
输出如下:
train score:0.9831460674157303;test score:0.7653631284916201;
我们可以清楚的看到train集的测试分数有0,98,但是test集的分数却只有0.76。明显的过拟合状态。
因此我们要进行模型的深度修改。就是说进行多次决策树的深度替换,并测试,得出效果最好的那个。
def cv_score(d):#这个函数就是生成深度为d的决策树模型,返回train分和test分数
clf=DecisionTreeClassifier(max_depth=d)
clf.fit(X_train,y_train)
tr_score=clf.score(X_train,y_train)
cv_score=clf.score(X_test,y_test)
return (tr_score,cv_score)
以下代码块,就是使用不同深度的决策树模型,训练测试得到最好的
import numpy as np
depths=range(2,15)#深度范围:2,到15
scores=[cv_score(d) for d in depths]#将获得的分数放入scores数组中
tr_scores=[s[0] for s in scores]#获取不同深度的训练分数集
cv_scores=[s[1] for s in scores]#获取不同深度的测试分数集
best_score_index=np.argmax(cv_scores)#找到测试分数最高的索引
best_score=cv_scores[best_score_index]#获取到测试分数最高的那个
best_param=depths[best_score_index]#获取到对应的深度
print('best param:{0};best score:{1};'.format(best_param,best_score))#输出
输出如下:
best param:9;best score:0.8379888268156425
我们可以看出其中最好的模型深度为9,最高的分数为0.8379888268156425,
但是这只是笔者的电脑上得出的数据,出现不同也有可能。
import matplotlib.pyplot as plt
plt.figure(figsize=(7,4),dpi=144)
plt.grid()#画格子
plt.xlabel('max depth of decision tree')
plt.ylabel('score')
plt.plot(depths,cv_scores,'.g-',label='cross-validation score')
plt.plot(depths,tr_scores,'.r--',label='training score')
plt.legend()
输出如下:
这是不同深度的决策树模型的训练集和测试集的对比参数
以下代码块则是指定信息熵或者是基尼不纯度的阀值,当决策树分裂后,其信息增益低于这个阀值时,则不再分裂。
其实就是测试不同阀值下的决策树模型的性能
def cv_score(val):
clf=DecisionTreeClassifier(criterion='gini',min_impurity_split=val)#criterion='gini'的意思是使用 “基尼系数” 方式划分节点数据集
#min_impurity_split=val的意思是树生长过程中早停止的阈值。如果当前节点的不纯度高于阈值,节点将分裂,否则它是叶子节点
clf.fit(X_train,y_train)
tr_score=clf.score(X_train,y_train)
cv_score=clf.score(X_test,y_test)
return (tr_score,cv_score)
values=np.linspace(0,0.5,50)#0到0.5之间取50个数
scores=[cv_score(v) for v in values]#训练模型,并获取分数,剩下的跟上两个代码块基本一样,不做过多解释
tr_scores=[s[0] for s in scores]
cv_scores=[s[1] for s in scores]
best_score_index=np.argmax(cv_scores)
best_score=cv_scores[best_score_index]
print('best param:{0};best score:{1}'.format(best_param,best_score))
plt.figure(figsize=(6,4),dpi=144)
plt.grid()
plt.xlabel('threshold of entropy')
plt.ylabel('score')
plt.plot(values,cv_scores,'.g-',label='cross_validation score')
plt.plot(values,tr_scores,'.r--',label='training score')
plt.legend()