使用决策树方法对泰坦尼克号数据进行预测和分类。

一、实验目的

(1) 熟悉和掌握信息熵的概念和定义;
(2) 掌握决策树分类方法
(3) 使用决策树方法对泰坦尼克号数据进行预测和分类。

二、实验内容

(1)导入数据集
(2)数据清洗:
① 删除对分类无帮助的特征
② 将某些字符串特征数值化
③ 填补缺失值或删除
(3)用sklearn默认参数生成棵普通的决策树,查看评分
(4) 调整参数,得到最优的参数并生成最终的树
(5)画出决策树

三、实验代码

#代码一
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sklearn
from sklearn import datasets
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.feature_extraction import DictVectorizer

from sklearn import tree
import warnings
warnings.filterwarnings('ignore')

train_data = pd.read_csv('titanic_train.csv')
test_data = pd.read_csv('titanic_test.csv')
print('训练集:')
print(train_data)
train_data.info()
print('测试集:')
print(test_data)
test_data.info()

#数据清洗
#训练集
train_data['Age'].fillna(train_data['Age'].mean(),inplace = True)#在缺失的Age值中填入Age平均值
print('登陆口岸的情况:')
print(train_data['Embarked'].value_counts())#打印登陆口岸的情况
train_data['Embarked'].fillna('S',inplace = True)#用占比最多的登陆口岸'S'对缺失数据进行填充
train_data.pop("PassengerId")
train_data.pop("Name")
train_data.pop("SibSp")
train_data.pop("Parch")
train_data.pop("Ticket")
train_data.pop("Cabin")
train_data=train_data.dropna()#去掉含有NA的行
#测试集
test_data['Age'].fillna(test_data['Age'].mean(),inplace = True)
test_data['Fare'].fillna(test_data['Fare'].mean(),inplace = True)
test_data.pop("PassengerId")
test_data.pop("Name")
test_data.pop("SibSp")
test_data.pop("Parch")
test_data.pop("Ticket")
test_data.pop("Cabin")
test_data=test_data.dropna()#去掉含有NA的行
#特征选择
features = ['Pclass','Sex','Age','Fare','Embarked']
train_features = train_data
train_labels = train_data.pop('Survived')
test_features = test_data

def sex(x):
    if x=="male":
        return 0
    else:
        return 1
train_data["Sex"]=train_data["Sex"].apply(lambda x:sex(x))
test_data["Sex"]=test_data["Sex"].apply(lambda x:sex(x))
print('train_data["Sex"]',train_data["Sex"])
print('test_data["Sex"]',test_data["Sex"])
def Embarked(x):
    if x=="S":
        return 0
    if x=="C":
        return 1
    if x=="Q":
        return 2

train_data["Embarked"]=train_data["Embarked"].apply(lambda x:Embarked(x))
test_data["Embarked"]=test_data["Embarked"].apply(lambda x:Embarked(x))
print('train_data["Embarked"]',train_data["Embarked"])
print('test_data["Embarked"]',test_data["Embarked"])

print('训练集:')
train_data.info()
print('测试集:')
test_data.info()

from sklearn.model_selection import GridSearchCV #网格搜索
#定义参数及取值范围
tree_param_grid={'max_depth':list((3,4,5,6,7))
                 ,'min_samples_split':list((2,4,6,8))}
#构建模型(选择要选择的模型,选择参数集,选择交叉验证的CV)
grid=GridSearchCV( DecisionTreeClassifier(),param_grid=tree_param_grid,cv=5) #cv表示把训练集分成几段,取其中一段作为测试集。产生的组合有5种
grid.fit(train_features, train_labels)
means = grid.cv_results_['mean_test_score'] #获取每个方案的分数均值
std=grid.cv_results_['std_test_score'] #获得分数的标准差
params = grid.cv_results_['params'] #获取参数组合
#输出参数组合
for mean,std,param in zip(means,std,params):
    print("mean: %f std: %f with: %r" % (mean,std,param))
#输出最优的参数以及最优的分数
print(grid.best_params_,grid.best_score_)


print('预测决策树的准确率:')
clf= DecisionTreeClassifier(criterion='entropy'
                            ,max_depth=grid.best_params_['max_depth']
                            ,min_samples_split=grid.best_params_['min_samples_split']
                            )
clf.fit(train_features,train_labels) # 使用训练集训练模型
score = clf.score(train_features,train_labels)
print(score)


#决策树可视化
import graphviz
dot_data = tree.export_graphviz(clf
                                ,feature_names=features
                                ,class_names=['0','1']
                                ,filled=True
                                ,rounded=True
                                )
graph=graphviz.Source(dot_data)
graph.view()

#导出预测结果
pred_labels = clf.predict(test_features)
test_data['Survived'] = pred_labels
test_data.to_csv('submission.csv')

#代码二
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sklearn
from sklearn import datasets
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.feature_extraction import DictVectorizer

from sklearn import tree
import warnings
warnings.filterwarnings('ignore')

train_data = pd.read_csv('titanic_train.csv')
test_data = pd.read_csv('titanic_test.csv')
print('训练集:')
print(train_data)
train_data.info()
print('测试集:')
print(test_data)
test_data.info()

train_data['Age'].fillna(train_data['Age'].mean(),inplace = True)#在缺失的Age值中填入Age平均值
print('登陆口岸的情况:')
print(train_data['Embarked'].value_counts())#打印登陆口岸的情况
train_data['Embarked'].fillna('S',inplace = True)#用占比最多的登陆口岸'S'对缺失数据进行填充
test_data['Age'].fillna(test_data['Age'].mean(),inplace = True)
test_data['Fare'].fillna(test_data['Fare'].mean(),inplace = True)


#特征选择
features = ['Age','Embarked','Fare','Pclass','Sex']
train_features = train_data[features]
train_labels = train_data.pop('Survived')
test_features = test_data[features]

dv = DictVectorizer(sparse = False)
train_features = dv.fit_transform(train_features.to_dict(orient= 'record'))
print(dv.feature_names_)

clf= DecisionTreeClassifier(criterion='entropy')
clf.fit(train_features,train_labels) # 使用训练集训练模型

from sklearn.model_selection import GridSearchCV #网格搜索
#定义参数及取值范围
tree_param_grid={'max_depth':list((3,4,5,6,7))
                 ,'min_samples_split':list((2,4,6,8))}
#构建模型(选择要选择的模型,选择参数集,选择交叉验证的CV)
grid=GridSearchCV( DecisionTreeClassifier(),param_grid=tree_param_grid,cv=5) #cv表示把训练集分成几段,取其中一段作为测试集。产生的组合有5种
grid.fit(train_features, train_labels)
means = grid.cv_results_['mean_test_score'] #获取每个方案的分数均值
std=grid.cv_results_['std_test_score'] #获得分数的标准差
params = grid.cv_results_['params'] #获取参数组合
#输出参数组合
for mean,std,param in zip(means,std,params):
    print("mean: %f std: %f with: %r" % (mean,std,param))
#输出最优的参数以及最优的分数
print(grid.best_params_,grid.best_score_)


print('预测决策树的准确率:')
clf= DecisionTreeClassifier(criterion='entropy'
                            ,max_depth=grid.best_params_['max_depth']
                            ,min_samples_split=grid.best_params_['min_samples_split']
                            )
clf.fit(train_features,train_labels) # 使用训练集训练模型
score = clf.score(train_features,train_labels)
print(score)


#决策树可视化
import graphviz
dot_data = tree.export_graphviz(clf
                                ,feature_names=['Age','Embarked=C','Embarked=Q','Embarked=S','Fare','Pclass','Sex=female','Sex=female']
                                ,class_names=['0','1']
                                ,filled=True
                                ,rounded=True
                                )
graph=graphviz.Source(dot_data)
graph.view()

#导出预测结果
test_features = dv.transform(test_features.to_dict(orient= 'record'))
pred_labels = clf.predict(test_features)
test_data['Survived'] = pred_labels
test_data.to_csv('submission.csv')

四、实验结果与分析

一、在导入训练集数据和测试集数据后我们可以看到数据统计情况及其整体情况。
在这里插入图片描述
在这里插入图片描述
二、通过这些数据,我们发现可以看到Age、Cabin、Fare、Embarked是有缺失数据的。此时,我们用平均年龄来填充Age中的空值,用平均票价来填充Fare中的空值,用登陆人数最多的口岸’S’来填充Embarked中的空值。
在这里插入图片描述
三、对于sex及Embarked的符号化的特征转化为数字我们参考了两种方法。
①实验代码一所示,我们利用sex(x)和Embarked(x)函数对数据进行处理。我们可以看到处理后的数据情况。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
②实验代码二所示,我们利用sklearn 特征选择中的 DictVectorizer类,用它可以处理符号化的对象,将符号转化为数字0或1进行表示。显示其属性情况。
在这里插入图片描述
四、下一步就是利用网格搜索来调整最优参数。我们用最大深度和叶子节点中包含样本最小个数作为调整参数,选择交叉验证的cv。通过训练,我们可以得到每个方案的分数均值、标准差、参数组合。在最后显示最优参数组合并输出最优分数。
①特征值选择为features=[‘Pclass’,‘Sex’,‘Age’,‘Fare’,‘Embarked’]
在这里插入图片描述

②特征值选择为features=[ ‘PassengerId’,‘Pclass’,‘Sex’,‘Age’,‘Fare’,‘Embarked’]时在这里插入图片描述
③特征值选择为features = [‘SibSp’,‘Pclass’,‘Sex’,‘Age’,‘Fare’,‘Embarked’]时在这里插入图片描述
④当特征值选择为features = [‘Parch’,‘Pclass’,‘Sex’,‘Age’,‘Fare’,‘Embarked’]在这里插入图片描述

⑤当特征值选择为features = [‘Pclass’,‘Sex’,‘Age’,‘Embarked’]时
在这里插入图片描述
⑥当特征值选择为features = [‘Sex’,‘Age’,‘Embarked’]时在这里插入图片描述
⑦当特征值选择为features = [‘PassengerId’,‘SibSp’,‘Parch’,‘Pclass’,‘Sex’,‘Age’,‘Fare’,‘Embarked’]时

在这里插入图片描述
通过此图我们可以发现,其准确率受到特征值选择的影响,并不是特征值越多准确率越高,我们要选择合适的特征。我们还发现并不是深度越深其预测准确率就越高,合适的最大深度和叶子节点中包含样本最小个数其正确率才高。训练存在剪枝的问题。只有进行了合适的剪枝,我们才能提高准确率。
五、此时,我们得到了最优参数组合。利用字典中的最优参数构造决策树,得出其决策树的图像。
在这里插入图片描述

  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值