7.1 实验介绍
实验准备
请到07 titanic文件目录下开始实验。
实验背景
1912年,泰坦尼克号在第一次航行中就与冰山相撞沉没,导致了大部分乘客和船员身亡。在这个项目中,我们将探索部分泰坦尼克号旅客名单,来确定哪些特征可以最好地预测一个人是否会生还。
为了完成这个项目,你将需要实现几个基于条件的预测并回答下面的问题。我们将根据代码的完成度和对问题的解答来对你提交的项目的进行评估。
7.2 获取数据
当我们开始处理泰坦尼克号乘客数据时,会先导入我们需要的功能模块以及将数据加载到 pandas
DataFrame。运行下面区域中的代码加载数据,并使用 .head()
函数显示前几项乘客数据。
模块导入
#
导入此项目所需要的库
import numpy as np
import pandas as pd
from IPython.display import display #
允许
DataFrame
使用
display()
import matplotlib as mpl
import visuals as vs #
导入可视化补充代码
visuals.py
#
在笔记中更好的显示图形
%matplotlib inline
#
设置
matplotlib
中文显示
mpl.rcParams['font.family'] = 'SimHei'
mpl.rcParams['axes.unicode_minus'] = False
获取数据
#
引入数据
try:
in_file = 'titanic_data.csv'
full_data = pd.read_csv(in_file)
print('
泰坦尼克数据集有
{}
个样本,每个样本有
{}
个特征。
'.format(
*full_data.shape))
#
显示数据列表中的前几个乘客的数据
display(full_data.head())
except:
print('
数据集无法加载,数据集丢失了吗?
')
泰坦尼克数据集有 891 个样本,每个样本有 12 个特征。
7.3 数据介绍
从泰坦尼克号的数据样本中,我们可以看到船上每位旅客的特征
- Survived:是否存活
-
- 0 代表否
- 1 代表是
- Pclass:社会阶级
-
- 1 代表上层阶级
- 2代表中层阶级
- 3 代表底层阶级
- Name:船上乘客的名字
- Sex:船上乘客的性别
- Age:船上乘客的年龄
-
- 可能存在 NaN
- SibSp:乘客在船上的兄弟姐妹和配偶的数量
- Parch:乘客在船上的父母以及小孩的数量
- Ticket:乘客船票的编号
- Fare:乘客为船票支付的费用
- Cabin:乘客所在船舱的编号
-
- 可能存在 NaN
- Embarked:乘客上船的港口
-
- C 代表从 Cherbourg 登船
- Q 代表从 Queenstown 登船
- S 代表从 Southampton 登船
下一步
7.4 预测生还率
因为我们感兴趣的是每个乘客或船员是否在事故中活了下来。可以将 Survived 这一特征从这个数据集移除,并且用一个单独的变量 outcomes
来存储。它也做为我们要预测的目标。
运行该代码,从数据集中移除 Survived 这个特征,并将它存储在变量 outcomes
中。
#
从数据集中移除
'Survived'
这个特征,并将它存储在一个新的变量中。
outcomes = full_data['Survived']
data = full_data.drop('Survived', axis = 1)
#
显示已移除
'Survived'
特征的数据集
display(data.head(10))
这个例子展示了如何将泰坦尼克号的 Survived 数据从 DataFrame 移除。注意到 乘客数据 data
和 是否存活 outcomes
现在已经匹配好。这意味着对于任何乘客的 data.loc[i]
都有对应的存活的结果 outcome[i]
。
为了验证我们预测的结果,我们需要一个标准来给我们的预测打分。因为我们最感兴趣的是我们预测的准确率,既正确预测乘客存活的比例。运行下面的代码来创建我们的 accuracy_score
函数以对前五名乘客的预测来做测试。
思考:从第六个乘客算起,如果我们预测他们全部都存活,你觉得我们预测的准确率是多少?
def accuracy_score(truth, pred):
'''
返回输入数据的真实值和预测值的准确分数。
'''
#
确保预测的数量与结果的数量相匹配
if len(truth) == len(pred):
#
计算并返回一个百分比的准确度
return '
预测准确率为
{:.2f}%
。
'.format((truth == pred).mean()*100)
else:
return '
预测数量与结果数量不匹配!
'
#
测试
'accuracy_score()'
函数
predictions = pd.Series(np.ones(5, dtype=int))
print(accuracy_score(outcomes[:5], predictions))
预测准确率为 60.00% 。
预测
如果我们要预测泰坦尼克号上的乘客是否存活,但是我们又对他们一无所知,那么最好的预测就是船上的人无一幸免。这是因为,我们可以假定当船沉没的时候大多数乘客都遇难了。下面的 predictions_0
函数就预测船上的乘客全部遇难。
def predictions_0(data):
'''
没有功能的模型,总是预测没有一个乘客生存。
'''
predictions = []
for _, passenger in data.iterrows():
#
预测
'passenger'
的生还率
predictions.append(0)
#
返回预测结果
return pd.Series(predictions)
#
进行预测
predictions = predictions_0(data)
对比真实的泰坦尼克号的数据,如果我们做一个所有乘客都没有存活的预测。
运行下面的代码来查看预测的准确率。
print(accuracy_score(outcomes, predictions))
我们可以使用 survival_stats
函数来看看 Sex 这一特征对乘客的存活率有多大影响。这个函数定义在名为 visuals.py
的 Python 脚本文件中,我们的项目提供了这个文件。传递给函数的前两个参数分别是泰坦尼克号的乘客数据和乘客的生还结果。第三个参数表明我们会依据哪个特征来绘制图形。
运行下面的代码绘制出依据乘客性别计算存活率的柱形图。
观察泰坦尼克号上乘客存活的数据统计,我们可以发现大部分男性乘客在船沉没的时候都遇难了。相反的,大部分女性乘客都在事故中生还。让我们在先前推断的基础上继续创建:如果乘客是男性,那么我们就预测他们遇难;如果乘客是女性,那么我们预测他们在事故中活了下来。
def predictions_1(data):
'''
具有两种功能的模型:
-
如果一名乘客是女性,则可预测其幸免于难。
'''
predictions = []
for _, passenger in data.iterrows():
#
移除下方的
'pass'
声明
#
输入你自己的预测条件
if passenger['Sex'] == 'male':
predictions.append(0)
else:
predictions.append(1)
#
返回预测结果
return pd.Series(predictions)
#
进行预测
predictions = predictions_1(data)
当我们预测船上女性乘客全部存活,而剩下的人全部遇难。
运行下面的代码来查看我们预测的准确率。
print(accuracy_score(outcomes, predictions))
预测准确率为 78.68% 。
仅仅使用乘客性别(Sex)这一特征,我们预测的准确性就有了明显的提高。现在再看一下使用额外的特征能否更进一步提升我们的预测准确度。例如,综合考虑所有在泰坦尼克号上的男性乘客:我们是否找到这些乘客中的一个子集,他们的存活概率较高。让我们再次使用 survival_stats
函数来看看每位男性乘客的年龄(Age)。这一次,我们将使用第四个参数来限定柱形图中只有男性乘客。
运行下面这段代码,把男性基于年龄的生存结果绘制出来。
vs.survival_stats(data, outcomes, 'Age', ["Sex == 'male'"])
仔细观察泰坦尼克号存活的数据统计,在船沉没的时候,大部分小于10岁的男孩都活着,而大多数10岁以上的男性都随着船的沉没而遇难。让我们继续在先前预测的基础上构建:如果乘客是女性,那么我们就预测她们全部存活;如果乘客是男性并且小于10岁,我们也会预测他们全部存活;所有其它我们就预测他们都没有幸存。
def predictions_2(data):
'''
具有两种功能的模型:
-
如果一名乘客是女性,则可预测其幸免于难。
-
如果一名乘客是男性,而且年龄小于
10
岁,则可预测其幸免于难。
'''
predictions = []
for _, passenger in data.iterrows():
#
移除下方的
'pass'
声明
#
输入你自己的预测条件
if passenger['Sex'] == 'female':
predictions.append(1)
else:
if passenger['Age'] < 10:
predictions.append(1)
else:
predictions.append(0)
#
返回预测结果
return pd.Series(predictions)
#
进行预测
predictions = predictions_2(data)
当预测所有女性以及小于10岁的男性都存活的时候。
运行下面的代码来查看预测的准确率。
print(accuracy_score(outcomes, predictions))
预测准确率为 79.35% 。
添加年龄(Age)特征与性别(Sex)的结合比单独使用性别(Sex)也提高了不少准确度。现在该你来做预测了:找到一系列的特征和条件来对数据进行划分,使得预测结果提高到80%以上。这可能需要多个特性和多个层次的条件语句才会成功。你可以在不同的条件下多次使用相同的特征。Pclass,Sex,Age,SibSp 和 Parch 是建议尝试使用的特征。
使用 survival_stats
函数来观测泰坦尼克号上乘客存活的数据统计。
vs.survival_stats(data, outcomes, 'SibSp', ["Sex == 'female'"])
当查看和研究了图形化的泰坦尼克号上乘客的数据统计后,请补全下面这段代码中缺失的部分,使得函数可以返回你的预测。
在到达最终的预测模型前请确保记录你尝试过的各种特征和条件。
def predictions_3(data):
'''
具有多种功能的模型:
-
要求预测准确度至少到达
80
%。
'''
predictions = []
for _, passenger in data.iterrows():
#
移除下方的
'pass'
声明
#
输入你自己的预测条件
if passenger['Sex'] == 'female':
if passenger['SibSp'] >=3:
predictions.append(0)
else:
predictions.append(1)
else:
if passenger['Age'] < 10:
predictions.append(1)
else:
predictions.append(0)
#
返回预测结果
return pd.Series(predictions)
#
进行预测
predictions = predictions_3(data)
print(accuracy_score(outcomes, predictions))
预测准确率为 80.36% 。
下一步
7.5 结论
经过了数次对数据的探索和分类,你创建了一个预测泰坦尼克号乘客存活率的有用的算法。在这个项目中你手动地实现了一个简单的机器学习模型——决策树(decision tree)。决策树每次按照一个特征把数据分割成越来越小的群组(被称为 nodes)。每次数据的一个子集被分出来,如果分割结果的子集中的数据比之前更同质(包含近似的标签),我们的预测也就更加准确。电脑来帮助我们做这件事会比手动做更彻底,更精确。这个链接提供了另一个使用决策树做机器学习入门的例子。
决策树是许多监督学习算法中的一种。在监督学习中,我们关心的是使用数据的特征并根据数据的结果标签进行预测或建模。也就是说,每一组数据都有一个真正的结果值,不论是像泰坦尼克号生存数据集一样的标签,或者是连续的房价预测。
结束当前小节