前言
前些天学习了一下决策树算法(ID3、C4.5、cart算法),今天实际练习一下。
数据集、测试集地址:
https://github.com/cystanford/Titanic_Data
原始数据:
train.csv 是训练数据集,包含特征信息和存活与否的标签;
test.csv: 测试数据集,只包含特征信息。
我们需要做的,就是使用训练集的数据,构建决策树,然后对测试集数据进行预测。
训练集中的数据特征:
数据分析流程:
接下来我们会按照以上这6个步骤,去对泰坦尼克号乘客进行生存预测。
数据探索:
数据探索,其实就是对现有数据进行分析。比如行数、列数、数据完整度等。
进行数据探索,你需要知道如下几个函数:
使用info()查看数据表的基本信息:行数、列数、每列的数据类型、数据完整度;
使用describe()了解数据表的统计情况:总数、平均值、标准值、最小值、最大值等;
使用describe(include=['0'])查看字符串(非数字)类型的整体情况
使用head查看前几行数据(默认5行)
使用tail查看后几行数据(默认后5行)
接下来我们执行一下这些命令
import pandas as pd # 数据加载 train_data = pd.read_csv('../niki/train.csv')
info()查看数据表基本信息
# 数据探索 print(train_data.info())
可以看到它展示了:行数、数据完整度、数据类型、字段名、数据类型数、内存使用情况。
describe()查看数据表的统计信息:
# 数据探索 print(train_data.describe())
可以看出,它展示的依次是:数据量、平均值、标准差、最小值、还有25%、50%、75%所含的数据、最大值
上面的输出结果只展示了部分数据,如果想展示全部的数据,只需要在describe方法执行之前,加上上面两句指令即可:
# 显示所有列 pd.set_option('display.max_columns', None) # 显示所有行 pd.set_option('display.max_rows', None)
describe(include=['0'])查看字符串类型整体情况:
# 数据探索 print(train_data.describe(include=['O']))
展示了数据的数量,有多少数据是不等的,出现数量最多的数据是什么,出现了几次。
head tail查看数据的前几行和后几行:
这两条命令和linux查看文件的命令是一样的。
# 数据探索 print(train_data.head()) print('-'*50) print(train_data.tail())
数据清洗:
我们对训练集和测试集中的数据进行探索,可以得知:
Age、Fare、Cabin、Embarked存在缺失,Age数值型,代表年龄。我们可以用平均值补齐,Fare是船票价格,同理。
# 数据清洗 train_data['Age'].fillna(train_data['Age'].mean(), inplace=True) test_data['Age'].fillna(test_data['Age'].mean(), inplace=True) train_data['Fare'].fillna(train_data['Fare'].mean, inplace=True) test_data['Fare'].fillna(test_data['Fare'].mean, inplace=True)
Cabin为船舱信息,由于训练集和测试集中有大量的缺失数据,所以无法进行补齐。
Embarked是港口信息,我们可以使用value_counts()方法进行观察:
print(train_data['Embarked'].value_counts())
发现S的占比超过了70%,所以我们可以用s值进行补齐
train_data['Embarked'].fillna('S', inplace=True) test_data['Embarked'].fillna('S', inplace=True)
特征选择:
通过数据探索,我们可以发现PassengerId为乘客的编号,对分类没有作用,可以舍弃,Name为乘客姓名,也可以舍弃,Cabin缺失值太多,可以舍弃,Ticket为船票号码,杂乱无章,可以舍弃,剩余的字段包括:Pclass、Sex、Age、SibSp、Parch 和 Fare,这些属性分别表示了乘客的船票等级、性别、年龄、亲戚数量以及船票价格,可能会和乘客的生存预测分类有关系。
我们现将这些值放到特征向量里:
# 特征选择 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 来表示。我们可以用klearn 特征选择中的 DictVectorizer 类进行上述操作:
from sklearn.feature_extraction import DictVectorizer dvec = DictVectorizer(sparse=False) train_features = dvec.fit_transform(train_features.to_dict(orient='record'))
fit_transfrom可以将特征向量转换成特征矩阵,然后我们可以通过查看dvec的feature_name_属性来获取特征值。
这样我们就得到了一个10个特征值,891个样本的10列的特征矩阵。
决策树模型:
我们可以使用ID3算法构建决策树,即创建DecisionTreeClassifier的时候,设置criterion='entropy'
from sklearn.tree import DecisionTreeClassifier # 构造ID3决策树 clf = DecisionTreeClassifier(criterion='entropy') # 决策树训练 clf.fit(train_features, train_labels)
模型的预测 & 评估:
我们首先应该得到测试集的特征矩阵,然后使用训练好的clf树进行预测。
test_features=dvec.transform(test_features.to_dict(orient='record')) # 决策树预测 pred_labels = clf.predict(test_features)
在模型评估中,我们可以使用决策树的score函数得到准确率,但是由于我们不知道测试集中的结果,所以我们这里使用训练集的数据,进行一下预测。
但是这么做显然是不准确的,因为我们的决策树是通过训练集数据构建出来的。所以它的正确率会趋近于100%,那么有没有什么方法可以在不知道测试机数据结果的时候,来统计决策树的准确率呢?
这里就会使用k折交叉验证的方式。
- K折交叉验证是这样的,我们将整个训练集分成k等份
- 使用其中的1份作为测试数据,其余的数据作为训练数据
- 计算测试数据的准确性
- 使用不同的训练集重复2、3动作
sklearn的model_selection模型中,就提供了用于k折交叉验证的函数,cross_val_score,参数cv代表将原始数据划分成多少份。
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)))
可以看出,结果差异还是比较大的
决策树可视化:
我们可以用Grapviz进行决策树的可视化:
import graphviz from sklearn import tree # 决策树可视化 dot_data = tree.export_graphviz(clf, out_file=None) graph = graphviz.Source(dot_data) graph.view()