Kaggle系列(1)——Titanic

0x01、项目介绍

学习了各种机器学习算法之后,可以找一个简单项目来练练手,感受一下完整的ML过程。本文主要记录我做这个项目的整个过程和思路。Titanic是Kaggle的入门项目,网上可以找到很多资料,所以选择它作为第一个练手的项目。(记录一下哈哈哈,截止到2020年10月3日,已经有17548支队伍参赛~)

简单介绍一下Titanic这个项目。泰坦尼克号海难是历史上最著名的海难事故之一:1912年4月15日,被誉为“永不沉没”的泰坦尼克号游轮在她的首航中撞上冰山而沉没,而船上并没有足够的救生艇,导致船上包括乘客和船员在内的2224人中有1502人在此次海难中丧生。但似乎有某些因素使得有一部分人更容易获救。这个项目是使用机器学习方法建立一个模型,用来预测泰坦尼克号海难中乘客是否生还。训练集(train.csv)包括了891位乘客的一些个人信息及其生还与否的信息。测试集(test.csv)含有418位乘客的信息,但不含生还信息。以下列出了部分字段及其含义:

字段名称 含义 描述
survival 是否生还 0:否; 1:是
pclass 船票等级 可代表经济水平: 1为上等,2为中等,3为底层
sex 性别
Age 年龄(单位是年) 如果小于1,则年龄是小数。如果估计了年龄,则采用xx.5的形式
sibsp 同在船上的兄弟姐妹/配偶数量 表示家庭关系:Sibling-(继)兄弟姐妹;Spouse-丈夫,妻子(情妇和未婚夫被忽略)
parch 同在船上的父母/子女数量 表示家庭关系:Parent-父母亲;Child-(继)子女。一些孩子只带一个保姆旅行,因此他们的parch=0。
ticket 船票号
fare 船票价格
cabin 船舱号
embarked 登船港口 C:Cherbourg(瑟堡,法国西北部港口城市), Q:Queenstown(皇后镇,爱尔兰), S:Southampton(南安普顿,英国南部港口城市)

0x02、项目过程简述

  1. 了解项目

    • 了解项目的背景,问题产生的原因等;
    • 可查找一些项目相关的资料,了解有关知识等,有助于分析和特征工程;
  2. 数据探索与分析

    • 了解训练集和测试集的字段结构,数据量,数据集的基本信息,有缺失值/异常值等;
    • 通过前面了解的知识,和数据分析寻找影响最终预测的因素。这个阶段需要综合利用各种统计与分析方法,可用各种图表使数据分展现得更加直观;
    • 生成挖掘思路,包括需要进行的预处理,规划使用的模型等;
  3. 预处理

    • 根据之前对数据集的了解,进行数据清洗、字段处理等,将训练集和测试集处理成为建模需要的格式;
    • 数据探索、分析与预处理的过程可能会占掉整个项目的80%以上的时间;
  4. 建模与优化

    • 根据前面的分析选择合适的模型算法,拟合数据;
    • 根据结果调整模型参数,优化特征工程,进行模型融合等。

0x03、数据探索与分析

3.1 数据的大致了解

首先读取训练集和测试集的数据,看一下含有的字段及取值范围,是否有缺失值或NaN等。

#coding=utf-8
import pandas as pd

d_train = pd.read_csv('train.csv')
d_test = pd.read_csv('test.csv')

print('---------- d_train.info() ----------')
print(d_train.info())
print('\n---------- d_train.describe() ----------')
print(d_train.describe())
print('\n---------- d_test.info() ----------')
print(d_test.info())
print('\n---------- d_test.describe() ----------')
print(d_test.describe())

print('---------- d_train.head() ----------')
print(d_train.head())

print('---------- d_test.head() ----------')
print(d_test.head())

以下是结果:

---------- d_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.7+ KB
None

---------- d_train.describe() ----------
       PassengerId    Survived      Pclass         Age       SibSp  \
count   891.000000  891.000000  891.000000  714.000000  891.000000   
mean    446.000000    0.383838    2.308642   29.699118    0.523008   
std     257.353842    0.486592    0.836071   14.526497    1.102743   
min       1.000000    0.000000    1.000000    0.420000    0.000000   
25%     223.500000    0.000000    2.000000   20.125000    0.000000   
50%     446.000000    0.000000    3.000000   28.000000    0.000000   
75%     668.500000    1.000000    3.000000   38.000000    1.000000   
max     891.000000    1.000000    3.000000   80.000000    8.000000   

            Parch        Fare  
count  891.000000  891.000000  
mean     0.381594   32.204208  
std      0.806057   49.693429  
min      0.000000    0.000000  
25%      0.000000    7.910400  
50%      0.000000   14.454200  
75%      0.000000   31.000000  
max      6.000000  512.329200  

---------- d_test.info() ----------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 11 columns):
PassengerId    418 non-null int64
Pclass         418 non-null int64
Name           418 non-null object
Sex            418 non-null object
Age            332 non-null float64
SibSp          418 non-null int64
Parch          418 non-null int64
Ticket         418 non-null object
Fare           417 non-null float64
Cabin          91 non-null object
Embarked       418 non-null object
dtypes: float64(2), int64(4), object(5)
memory usage: 36.0+ KB
None

---------- d_test.describe() ----------
       PassengerId      Pclass         Age       SibSp       Parch        Fare
count   418.000000  418.000000  332.000000  418.000000  418.000000  417.000000
mean   1100.500000    2.265550   30.272590    0.447368    0.392344   35.627188
std     120.810458    0.841838   14.181209    0.896760    0.981429   55.907576
min     892.000000    1.000000    0.170000    0.000000    0.000000    0.000000
25%     996.250000    1.000000   21.000000    0.000000    0.000000    7.895800
50%    1100.500000    3.000000   27.000000    0.000000    0.000000   14.454200
75%    1204.750000    3.000000   39.000000    1.000000    0.000000   31.500000
max    1309.000000    3.000000   76.000000    8.000000    9.000000  512.329200

img-train-head
img-test-head

观察数据并结合相关资料,把获得的信息梳理一下:

  • 训练集train.csv共891条数据,其中Age缺了177条(占19.9%),Cabin缺了687条(占77.1%),Embarked缺了2条。

  • 测试集test.csv共418条数据,其中Age缺了86条(占20.6%);Cabin缺了327条(占78.2%);Fare缺了1条。

  • 训练集train.csv中,大约38.4%的乘客得救;平均年龄29.7岁,最大的80岁,最小的不到半岁;大多数乘客是一个人坐船,少数乘客与家人同乘;多数乘客是3等舱且票价很便宜,同等级的舱位票价也有不同。

  • 测试集test.csv中,平均年龄30.3岁,最大的76岁,最小的也是不到半岁;同乘和舱位分布似乎与训练集差不多的样子。

  • 据一些资料,船上的乘客数量是1316,而这里训练集和测试集相加后乘客数量是1309,那么几乎已经包含了所有的乘客。(所以这里没有把船员信息包含进来?)那么训练集占68%,测试集占32%。

  • 训练集中比较重要的信息有是否获救、舱位等级、性别、年龄、父母子女数量、兄弟姐妹数量、登船港口这七个字段;而姓名、船票号、票价、舱位这四个字段初看并没有什么有用的信息,可能需要结合一些资料来挖掘。

  • 乘客名字(Name)信息中,女性有区分Mrs.和Miss.,这似乎能代表是否已婚,不知道这与是否获救有没有关系?可以统计看看都有哪些称呼,找寻称呼中的“隐藏信息”。

  • 查找了一些泰坦尼克号的资料,该船共有10层甲板,从上到下分别是:救生艇甲板(Top Deck),A~G共8层载客的甲板,H甲板和底层是锅炉和仓库。那么舱位(Cabin)信息是C85,是不是表示它位于C甲板?可以试着统计一下,验证一下猜想。

  • 票价和船舱等级的关系。一些资料显示,一等舱票价30英镑起步(如果是套房就更贵了,最贵票价870英镑),乘客主要是富豪贵族和社会名流;二等舱票价13英镑,乘客主要是中产阶级如律师医生等精英职业;三等舱票价7~9英镑,儿童票价是3英镑,乘客主要是来自英国、爱尔兰、北欧、意大利、俄国和土耳其等地的贫穷移民。结合这些资料,可猜测本项目中的票价(Fare)单位是英镑。但是有一些记录似乎有点不对劲,例如有的三等舱票价21英镑?可能是因为是与亲属一起买的套票。例如船上有8位中国人,买的是56英镑的三等舱套票,这样的话会使其舱位等级和票价不符,不知道会不会影响算法结果。

  • 舱位(Cabin)信息其实可以表示距离救生艇的远近,离救生艇较近的获救概率应该更大。但缺失值太多了,可能用处不大。

  • 船票号目前没什么头绪。可能与船舱等级、舱位、登船口岸等有关。

3.2 查看各项数据的分布

3.2.1 数值统计

统计是否获救、性别、船舱等级、父母子女数量、兄弟姐妹数量、登船港口的分布。代码如下:

# 数值统计
print('---------- 1、获救人数 ----------')
print(d_train.groupby(['Survived'])['PassengerId'].count())

print('\n---------- 2、性别分布 ----------')
print(d_train.groupby(['Sex'])['PassengerId'].count())

print('\n---------- 3、船舱等级分布 ----------')
print(d_train.groupby(['Pclass'])['PassengerId'].count())

print('\n---------- 4、父母/子女数量分布 ----------')
print(d_train.groupby(['Parch'])['PassengerId'].count())

print('\n---------- 5、兄弟姐妹数量分布 ----------')
print(d_train.groupby(['SibSp'])['PassengerId'].count())

print('\n---------- 6、登船港口分布 ----------')
print(d_train.groupby(['Embarked'])['PassengerId'].count())

print('\n---------- 7、称呼的分布 ----------')
d_train['Title'] = d_train['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)
print(pd.crosstab(d_train['Title'], d_train['Sex']))

print('\n---------- 8、名字长度分布 ----------')
d_train['NameLength'] = d_train['Name'].apply(len)
print(d_train.groupby(['NameLength'])['PassengerId'].count())

print('\n---------- 9、舱位甲板分布 ----------')
d_train['Deck'] = d_train['Cabin'].str[0]
print(d_train.groupby(['Deck'])['PassengerId'].count())

得到结果如下:

---------- 1、获救人数 ----------
Survived
0    549
1    342
Name: PassengerId, dtype: int64

---------- 2、性别分布 ----------
Sex
female    314
male      577
Name: PassengerId, dtype: int64

---------- 3、船舱等级分布 ----------
Pclass
1    216
2    184
3    491
Name: PassengerId, dtype: int64

---------- 4、父母/子女数量分布 ----------
Parch
0    678
1    118
2     80
3      5
4      4
5      5
6      1
Name: PassengerId, dtype: int64

---------- 5、兄弟姐妹数量分布 ----------
SibSp
0    608
1    209
2     28
3     16
4     18
5      5
8      7
Name: PassengerId, dtype: int64

---------- 6、登船港口分布 ----------
Embarked
C    168
Q     77
S    644
Name: PassengerId, dtype: int64

---------- 7、称呼的分布 ----------
Sex       female  male
Title                 
Capt           0     1
Col            0     2
Countess       1     0
Don            0     1
Dr             1     6
Jonkheer       0     1
Lady           1     0
Major          0     2
Master         0    40
Miss         182     0
Mlle           2     0
Mme            1     0
Mr             0   517
Mrs          125     0
Ms             1     0
Rev            0     6
Sir            0     1

---------- 8、名字长度分布 ----------
NameLength
12     2
13     2
14     3
15    15
16    26
17    42
18    50
19    64
20    39
21    40
22    38
23    39
24    43
25    55
26    49
27    50
28    43
29    32
30    37
31    30
32    23
33    22
34     7
35     6
36     9
37    10
38     9
39     9
40     7
41     8
42     5
43     5
44     8
45     9
46     7
47    11
48     3
49     5
50     4
51     7
52     4
53     2
54     1
55     2
56     3
57     2
61     1
65     1
67     1
82     1
Name: PassengerId, dtype: int64

---------- 9、舱位甲板分布 ----------
Deck
A    15
B    47
C    59
D    33
E    32
F    13
G     4
T     1
Name: PassengerId, dtype: int64

有很多种称呼(Title),整理了一下:

序号 称谓 含义 女性人数 男性人数
1 Capt 船长 0 1
2 Col 上校(简写) 0 2
3 Countess 女伯爵/伯爵夫人 1 0
4 Don 大学教师 0 1
5 Dr 博士/医生 1 6
6 Jonkheer 可能是某个家族 0 1
7 Lady 女士(可能有一定地位) 1 0
8 Major 少校 0 2
9 Master 硕士/专家 0 40
10 Miss (未婚)女士 182 0
11 Mlle 小姐(法语) 2 0
12 Mme 夫人(法语) 1 0
13 Mr 先生 0 517
14 Mrs (已婚)女士 125 0
15 Ms 女士(不指名婚否) 1 0
16 Rev 0 6
17 Sir 男爵 0 1
  • 另外测试集中还有一条Title是 Dona 的39岁头等舱女性,应该也是有一定社会地位的。

  • 不知道 Master 指的是什么,因为Master有专家的意思,一开始我以为是随同登船的设计师团队,后来看了一下乘客的详细情况,发现年龄最大的是12岁,所以这里Master应该指的是小于等于12岁的男孩。顺便又看了一下,女孩都计算在Miss这个称呼里面,小于等于12岁的有32个。

  • Rev 这个缩写真的不知道是什么,都是二等舱,年龄范围也挺大的,但是数量不多。

  • Jonkheer 这个也比较奇怪,票价是0。我看了一下训练集中一共有15位票价是0的。三个舱位

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值