Python社区  »  机器学习算法

死里逃生?机器学习算法揭露泰坦尼克号幸存者之谜

数据魔术师 • 1 年前 • 140 次点击  

“你一定会脱险的,你要活下去,生很多孩子,看着他们长大。你会安享晚年,安息在温暖的床上,而不是今晚在这里,不是像这样死去。”

——电影《泰坦尼克号》

1997年,一部凄美的《泰坦尼克号》让人记住了迎着黄昏拥立在船头的杰克和罗丝,也让人忘不了那艘号称“永不沉没之船”的巨轮如何一点点淹没在大海。

“后来,700多个人在大海上等着,等着活,等着死,等着做忏悔,遥遥无期。”

——电影《泰坦尼克号》


Part1 案例背景


影片根据真实事件改编,片中的泰坦尼克号是英国白星航运公司下辖的一艘奥林匹克级邮轮,于1909年动工建造,1912年首次航行。1912年4月15日,在首次航行期间,泰坦尼克号撞上冰山后沉没,2224名乘客和机组人员中有1502人遇难。这场轰动的旷世悲剧震撼了国际社会,并警醒人们制定了更完善的船舶安全条例。


本研究中,我们希望分析具有哪种特征的人可能在这样的灾难中存活。具体而言,就是运用机器学习算法来预测哪些乘客将幸免于难,从而帮助人们做好灾前预警,提高在灾难中的存活率。


本项目使用随机森林进行预测。

Part 2 数据来源及变量说

本研究数据来源于Kaggle中的项目:Titanic: Machine Learning from Disaster,网页链接:https://www.kaggle.com/c/titanic。Kaggle提供的数据集包括Training Set (train.csv)、Test Set (test.csv),其中训练集有891个观察值和12个变量,测试集有418个观察值和11个变量(缺失Survived变量)。变量说明如下:

变量类型

变量

类型

定义

取值范围/示例

因变量

Survived

int

存活与否

0=No, 1=Yes

自变量

PassengerId

int

乘客序号

1-1309


Pclass

int

乘客序号

1-1309


Name

chr

姓名

Braund, Mr. Owen Harris; Cumings, Mrs. John Bradley (Florence Briggs Thayer); Nicola-Yarred, Miss. Jamila等


Sex

chr

性别

male, female


Age

num

年龄

0.17-80 (如果年龄小于1,则年龄是分数。如果为估计年龄,为xx.5)


SibSp

int

共同登船的兄弟姐妹&配偶的总数

0-8


Parch

int

共同登船的父母&子女的总数

0-9


Ticket

chr

票号



Fare

num

票价

0-512.3292


Cabin

chr

舱号

A/B/C/D/E/F/G+数字


Embarked

chr

登船港口

C = Cherbourg, Q = Queenstown, S = Southampton


Part 3 加载数据及初步探索

第一,加载和安装必要的R包,并将测试集和训练集导入R。


第二,定义测试集的Survived变量为NA,合并测试集和训练集。


第三,查看数据完整性,是否有缺失值。


#查看数据完整性

sapply(all, function(x) {sum(is.na(x))})

结果显示:



从输出结果可以看出,变量Survived缺失的刚好是418个值,对应测试集的418个观察值,这是我们需要预测的目标。变量Age、Fare、Cabin、Embarked存在缺省值,后续需要填补缺省值。


第四,发现重要变量Sex和Pclass。


首先将Survived、Sex和Pclass转化为因子变量。接着我们调用ggplot()函数绘制了以下图形,总览了训练集中死亡和幸存的人数。


Figure 2 训练集中死亡和幸存的人数


经计算观察,在泰坦尼克号上的1309人(训练集891人+测试集418人)中,64.4%是男性。这一比例与训练集中的男性比例几乎相同(64.7%)。在训练集中,81.1%的男性死亡,25.8%的女性死亡。性别不同导致的存活率差异巨大,因此我们认为Sex似乎是一个非常重要的预测指标。


另一方面,经绘图观察,存活与否和乘客阶层密切相关。大部分头等乘客幸存下来,大多数三等乘客死亡。同样值得注意的是,几乎所有一、二等的女性都幸存下来了。而对于男性来说,二等乘客的存活率几乎和三等乘客一样糟糕(见图3)。


Figure 3 阶层、性别和存活的关系   


由此可见,Pclass和Sex同时影响存活与否,所以我们将两个变量结合,创造出PclassSex变量。PclassSex变量为因子变量,包括6个水平——“P1Male”、“P2Male”、“P3Male”、“P1Female”、“P2Female”、“P3Female”。

Part 4 数据清洗

我们对原始的变量进行一定的处理,主要是对缺省值进行处理。

4.1

>>挖掘Name中的称谓,建立“Title”变量 <<<

在数据中,“名字”(name)变量是完整的(即非空的),但是实际上这个变量不仅仅包含了姓氏和名字,还包括了对每个人的称呼(Title),我们必须将其分开,以便整理数据。同理,将姓氏分解出来(Surname,在称呼之前),我们想在后续分析家庭是否一起旅行时使用这个变量。



从上边的表格中我们可以看到,部分Title的数量很少,我们希望能够减少Title的种类,以便更好的用于预测。Ms.经常用于较年轻的已婚女士,因此我们希望将Ms.加入到Miss中,在法语中,Mlle同样也可以用Miss来表示。再者,我们假设Mme代表已婚女士,我们将其加入Mrs。对于其他低频的Title,我们将用“Rare Title”来代替。



4.2

>>处理Age缺失值 <<<

我们绘制Age和Survived变量的密度图,如下:



从密度图中可以看出,18岁以下的存活几率相对更大。


为了处理年龄缺失值,我们试图探究Age变量和Title变量、Pclass变量之间的关系。从箱线图可以看到,不同的年龄段对应不同的称谓(Title)。值得注意的是,Master这个称谓都是儿童。通过搜索得知,Master这个称谓一般指的是最大的儿子,因此有Master称谓的都是男孩。



我们进行线性回归,结果如下:



可以看出,Pclass变量和Title变量与Age之间的关系更为显著,与前面箱线图预期一致。


之后我们利用回归出来的方程预测年龄的缺省值,具体如下:


4.3

>>处理Fare和Embarked缺失值 <<<

登船地点变量(Embarked)存在2个缺失值,票价(Fare)存在着1个缺省值。登船地点对票价来说是重要的,因为不同的登船地点表示的路程不同。



没有家人陪同而出来旅行的两个女性(Fsize =1),彼此之间肯定是朋友,她们是结伴出行的,因为他们的船票号码都相同,为113572(没有其他人的船票号码和她们一样)。


我们尝试找出登船地点信息与票价信息都存在的乘客的信息后,对它们按照登船地点与船舱等级分组,算出每组中人均票价的中位数。



因为这两个平均票价都是40,所以她们可能在Cherbourgh登船的,因此我们补全票价数据。


同理,我们运用同样的方法预测Mr Story的票价。



由于Mr.Story是阶级三且在S港登船,我们预测Mr Story的票价为7.8。


尽管现在票价这个变量已经没有空缺值了,但我们留意到有17个人的票价为0,且这些人都不是儿童。虽然我们觉得信息可能正确的(可能有些人的船票是靠赢来的呢?),但我们认为这些票价会扰乱算法。比如,在一等船舱,有些乘客的票价也为0。避免这些问题,我们用每个人的等级所对应票价的中位数去代替那些为0的票价值。


处理数据后,fare的数据如下:

4.4

>>处理Cabin缺失值 <<<

Cabin变量的值的第一个字母代表的是甲板的层级,甲板A-E是顶级的,往往是第一阶层的人住在里面。


用甲板U来代替Cabin的缺失值,并且只保留Cabin变量的第一个字母。


各阶层各舱位的乘客存活情况直方图如下:



可以看到,甲板A的存活率不高,甲板F和甲板E的存活率较高。


我们具体看下缺省值的数量:



可以看到Cabin的缺失值很多,尽管Cabin可以较好地预测乘客的存活与否,但是我们没有一个合适的方法进行筛选,考虑之下,我们在后续还是选择放弃这个变量。

4.5

>>寻找一起旅行的团体 <<<

逻辑上来讲,如果是以团体出行的,出事时一起生存的概率会提高(可能是更好的对灾难反应)。我们希望能够找到在泰坦尼克号上一起旅行的团体,这些团体可能包括直系家庭(如父母、孩子),也可能包括旁系家庭(如表、堂),也有可能包括一起订票的朋友,在本部分中我们将尝试区分出这些团体。

4.5.1

>> 家庭规模:兄弟姐妹、配偶、父母和孩子 <<

为了能够建立每个人在船上的家庭规模,我们将个体在船上的父母/孩子数量(Parch)和兄弟姐妹/配偶(SibSp)相加起来,当然,再加上自己。


从下面的图中可以很明显的看到,单独旅行的人有更大的可能遇险。此外,我们可以看到,家庭成员在2-4个人之间的有更大的可能性生存下来。然而,5及5个人以上的大家庭生存的几率明显降低。



现在我们可以按照家庭规模将数据分为3组——包括单独(solo),小规模家庭(small family)和大规模家庭(large family),但是在这之前,我们想先检验下数据中家庭规模是否与其他变量(如Surname)存在矛盾。

4.5.2

>> 检验家庭规模是否存在矛盾 <<

为了检验家庭规模数据的不一致性,我们建立一个变量(FsizeName),这个变量连接Surname和Fsize,之后,我们对不一致的数据进行定位,分别处理。



数据中显示,有93个样本数据的“NumObs”和“Fsize”不一致,即同家庭规模同姓氏的人数与同一个家庭的人数不相等。通过网络搜索我们发现,泰坦尼克号上确实有大约1300名乘客(其余的为船员),所以我们的数据集中应该没有缺失的乘客。

4.5.3

>> 尝试纠正退票带来的影响 <<

对于家庭规模中存在的矛盾,一个合理的解释是,部分乘客订票后又将票取消(这种情况下,SibSp和Parch不会实时更新)。我们以“Davies”为例,从表格中我们可以看到,这里应该有2个Davies家庭(Fsize=3,NumObs=5)。在我们上一步的检查过程中,由于Surname一致,这两个家庭的姓氏被加总了,导致了不一致。



票号为A/4的三位“Davies”应该是完整的一个家庭。因此错误应该出现在编号【550】和【1222】两位乘客上。通过SibSp和Parch的数据可以推测,No.550和No.1222是母子。一种可能是,No.1222号乘客原来打算携带2位孩子登船,但最终只带了一位。



严格意义上来说,数据集中肯定还有类似这样的错误没有被修正,但是考虑到最终可能对模型结果影响很小,也考虑到可行性,我们决定暂时忽略这类错误,寻找并修正其他错误。

4.5.4

>> 家庭规模:叔叔阿姨、表兄弟姐妹等 <<

在这些数据里面,其实有一些隐藏的家庭关系比退票情况更为有趣。例如, Hockings和Richards这两个姓氏很可能是相关的。我们将这两个姓氏的异常值输出。



从表格上来看,我们可以猜测,438号乘客带了2个孩子(408和832),一位母亲(775),一个弟弟(530)和一个妹妹(944),对于438号乘客来说,这些都是直系亲属。但是,对于其他人来说,这些可能是间接相关的。比如408和832两个孩子,对于他们来说,只会计算SibSp为1和Parch为1,不会将530和944这类间接相关的亲属计算进去。这样导致了Fsize将会虚高,这些大规模的家庭实际上可以细分成更小的群组。438这位乘客作为母亲更可能跟530和832两位孩子在一起,而她的弟弟(530)和妹妹(944)更可能与她的母亲(775)待在一起。

 

为了处理这种情况,将大的家庭规模分解成更小的家庭,我们需要先将归属于女方(maiden name)的家庭找出来



如图我们可以看到,以女方为线索,一共有7个大规模家庭被找出,这些家庭成员没有一致的Fsize, 这意味着他们存在着间接的亲属关系(如祖父母等)。同理,我们将未处理的男方的大规模家庭寻找出来。



我们以Mr Julius Vander Planke(1037)为例子,他与他的妻子(19)和2个兄弟姐妹(39和334)一起旅行。而他的妻子和他的兄弟姐妹实际上是间接相关的。



经过上面的分析,我们可以看到一共有9个家庭(涉及37个乘客)包含间接家庭成员。我们希望能够给这些家庭一样的Fsize(这将给每个在这样的家庭里面的成员拥有一致的生存机会)。为了降低家庭规模,我们将各个姓氏家庭的不同Fsize进行平均。



这确实是我们想要的效果,我们想要赋予这些属于同个家庭的人一个一致的Fsize(给予这些成员共同的生存机会),但并不想用最大Fsize去替代,因为比起直系家庭,这些大规模家庭在灾难发生时,不太可能一直呆在一起。

4.5.5

>> 寻找更多的二级家庭 <<

我们在考虑是否忽略了某些二级家庭,我们对数据进行再次的浏览,发现有些具有相同Surname的人的票号(Ticket)往往具有一致性。


这些人没有兄弟姐妹、配偶、父母或者孩子在船上,他们之间票号的关联更可能意味着他们是表兄弟姐妹或者叔伯关系。在本项目中,我们并不是想将所有的人的家庭关系都找出来,而是想知道灾难发生时这些人是否有可能待在一起。一个合理的假设是,一般来说直系家庭(比如父母和孩子)经常会待在一起,而叔伯/堂表兄弟姐妹更可能相互照顾。我们在数据集中,寻找家庭规模(Fsize)只有1个人,但是Surname有重复且Ticket只差两位尾数的乘客,一共有56个人。下表我们只展示前12个人。


4.5.6

>> 一起旅行的朋友 <<

除了我们上面所提及的家庭群组之外,朋友之间也有可能一起旅行。以Ticket号为1601的乘客为例:

上述这几个乘客,年龄基本相仿,所预定的票号也是一致的,我们有理由相信这是一个团队来出游(或许是旅行团呢)。因此,我们将拥有一样Ticket号码的人进行统计,并且建立Tsize变量。


与家庭规模非常类似,从下面的柱状图可以看到,2-4人的小规模团体往往有更高的几率生存下来。



经过上述的分组后,家庭规模和朋友(用Ticket分组)规模可能有一部分重叠,我们将Fsize和Tsize结合起来,利用这些数据创建一个分类变量。


由于1个人和2个人旅行生存机会显然不同,我们将其分为两个组(solo和group),3个人和4个人似乎有最好的生存机会(group),5个及5个人以上显然有更加糟糕的生存机会。


4.6

>>根据票号(Ticket)分组 <<<

票号可以检查是否有集体出游的人存活下来,考虑到,处在同个位置的组有人存活下来的话,组内其他人存活的概率更大。我们由此建立AnySurvivors变量。

4.7

>>考虑儿童对模型的影响 <<<

从之前绘制的年龄与存活的密度图看到,大概在14.5岁以下的儿童比其他年龄段的人存活率高。但是年龄在14.5岁以下的儿童大部分来自第三阶层,并且绝大多数没有存活下来,因此我们认为第三阶层是一个噪音,需要考虑从模型中去除。



同时考虑到将第三阶层儿童分离出来这种分类是否合理,所以我们也生成一个新的变量:是否儿童-IsChild。

Part 5 建立模型

随机森林模型拟合度较高,且过度拟合问题不严重,首先我们选择了随机森林模型来进行分析。


首先我们利用原始变量作出第一步模型预测,基于前文的分析,我们选取了5个变量来进行随机森林模拟(分别是Pclass,Sex,Age,Cabin,Embarked)。


#情况一:'Pclass', 'Sex', 'Age', 'Cabin', 'Embarked'



该随机模型用了891个样本。5个自变量,要预测的变量的结果是0或1。Accuracy的值最大时,模型最合适。所以,我们选择了mtry = 2,此时对应的Accuracy是0.804。


初步预测的准确率似乎已经较高,我们将基于前文对各变量的分析,进一步调整模型变量以期继续调整模型预测准确度。即使前面我们分析了那么多变量,为了避免产生拟合过度的问题,我们模型预测时,变量个数均不超过5个。我们依次考虑了是否加入港口(Embarked)、是否是一二层级小孩(IsChildP12)、是否是小孩(IsChild)变量。具体结果分析见附录一。最终当我们加入AnySurvivors变量时,我们发现选择5个变量(PclassSex,GroupSize,FarePP,AnySurvivors,IsChildP12)预测时,此时准确率显著提高。


#情况二:'PclassSex', 'GroupSize', 'FarePP', 'AnySurvivors', 'IsChildP12'



Accuracy的值最大时, mtry = 3,此时对应的Accuracy是0.857。


MeanDecreaseGini通过基尼(Gini)指数计算每个变量对分类树每个节点上观测值的异质性的影响,从而比较变量的重要性。该值越大表示该变量的重要性越大。所以,我们用MeanDecreaseGini来对5个变量的重要性进行评分:



考虑到IschildP12变量重要性最低,我们进一步考虑采用Ischild来代替IschildP12。


#情况三:'PclassSex', 'GroupSize', 'FarePP', 'AnySurvivors', 'IsChild'


#显示预测质量



最后,我们可以用训练出来的模型去预测测试集里的存活变量(Survived):


solution_rf


##随机森林模型的Accuracy是0.868。


-- the end --


后台回复【泰坦尼克号】,即可下载本文代码和数据


精彩文章推荐

数模竞赛|数学建模比赛该如何准备?

你永远都不知道男生有多想和18岁女孩子谈恋爱!

"最萌身高差"究竟有多萌?

年薪百万的王宝强和月入三千的吴彦祖,你更愿意pick谁?


扫一扫,获取数据和模型

还有更多算法学习课件分享哟



文案、代码、审核 / 张元新、郑少淳、李大伟、郭丽丽、朱小青(皆为研二)

排版 / 陈志(大四)

指导老师 / 朱文斌教授


如对文中内容有疑问,欢迎交流。PS:部分资料来自网络。

朱文斌(华南理工大学工商管理学院教授、i@zhuwb.com)

张元新(华南理工大学工商管理学院研究生二年级、jerry.yx@foxmail.com)

郑少淳(华南理工大学工商管理学院研究生二年级、sczheng_zoe@163.com)

李大伟(华南理工大学工商管理学院研究生二年级、397406076@qq.com)

郭丽丽(华南理工大学工商管理学院研究生二年级、201720130156@mail.scut.edu.cn)

朱小青(华南理工大学工商管理学院研究生二年级、1740384223@qq.con)





今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/JjXqgIE1Ns
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/23871
 
140 次点击  
分享到微博
文章 [ 1 ]  |  最新文章 4 月前
因为粥凉了
Reply   •   1 楼
因为粥凉了    4 月前

泰坦尼克号