泰坦尼克号生存预测

本次笔记主要记录了一个机器学习的入门实战,泰坦尼克号生存预测。主要涉及的知识点有,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()
--------------------------------------------------

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表格如下:


泰坦尼克号生存预测_第1张图片
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)
# 最终得到数据如下
--------------------------------------------------

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})

你可能感兴趣的:(泰坦尼克号生存预测)