决策树(下):泰坦尼克乘客生存预测

决策树(下):泰坦尼克乘客生存预测

决策树分类的应用场景有很多,比如在金融行业用决策树做贷款风险评估,医疗行业用决策树生成辅助诊断,用sklearn工具解决泰坦尼克乘客生存预测:

sklearn中的决策树模型

sklearn中自带的决策树分类器DecisionTreeClassifier

clf = DecisionTreeClassifier(criterion='entropy')

在构建DecisionTreeClassifier类时,其中一个参数是criterion,决定了构造的分类树是采用ID3分类是还是CART分类树,对应的取值分别是entropy或者gini,用criterion=‘entropy’,然后打印clf,看下决策树在sklearn:

DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
            splitter='best')

criterion采用不同决策树算法外,一般建议使用默认参数,默认参数不会限制决策树的最大深度,不限制叶子节点数,认为所有分类的权重都相等。

在构造决策树分类器后,使用fit方法让分类器进行拟合,使用predict方法对新数据进行预测,得到预测的分类结果,使用score方法得到分类器的准确率

img

泰坦尼克乘客生存预测

究竟有多少人遇难,可以得到部分数据< https://github.com/cystanford/Titanic_Data >,完整的项目代码见:< https://github.com/cystanford/Titanic_Data/blob/master/titanic_analysis.py >,有两个数据集csv

  • train.csv是训练数据集,包含特征信息和存活与否的标签
  • test.csv测试数据集,只包含特征信息

用决策树分类对训练集进行训练,针对测试集中的乘客进行生存预测,并告知分类器的准确率,训练集中,包括以下字段

img

生存预测的关键流程

对训练集中乘客的生存进行预测,分为两个重要阶段:

  • 准备阶段:首先对训练集、测试集的数据进行探索,分析数据质量,对数据进行清洗,通过特征选择对数据进行降维
  • 分类阶段:首先通过训练集的特征矩阵、分类结果得到决策树分类器,然后将分类器应用于测试集,然后对分类器的准确性进行分析,对决策树模型进行可视化

模块1:数据探索

如何进行数据探索?需要了解一些函数:

  • 使用info()了解数据表的基本情况:行数、列数、每列的数据类型、数据完整度
  • 使用describe()了解数据表的统计情况:总数、平均数、标准差、最小值、最大值
  • 使用describe(include=[‘O’])查看字符串类型(非数字)的整体情况
  • 使用head查看前几行数据
  • 使用tail查看后几行数据
import pandas as pd
# 数据加载
train_data = pd.read_csv('./Titanic_Data/train.csv')
test_data = pd.read_csv('./Titanic_Data/test.csv')
# 数据探索
print(train_data.info())
print('-'*30)
print(train_data.describe())
print('-'*30)
print(train_data.describe(include=['O']))
print('-'*30)
print(train_data.head())
print('-'*30)
print(train_data.tail())

模块2:数据清洗

有些字段数据缺失,比如Age年龄字段,是数值型,可以通过平均值进行补齐,Fare为船票价格,数值型,也可以用其他人购买船票的平均值进行补齐

# 使用平均年龄来填充年龄中的nan值
train_data['Age'].fillna(train_data['Age'].mean(), inplace=True)
test_data['Age'].fillna(test_data['Age'].mean(),inplace=True)
# 使用票价的均值填充票价中的nan值
train_data['Fare'].fillna(train_data['Fare'].mean(), inplace=True)
test_data['Fare'].fillna(test_data['Fare'].mean(),inplace=True)

Cabin为船舱,有大量缺失值,Embarked为登录港口

先观察Embarked的取值print(train_data['Embarked'].value_counts())

结果如下

S 644
C 168
Q 77

Name:Embarked ,dtype:int64

一共3个登录港口,其中S港口最多,因此将其余缺失的Embarked数值设置为S

# 使用登录最多的港口来填充登录港口的nan值
train_data['Embarked'].fillna('S', inplace=True)
test_data['Embarked'].fillna('S',inplace=True)

模块3:特征选择

特征选择是分类器的关键,特征选择不同,得到的分类器也不同

通过数据探索发现,Passengerld为乘客编号,对分类没用,可以放弃;

Name为乘客姓名,对分类没用,放弃;

Cabin字段缺失值太多,放弃;Ticket字段为船票号码,杂乱无章无规律,放弃;其余的字段包含:Pclass、Sex、Age、SibSp、Parch、Fare分别表示了乘客的船票等级、性别、年龄、亲戚数量、船票价格,可能会和乘客的生存预测有关系,具体什么关系,交给分类器处理

将Pclass、Sex、Age等字段作特征,放到特征向量features里

# 特征选择
features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
train_features = train_data[features]
train_labels = train_data['Survived']
test_features = test_data[features]

特征值里有一些是字符串,需要转成数值类型,比如Sex,有male和female两种取值,把它变成Sex = male,和Sex = female两个字段,数值用0或1来表示

同理,Embarked有S,C,O三种可能,三个字段分别是0,1,来表示

使用DictVectorizer类,将可以处理符号化的对象,将符号转成数子0/1来表示

from sklearn.feature_extraction import DictVectorizer
dvec=DictVectorizer(sparse=False)
train_features=dvec.fit_transform(train_features.to_dict(orient='record'))

fit_transform函数可以将特征向量转化为特征值矩阵

dvec在转化后的特征属性是怎样的,即dvec的feature_names_属性值

print(dvec.feature_names_)

[‘Age’, ‘Embarked=C’, ‘Embarked=Q’, ‘Embarked=S’, ‘Fare’, ‘Parch’, ‘Pclass’, ‘Sex=female’, ‘Sex=male’, ‘SibSp’]

原本是一列的Embarked,变成了“Embarked=C”“Embarked=Q”"Embarked=S"三列,Sex列变成了“Sex=female”"Sex=male"两列

模块4:决策树模型

使用ID3算法,即在创建DecisionTreeClassifier时,设置criterion=‘entropy’,使用fit进行训练,将特征值矩阵和分类标识结果作为参数传入得到决策树分类器

from sklearn.tree import DecisionTreeClassifier
# 构造ID3决策树
clf = DecisionTreeClassifier(criterion='entropy')
# 决策树训练
clf.fit(train_features, train_labels)

模块5 :模型预测 & 评估

预测中,需要得到测试集的特征值矩阵,然后使用训练好的决策树clf进行预测,得到预测结果pred_labels:

test_features=dvec.transform(test_features.to_dict(orient='record'))
# 决策树预测
pred_labels = clf.predict(test_features)

决策树提供了score函数可以直接得到准确率,但是不知道真实的预测结果,无法用预测值和真实的预测结果做比较,只能使用训练集中的数据进行模型评估,使用决策树自带的score函数计算:

# 得到决策树准确率
acc_decision_tree = round(clf.score(train_features, train_labels), 6)
print(u'score准确率为 %.4lf' % acc_decision_tree)

score准确率为0.9820

用训练集做训练,再用训练集自身做准确率评估自然很高,但是不能代表决策树分类器的准确率

因为我们没有测试集的实际结果,因此无法用测试集的预测结果与实际结果作对比,如果使用score函数对训练集的准确率进行统计,正确率会接近于100%,无法对分类器的在实际环境下做准确率的评估

如何同居决策树分类器的准确率呢?

使用K折交叉验证方式,交叉验证是一种常用的验证分类准确率的方法,原理是拿出大部分样本进行训练,少量的用于分类器的验证,K折交叉验证就是做K次交叉验证,每次选取K分之一的数据作为验证,其余作为训练,轮流K次,取平均值

K折交叉验证的原理是:

  • 将数据集平均分割成K个等份
  • 使用1份数据作为测试数据,其余作为训练数据
  • 计算测试准确率
  • 使用不同的测试集,重复2,3步骤

在sklearn的model_selection模型选择中提供cross_val_score函数,cross_val_score函数中参数cv代表对原始数据划分成多少份,就是我们的K值,一般建议K值取10,设cv=10,对比下score和cross_val_score两种函数的正确率和评估结果:

import numpy as np
from sklearn.model_selection import cross_val_score
# 使用K折交叉验证 统计决策树准确率
print(u'cross_val_score准确率为 %.4lf' % np.mean(cross_val_score(clf, train_features, train_labels, cv=10)))

cross_val_score准确率为 0.7835

对于不知道测试集实际结果的,使用K折交叉验证才能知道模型的准确率

模块6:决策树可视化

使用Graphviz可视化工具把决策树呈现出来

安装Graphviz库:

1 安装Graphviz工具,下载地址是:< http://www.graphviz.org/download/ >

2 将 Graphviz添加到环境变量PATH中;

3 需要Graphviz库,如果没有可以使用pip install graphviz进行安装

在程序里面使用Graphviz对决策树模型进行呈现得到一个决策树可视化的PDF文件,可视化结果文件Source.gv.pdf在Github上下载:< https://github.com/cystanford/Titanic_Data >

总结:

import pandas as pd
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier

# 数据加载
train_data = pd.read_csv('./train.csv')
test_data = pd.read_csv('./test.csv')
# 数据探索
print(train_data.info())
print('-'*30)
print(train_data.describe())
print('-'*30)
print(train_data.describe(include=['O']))
print('-'*30)
print(train_data.head())
print('-'*30)
print(train_data.tail())
# 数据清洗
# 使用平均年龄来填充年龄中的 nan 值
train_data['Age'].fillna(train_data['Age'].mean(), inplace=True)
test_data['Age'].fillna(test_data['Age'].mean(),inplace=True)
# 使用票价的均值填充票价中的 nan 值
train_data['Fare'].fillna(train_data['Fare'].mean(), inplace=True)
test_data['Fare'].fillna(test_data['Fare'].mean(),inplace=True)
print(train_data['Embarked'].value_counts())

# 使用登录最多的港口来填充登录港口的 nan 值
train_data['Embarked'].fillna('S', inplace=True)
test_data['Embarked'].fillna('S',inplace=True)

# 特征选择
features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
train_features = train_data[features]
train_labels = train_data['Survived']
test_features = test_data[features]

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

# 构造 ID3 决策树
clf = DecisionTreeClassifier(criterion='entropy')
# 决策树训练
clf.fit(train_features, train_labels)

test_features=dvec.transform(test_features.to_dict(orient='record'))
# 决策树预测
pred_labels = clf.predict(test_features)

# 得到决策树准确率
acc_decision_tree = round(clf.score(train_features, train_labels), 6)
print(u'score 准确率为 %.4lf' % acc_decision_tree)

_features, train_labels)

test_features=dvec.transform(test_features.to_dict(orient=‘record’))

决策树预测

pred_labels = clf.predict(test_features)

得到决策树准确率

acc_decision_tree = round(clf.score(train_features, train_labels), 6)
print(u’score 准确率为 %.4lf’ % acc_decision_tree)








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章