泰坦尼克号生存预测

本次笔记主要记录了一个机器学习的入门实战,泰坦尼克号生存预测。主要涉及的知识点有,python的pandas包,机器学习包sklearn。

背景知识:

泰坦尼克号是英国一艘奥林匹克级邮轮,在1912年4月10日,从南安普顿港码头出发,途径法国和爱尔兰,在驶向美国纽约的时候,与一座冰山相撞,最终沉没。在2224名船员及乘客中,逾1500人丧生。本次案例主要是通过机器学习方法对418人的生存状况进行预测。案例取自kaggle: https://www.kaggle.com/c/titanic。同时,kaggle上提供了泰坦尼克号案例的训练集train.csv和测试集test.csv。

一、提出问题

数据取自kaggle,本次问题主要是探究泰坦尼克号中,各个特征与生存状况的关系,并利用机器学习方法对生存状况进行预测。

二、 理解数据

首先导入数据集train.csv和test.csv:

import pandas as pd
import numpy as np

#导入训练集
train = pd.read_csv("train.csv")

#导入测试集
test = pd.read_csv("test.csv")

#查看测试集和训练集数据形状
print("Train data: ",train.shape)
print("Test data: ",test.shape)
full=train.append(test,ignore_index=True,sort=False)
print("Full data:", full.shape)
full.head()

由以上代码可以得出,训练数据为891行,12个字段,测试数据为418行,11个字段,缺少的这一行字段便是要预测的生存状况。

以下给出12个字段的含义解释:
1. PassengerId:乘客ID
2. Survived:生存状况;1:生存;死亡:0
3. Pclass:船舱等级;1:一等;2:二等;3:三等
4. Name:乘客姓名
5. Sex:乘客性别
6. Age:乘客年龄
7. SibSp:乘客的兄弟姐妹以及配偶数量
8. Parch:乘客的父母与子女数量
9. Ticket:票的编号
10. Fare:船票费用
11. Cabin:乘客船舱座位号
12. Embarked:乘客登船的港口,有三个可选值:S:南安普顿,C:法国瑟堡Q:爱尔兰昆士敦

full.info()
--------------------------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 12 columns):
PassengerId    1309 non-null int64
Survived       891 non-null float64
Pclass         1309 non-null int64
Name           1309 non-null object
Sex            1309 non-null object
Age            1046 non-null float64
SibSp          1309 non-null int64
Parch          1309 non-null int64
Ticket         1309 non-null object
Fare           1308 non-null float64
Cabin          295 non-null object
Embarked       1307 non-null object
dtypes: float64(3), int64(4), object(5)
memory usage: 122.8+ KB

通过分析可以得出,总数据为1309,其中Survived, Age, Fare, Cabin, Embarked均有缺失值,其中Survived的缺失值是所需要求的生存状况,其他值则需要通过数据清洗的方法来补全。

三、数据清洗

  1. Fare为数值类型,缺失值为1,因此采用平均值进行填充。
  2. Embarked为字符串类型,缺失值为2,因此采用众数进行填充。
  3. Cabin为字符串类型,缺失过多,缺失值为1014,缺失率为77.46%,原因可能为很多乘客没有舱位号,因此将缺失值用U来替代,表示未知。
  4. Age为数值类型,缺失值为263,本次采用平均值进行填充,由于年龄对于生存影响可能相对较大,因此下次会介绍如何使用机器学习方法进行填充。
# Fare缺失值填充
full.Fare = full.Fare.fillna(full.Fare.mean())
# Embarked缺失值填充
full.Embarked = full.Embarked.fillna(full.Embarked.mode()[0])
# Cabin缺失值填充
full.Cabin = full.Cabin.fillna('U')
# Age本次使用平均值填充
full.Age = full.Age.fillna(full.Age.mean())

在处理完缺失值以后,还需要对字符串类型的数值进行one-hot编码,方便机器学习算法识别。这里对Sex, Cabin, Embarked进行重新编码。

# 对Sex进行编码
sex = {'male':1,'female':0}
sex_num = full.Sex.map(sex)
sex_num.head()
# 对Embarked进行编码
embarked = pd.DataFrame()
embarked = pd.get_dummies(full.Embarked,prefix="Embarked")
embarked.head()
# 对Pcclass进行编码
pclass = pd.DataFrame()
pclass = pd.get_dummies(full.Pclass,prefix="Pclass")
pclass.head()

接下来将对名字的头衔进行提取,因为不同的头衔和职位可能会对生存情况产生影响。同时,在提取名字头衔后,会定义一个新字典作为身份,用来映射头衔与身份的关系,并对身份进行one-hot编码。

# 提取名字中的头衔
title = pd.DataFrame()
title['title'] = full.Name.map(lambda name:name.split(',')[1].split('.')[0].strip())
# 用groupby方法列出各种头衔
title.groupby('title').count()
# 创建身份字典
position = {
    'Capt':'Officer',
    'Col':'Officer',
    'Dr' :'Officer',
    'Don':'Royalty',
    'Dona':'Royalty',
    'Jonkheer':'Royalty',
    'Lady':'Miss',
    'Major':'Officer',
    'Master':'Master',
    'Mlle':'Miss',
    'Mme':'Mrs',
    'Mr':'Mr',
    'Mrs':'Mrs',
    'Ms':'Miss',
    'Rev':'Officer',
    'Sir':'Royalty',
    'the Countess':'Royalty'
}
# 将字典映射到头衔上
title['title'] = title['title'].map(position)
------------------------------
title
Master      61
Miss         5
Mr         757
Mrs        198
Officer     23
Royalty      5
Name: Name, dtype: int64
# 进行one-hot编码
title = pd.get_dummies(title['title'])

完成上述步骤后,可以获得one-hot表格如下:


one-hot编码后的头衔表格

接下来对Cabin列进行分类处理,首先提取首字母,然后按照首字母进行one-hot编码。

# 提取cabin首字母
cabin = full.Cabin.map(lambda cabin:cabin[0])
# 进行one-hot编码
cabin = pd.get_dummies(cabin,prefix='Cabin')

Parch字段和SibSp字段,其实可以归类为家庭成员的个数,可以将两者相加组成一个新字段作为家庭成员数量

family = full.Parch+full.SibSp +1

最后,将原始数据复制保留一份,并将重新编码的字段包括(Pclass, Name,Sex,Age,SibSp,Parch,Cabin,Embarked)以及无用字段Ticket删除。

# 复制一份原始数据
full_origin = train.append(test,ignore_index=True,sort=False)
# 建立一份新数据继续继续操作
full_data = full
# 删除无用字段及重新编码字段
full_data = full_data.drop(['Cabin','Name','Sex','Pclass','Embarked','Parch','SibSp','Ticket'],axis=1)
# 将重新编码后的字段加入新数据
full_data = pd.concat([full_data,sex_num,embarked,pclass,title,cabin,family],axis=1)
# 最终得到数据如下
--------------------------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 27 columns):
PassengerId    1309 non-null int64
Survived       891 non-null float64
Age            1309 non-null float64
Fare           1309 non-null float64
Sex            1309 non-null int64
Embarked_C     1309 non-null uint8
Embarked_Q     1309 non-null uint8
Embarked_S     1309 non-null uint8
Pclass_1       1309 non-null uint8
Pclass_2       1309 non-null uint8
Pclass_3       1309 non-null uint8
Master         1309 non-null uint8
Miss           1309 non-null uint8
Mr             1309 non-null uint8
Mrs            1309 non-null uint8
Officer        1309 non-null uint8
Royalty        1309 non-null uint8
Cabin_A        1309 non-null uint8
Cabin_B        1309 non-null uint8
Cabin_C        1309 non-null uint8
Cabin_D        1309 non-null uint8
Cabin_E        1309 non-null uint8
Cabin_F        1309 non-null uint8
Cabin_G        1309 non-null uint8
Cabin_T        1309 non-null uint8
Cabin_U        1309 non-null uint8
Family         1309 non-null int64
dtypes: float64(3), int64(3), uint8(21)
memory usage: 88.3 KB

四、 建模与评估

  1. 首先利用corr()函数建立相关系数矩阵,并提取出生存字段的相关系数并进行排序。
# 建立相关系数矩阵
corrDf = full_data.corr()
# 对生存字段的相关系数进行排序
print(corrDf['Survived'].sort_values(ascending=False))
----------------------------------------
Survived       1.000000
Mrs            0.341994
Pclass_1       0.285904
Fare           0.257307
Cabin_B        0.175095
Embarked_C     0.168240
Cabin_D        0.150716
Cabin_E        0.145321
Cabin_C        0.114652
Pclass_2       0.093349
Master         0.085221
Miss           0.085083
Cabin_F        0.057935
Cabin_A        0.022287
Family         0.016639
Royalty        0.016040
Cabin_G        0.016040
Embarked_Q     0.003650
PassengerId   -0.005007
Cabin_T       -0.026456
Officer       -0.031316
Age           -0.070323
Embarked_S    -0.149683
Cabin_U       -0.316912
Pclass_3      -0.322308
Sex           -0.543351
Mr            -0.549199
Name: Survived, dtype: float64

经过排序后发现,呈正相关的字段有:头衔,客舱等级,船票价格,船舱号等;呈负相关的的字段有:头衔,性别,客舱等级,船舱号。

  1. 原训练数据为891行,因此将处理后的新数据集拆分成训练集和测试集
from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LogisticRegression

# 训练数据数量
trainNum = 891
# 截取训练数据
data_X = full_data.loc[0:trainNum-1,:]
data_X = data_X.drop('Survived',axis=1)
data_y = full_data.loc[0:trainNum-1,'Survived']
# 配置训练数据和测试数据
X_train,X_test,y_train,y_test = train_test_split(data_X,data_y,train_size=0.8)
print('Orginal data x:', data_X.shape)
print('Train data x:',X_train.shape)
print('Test data x:',X_test.shape)
print('Orginal data y: ', data_y.shape)
print('Train data y: ',y_train.shape)
print('Test data y: ',y_test.shape)
  1. 导入模型算法,代入数据训练模型
# 导入逻辑回归模型
model = LogisticRegression()
# 使用训练数据训练模型
model.fit(X_train, y_train)
# 测试模型准确度
print(model.score(X_test,y_test))

利用训练数据中的测试集进行测试,发现模型准确率为86.6%

  1. 利用训练好的模型对测试集进行预测
# 取出测试集
X_predict = full_data.loc[trainNum:,:]
X_predict = X_predict.drop(['Survived'],axis=1)
# 将测试基代入模型进行预测
y_predict = model.predict(X_predict)
# 对测试集进行格式化
y_predict = y_predict.astype(int)
# 将预测结果用passengerId进行保存
passengerId = full_data.loc[trainNum:,'PassengerId']
predictDf = pd.DataFrame({'PassengerId':passengerId,'Survived':y_predict})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容