跳至主要内容

Kaggle 教程:EDA 与机器学习

在本次 Kaggle 教程中,您将学习如何结合泰坦尼克号数据进行探索性数据分析(EDA),以构建监督学习模型。
· 10分钟 阅读

使用 AI 探索

本月早些时候,我在 Facebook 做了一场 Live Code Along 活动,我(以及一起跟着编程的同学们)基于乘客所支付的票价、登船地点、年龄等信息,构建了多个难度逐步提升的算法,用于预测泰坦尼克号上的任意一名乘客是否幸存。

在本文中,您将回顾本次活动中涉及的一些要点。如果您想回看或边看视频边阅读本文,可在此观看:

特别是,您可能还记得我们构建的是监督学习模型。

监督学习是机器学习(ML)的一个分支,目标是预测诸如“幸存”或“未幸存”之类的标签。这类模型从带标签的数据中学习,也就是包含乘客是否幸存信息的数据(称为“模型训练”),然后再对未标注的数据进行预测。

在 Kaggle(一个用于预测建模与分析竞赛的平台)上,这些数据被称为训练集和测试集,因为

  • 您需要用训练集来学习其中的模式,且
  • 随后用模型在测试集上进行预测。

随后 Kaggle 会告诉您预测正确的百分比:这就是模型的准确率。

如何开始监督学习

您可能已经知道,一个不错的入手方式是:

  • 对数据集进行探索性数据分析(EDA);
  • 先构建一个“快速粗略”的模型或基线模型,作为之后模型的对比参照;
  • 循环迭代:做更多 EDA,并再构建一个模型;
  • 进行特征工程:对已有特征进行组合或提取更多信息,最终达成最后一点,即
  • 获得表现更好的模型。

在这次跟练中,您已经或即将完成以上所有步骤!

注意:我们也有课程可帮助您用 Python 和 R 在泰坦尼克号数据集上快速上手机器学习。

导入数据并快速查看

第一步通常是导入数据,快速浏览您要处理的数据。在这里,您将导入 pandas 包并使用 read_csv() 函数读取数据:

注意:下面的代码块中,matplotlib、sklearn 和 seaborn 等包(及其子模块)已被导入。稍后您将更多地将它们用于(统计)数据可视化和机器学习!

您还将使用 IPython 魔法命令 %matplotlib inline 以便在笔记本中内联显示图表。同时添加 sns.set() 将可视化风格设置为 Seaborn 的基础样式:

# Import modules
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import tree
from sklearn.metrics import accuracy_score

# Figures inline and set visualization style
%matplotlib inline
sns.set()

事不宜迟,先导入数据,并迈出检查数据的第一步:

# Import test and train datasets
df_train = pd.read_csv('../data/train.csv')
df_test = pd.read_csv('../data/test.csv')

# View first lines of training data
df_train.head(n=4)
 PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S

如果您想了解这些特征分别代表什么,请查看 Kaggle 的数据文档这里。

在继续之前,术语方面有几点需要注意:

  • 目标变量(target variable)是您要预测的变量;
  • 其他变量称为“特征”(或“自变量/预测变量”,即用于预测目标变量的那些特征)。

牢记这一点,您可以继续用例如 head() 函数来查看数据集的前五行:

# View first lines of test data
df_test.head()
 PassengerIdPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
08923Kelly, Mr. Jamesmale34.5003309117.8292NaNQ
18933Wilkes, Mrs. James (Ellen Needs)female47.0103632727.0000NaNS
28942Myles, Mr. Thomas Francismale62.0002402769.6875NaNQ
38953Wirz, Mr. Albertmale27.0003151548.6625NaNS
48963Hirvonen, Mrs. Alexander (Helga E Lindqvist)female22.011310129812.2875NaNS

请注意,df_test DataFrame 不包含 'Survived' 列,因为这正是您要预测的!

  • 您还可以使用 DataFrame 的 .info() 方法来查看数据类型、缺失值等信息(针对 df_train)。
df_train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

在这里,您会看到 DataFrame 共 891 行,而“Age”列只有 714 个非空值。这意味着有 177 个空值或缺失值。

  • 也可使用 DataFrame 的 .describe() 方法查看数值列(df_train)的汇总统计。
df_train.describe()
 PassengerIdSurvivedPclassAgeSibSpParchFare
count891.000000891.000000891.000000714.000000891.000000891.000000891.000000
mean446.0000000.3838382.30864229.6991180.5230080.38159432.204208
std257.3538420.4865920.83607114.5264971.1027430.80605749.693429
min1.0000000.0000001.0000000.4200000.0000000.0000000.000000
25%223.5000000.0000002.00000020.1250000.0000000.0000007.910400
50%446.0000000.0000003.00000028.0000000.0000000.00000014.454200
75%668.5000001.0000003.00000038.0000001.0000000.00000031.000000
max891.0000001.0000003.00000080.0000008.0000006.000000512.329200

可视化 EDA 与您的第一个模型

现在您对数据有了初步印象,也看过一些统计量,是时候借助 seaborn 对数据进行可视化了:

  • 例如,用 seaborn 绘制目标变量——泰坦尼克号幸存情况的柱状图。
sns.countplot(x='Survived', data=df_train);

bar chart

要点:在训练集中,未幸存的人数多于幸存者。那我们就先构建一个预测“无人幸存”的模型。

这个模型当然很差,因为我们知道有人幸存。但它提供了一个基线:之后我们构建的任何模型都应该优于它。

您可以按以下步骤操作:

  • 在 df_test 中创建 'Survived' 列,将所有行编码为“未幸存”;
  • 将 df_test 的 'PassengerId' 与 'Survived' 列保存为 .csv 并提交至 Kaggle。
df_test['Survived'] = 0
df_test[['PassengerId', 'Survived']].to_csv('data/predictions/no_survivors.csv', index=False)

这个模型给到您的准确率是多少?在 Kaggle 上为 62.7。

kaggle

不算太差!

重要提示! 您也需要考虑准确率之外的评估指标!

对特征变量进行 EDA

现在您已经做了一个快速粗略的模型,是时候再次迭代:继续做一些探索性数据分析,很快再构建一个新模型!

  • 您可以使用 seaborn 绘制泰坦尼克号数据集特征 'Sex'(df_train)的柱状图。
sns.countplot(x='Sex', data=df_train);

bar plot

  • 此外,使用 seaborn 绘制按特征 'Sex' 分面(拆分)的 'Survived' 柱状图。
sns.factorplot(x='Survived', col='Sex', kind='count', data=df_train);

bar plot

要点:女性的幸存概率高于男性。

  • 基于此要点,您可以用 pandas 计算幸存的女性和男性各有多少:
df_train.groupby(['Sex']).Survived.sum()
Sex
female    233
male      109
Name: Survived, dtype: int64
  • 用 pandas 分别计算女性与男性的幸存比例:
print(df_train[df_train.Sex == 'female'].Survived.sum()/df_train[df_train.Sex == 'female'].Survived.count())
print(df_train[df_train.Sex == 'male'].Survived.sum()/df_train[df_train.Sex == 'male'].Survived.count())
0.742038216561
0.188908145581

女性的幸存率为 74%,男性为 19%。

现在来构建第二个模型:预测所有女性都幸存,所有男性都未幸存。同样,这并不现实,但它能提供一个可与后续模型比较的基线。

  • 为 df_test 创建 'Survived' 列,按上述规则进行编码。
  • 将 df_test 的 'PassengerId' 与 'Survived' 列保存为 .csv 并提交至 Kaggle。
df_test['Survived'] = df_test.Sex == 'female'
df_test['Survived'] = df_test.Survived.apply(lambda x: int(x))
df_test.head()
 PassengerIdPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedSurvived
08923Kelly, Mr. Jamesmale34.5003309117.8292NaNQ0
18933Wilkes, Mrs. James (Ellen Needs)female47.0103632727.0000NaNS1
28942Myles, Mr. Thomas Francismale62.0002402769.6875NaNQ0
38953Wirz, Mr. Albertmale27.0003151548.6625NaNS0
48963Hirvonen, Mrs. Alexander (Helga E Lindqvist)female22.011310129812.2875NaNS1
df_test[['PassengerId', 'Survived']].to_csv('../data/predictions/women_survive.csv', index=False)

将该模型提交到 Kaggle 后,准确率是多少?

在 Kaggle 上的准确率为 76.6%:

kaggle

通过这次提交,您的排行榜名次上升了大约 2000 位!同时,分数也提升了,做得很棒!

继续更深入地探索数据!

  • 使用 seaborn 绘制按特征 'Pclass' 分面的 'Survived' 柱状图。
sns.factorplot(x='Survived', col='Pclass', kind='count', data=df_train);

bar plot

要点:头等舱乘客更可能幸存;相反,三等舱乘客更不容易幸存。

  • 使用 seaborn 绘制按特征 'Embarked' 分面的 'Survived' 柱状图。
sns.factorplot(x='Survived', col='Embarked', kind='count', data=df_train);

bar plot

要点:在南安普顿登船的乘客幸存概率较低。

数值型变量的 EDA

  • 使用 seaborn 绘制 df_train 中 'Fare' 列的直方图。
sns.distplot(df_train.Fare, kde=False);

histogram

要点:大多数乘客的票价低于 100。

  • 使用 pandas 的绘图方法,在同一张图上分别绘制各 'Survived' 取值对应的 'Fare' 分布。
df_train.groupby('Survived').Fare.hist(alpha=0.6);

bar plot

要点:看起来票价更高的人,幸存概率也更高。

  • 使用 seaborn 绘制 df_train 中 'Age' 列的直方图。在此之前,您需要先删除空值。
df_train_drop = df_train.dropna()
sns.distplot(df_train_drop.Age, kde=False);

histogram

  • 绘制以 'Survived' 为 x 轴、'Fare' 为 y 轴的条带图与蜂群图。
sns.stripplot(x='Survived', y='Fare', data=df_train, alpha=0.3, jitter=True);

strip plot

sns.swarmplot(x='Survived', y='Fare', data=df_train);

swarm plot

要点:票价与是否幸存在泰坦尼克号上明显相关。

  • 使用 DataFrame 方法 .describe(),按幸存与否查看 'Fare' 的汇总统计。
df_train.groupby('Survived').Fare.describe()
 countmeanstdmin25%50%75%max
Survived        
0549.022.11788731.3882070.07.854210.526.0263.0000
1342.048.39540866.5969980.012.475026.057.0512.3292
  • 使用 seaborn 绘制以 'Age' 为横轴、'Fare' 为纵轴,并按 'Survived' 着色的散点图。
sns.lmplot(x='Age', y='Fare', hue='Survived', data=df_train, fit_reg=False, scatter_kws={'alpha':0.5});

scatter plot

要点:幸存者要么支付了较高票价,要么年龄较小。

  • 使用 seaborn 基于 df_train(去空后的 df_train_drop)创建按 'Survived' 着色的 pairplot。pairplot 能在一个图网格中集中展示您已发现的大部分信息。
sns.pairplot(df_train_drop, hue='Survived');

plots

从 EDA 到机器学习模型

在本教程中,您已经顺利完成:

  • 加载并初步浏览数据;
  • 对目标变量进行可视化并做出第一次预测;
  • 对部分特征变量做可视化,并基于 EDA 做出更好的预测;
  • 对分类与数值特征进行了更深入的 EDA。

在下一篇文章中,您将基于本次 EDA 的发现来构建一些机器学习模型。我们会在该项目的下一篇文章中进行(计划于 12 月 27 日发布)。

主题