Titanic是kaggle的一个toy级别的入门问题,主要是为了熟悉一下kaggle题目的解题思路,以及用到的处理方法,算法,以及对应的函数库的使用。首先,用pandas做数据的读写,并且可以大致看一下数据长什么样子;然后,用seaborn可以了解一下数据的一些统计规律,尤其是各个特征的分布情况,为之后选择何种模型提供一个参考;然后matplotlib可以完成一些比较基本的和底层的可视化的任务;然后进行建模,可以用scikit-learn,如果用到DL的话,需要考虑tensorflow等;最后进行调参,以及不同模型之间的集成(ensemble),得到最终的结果。
Titanic问题是通过给定船上人员的各种身份信息,如性别,年龄,姓名,舱位等等,以及是否生还的信息,希望找到一个合理的模型,或者叫做判据,来对于一个已知身份的人,预测其在这场海难中是否会生还。当然,有这个实际问题来看,其准确率不可能做到1.00,如果做到了,一定是对于这个问题本身过拟合了(overfitting),因为生还与否和每个人的身份,年龄,地位,性别等有一定关系,但是并不是完全由这些因素决定的。我们希望找到一个模型,能够较大把握的预测生还的几率即可,也就是准确度较高即可。
该问题实际上是一个给定部分可选择的特征并且指出特征的实际含义的情况下的二分类问题。
先看看数据长什么样子,对于不方便编程处理的做一下预处理,比如填补空缺,或者将字符串转成布尔值,以及其他的类型转换。然后观察一下统计特征,先根据经验选择要使用的特征。
import pandas as pd
import numpy as np
import seaborn as sns # 不知道为啥seaborn的简写是sns...documentation里这样写就这样吧
import matplotlib.pyplot as plt
path = './titanic/'
trainset = pd.read_csv( path + 'train.csv')
trainset.describe()
trainset.shape
(891, 12)
trainset.head(3)
trainset.tail(3)
先看一下这些column都是什么,index在最左边是标号,一共891个traindata,passengerid就是编号,比index多1,对于特征无用。survived表示是否生还,0代表死,1代表生。pclass代表票的等级,分别是1,2,3等。 name,sex,age不需要说明。sibsp为 # of siblings / spouses aboard the Titanic,就是兄弟姐妹以及配偶的人数。parch为# of parents / children aboard the Titanic,也就是父母或子女,直系亲属的数量。ticket为票号,fare是票价,cabin是舱位,embarked是登船地点,S,C,Q分别代表三个城市。C = Cherbourg, Q = Queenstown, S = Southampton。
我们先看一下这些数据的分布,用seaborn直方图
sns.distplot(trainset['Survived'], kde = False, rug = False)
plt.show()
sns.distplot(trainset['Survived'], kde = True, rug = False) # kde set true when we need ratio (pdf approx) instead of real number
# rug set true, then there are small tick at each observation
plt.show()
trainset['Survived'].unique()
array([0, 1])
svvd = trainset['Survived']
print 'dead : ' + str(len(svvd[svvd == 0])) + ' ' + str(float(len(svvd[svvd == 0]))/len(svvd)*100) + '%'
print 'survived : ' + str(len(svvd[svvd == 1])) + ' ' + str(float(len(svvd[svvd == 1]))/len(svvd)*100) + '%'
dead : 549 61.6161616162%
survived : 342 38.3838383838%
说明死亡率百分之六十多,也就是说,如果直接全部预测死亡的话,还会有60%左右的准确率。相当于recall达到100%,因为FN=0,假阴性为零,这是显然的,因为我们的预测中根本没有阴性,所以不存在真假阴性。但是准确率由于有FP,假阳性,所以大概能够有60%。这个数值应当作为我们的标准,就是benchmark,因为不需要对特征进行任何分析,直接考虑需要预测的结果的分布都能达到这样的准确率。
trainset.Pclass.unique() # 也可以用成员运算符加上column的名称,作为成员提取某一列
array([3, 1, 2])
sns.distplot(trainset.Pclass,kde=False)
plt.show()
在这891个人中,头等舱大佬有两百多,中间的也是两百左右,吊斯舱有五百左右。
trainset.loc[trainset.Sex == 'male','Sex'] = 0 # loc 定位到sex==‘male’的行,后面表示修改‘sex’column的值
trainset.loc[trainset.Sex == 'female','Sex'] = 1
sns.distplot(trainset.Sex,kde=False)
plt.show()
sns.distplot(trainset[trainset.Sex == 0].Age.dropna(),hist = False, color='black', label='male')
sns.distplot(trainset[trainset.Sex == 1].Age.dropna(),hist = False, color='red', label='female')
plt.title('Age versus Class')
plt.show()
sns.distplot(trainset[trainset.Pclass == 1].Age.dropna(),hist = False, color='blue', label='class 1')
sns.distplot(trainset[trainset.Pclass == 2].Age.dropna(),hist = False, color='green', label='class 2')
sns.distplot(trainset[trainset.Pclass == 3].Age.dropna(),hist = False, color='pink', label='class 3')
plt.title('Age versus Class')
plt.show()
hhh,买得起头等舱的年龄相对大一些,吊斯们以青年为主。符合我们的认知。
sns.distplot(trainset[trainset.Pclass == 1].Fare.dropna(),hist = False, color='blue', label='class 1')
sns.distplot(trainset[trainset.Pclass == 2].Fare.dropna(),hist = False, color='green', label='class 2')
sns.distplot(trainset[trainset.Pclass == 3].Fare.dropna(),hist = False, color='pink', label='class 3')
plt.title('Fare versus class')
plt.show()
plt.figure()
plt.subplot(121)
sns.distplot(trainset[trainset.Survived == 1].Pclass.dropna(),hist = True, color='blue', label='survived', kde = False)
plt.title('survived')
plt.subplot(122)
sns.distplot(trainset[trainset.Survived == 0].Pclass.dropna(),hist = True, color='red', label='dead', kde = False)
plt.title('dead')
plt.show()
death_number = trainset[trainset.Survived == 0].groupby('Pclass').Survived
alive_number = trainset[trainset.Survived == 1].groupby('Pclass').Survived
death_ratio = death_number.count()/(alive_number.count() + death_number.count())
fig, axes = plt.subplots(1,1,figsize = (5,2),dpi = 100)
axes.bar(range(1,4), death_ratio, width=0.35, facecolor = 'black', edgecolor = 'blue')
axes.set_xticks([1,2,3])
axes.set_xticklabels(['class 1', 'class 2', 'class 3'])
plt.title('death ratio versus class')
plt.show()
plt.close(fig)
alive_fare = trainset[trainset.Survived == 0].Fare
dead_fare = trainset[trainset.Survived == 1].Fare
fig, axes = plt.subplots(1,1)
sns.distplot(alive_fare, hist = False, kde = True, color = 'pink', rug = False, label = 'alive')
sns.distplot(dead_fare, hist = False, kde = True, color = 'black', rug = False, label = 'dead')
plt.title('survived/dead versus fare')
plt.show()
trainset.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | 0 | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th… | 1 | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | 1 | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
trainset.loc[trainset.Embarked == 'S','Embarked'] = 1
trainset.loc[trainset.Embarked == 'C','Embarked'] = 2
trainset.loc[trainset.Embarked == 'Q','Embarked'] = 3
trainset.tail(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
888 | 889 | 0 | 3 | Johnston, Miss. Catherine Helen “Carrie” | 1 | NaN | 1 | 2 | W./C. 6607 | 23.45 | NaN | 1 |
889 | 890 | 1 | 1 | Behr, Mr. Karl Howell | 0 | 26.0 | 0 | 0 | 111369 | 30.00 | C148 | 2 |
890 | 891 | 0 | 3 | Dooley, Mr. Patrick | 0 | 32.0 | 0 | 0 | 370376 | 7.75 | NaN | 3 |
traincorr = trainset.dropna().drop('PassengerId',axis=1).corr()
traincorr
Survived | Pclass | Sex | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|---|
Survived | 1.000000 | -0.034542 | 0.532418 | -0.254085 | 0.106346 | 0.023582 | 0.134241 |
Pclass | -0.034542 | 1.000000 | 0.046181 | -0.306514 | -0.103592 | 0.047496 | -0.315235 |
Sex | 0.532418 | 0.046181 | 1.000000 | -0.184969 | 0.104291 | 0.089581 | 0.130433 |
Age | -0.254085 | -0.306514 | -0.184969 | 1.000000 | -0.156162 | -0.271271 | -0.092424 |
SibSp | 0.106346 | -0.103592 | 0.104291 | -0.156162 | 1.000000 | 0.255346 | 0.286433 |
Parch | 0.023582 | 0.047496 | 0.089581 | -0.271271 | 0.255346 | 1.000000 | 0.389740 |
Fare | 0.134241 | -0.315235 | 0.130433 | -0.092424 | 0.286433 | 0.389740 | 1.000000 |
sns.heatmap(traincorr,square=True,vmax=0.99,vmin=-0.99)
plt.show()
fare和pclass负相关,显然。sex和survivd有一定的正相关性,由于sex中男性0,女性1,而survived中0dead,1survived,也是就说女性更容易获救。age和parch有些负相关,可能因为小孩子age小,有父母陪同,所以parch大,而成年人独自出行的多。
axes = plt.figure(figsize=(10,5)).add_subplot(111)
sns.violinplot(ax=axes, x = 'Sex',y = 'Age', hue = 'Survived', data=trainset, split = True) # split 将提琴图从中间分开,不同hue在不同边
axes.set_xticks([0,1])
axes.set_xticklabels(['male','female'])
plt.show()
可以看出,成年男性死亡率高,男性中获救的多数是小孩子,而女性获救的多数为成年人。可以看出在救援过程中,最大限度的照顾到了妇女和儿童,看来当时船上的人还是很遵从绅士精神的。
axes = plt.figure(figsize=(10,3)).add_subplot(111)
sns.violinplot(ax=axes, x = 'Pclass',y = 'Age', hue = 'Survived', data=trainset, split = True)
axes.set_xticks([0, 1, 2])
axes.set_xticklabels(['high class','median class', 'low class'])
plt.show()
axes = plt.figure(figsize=(10,3)).add_subplot(111)
sns.violinplot(ax=axes, x = 'Pclass',y = 'Sex', hue = 'Survived', data=trainset, split = True)
axes.set_xticks([0, 1, 2])
axes.set_xticklabels(['high class','median class', 'low class'])
plt.show()
从上图看,可以看到各个舱位的男性和女性的生还比例,以及获救的和死亡的人里面男性和女性的比例。首先,头等舱女性生还比例很大,而吊斯舱里面的女性死亡率比较高,相对的,头等舱的男性生还比率很低,而吊斯舱的男性生还率是三个舱位里最大的。说明不同阶层的人在灾难事件中采取的对策还是不一样的,相较而言,阶层较高的人群可能会更遵守妇女儿童先上船的规则。但是,我们从上图还能看出,不管那个阶层,男性的死亡率都比女性要高很多,女性生还的都是多于死亡的,而男性死亡的远多于生还的。由此看来,即便对待妇女的态度上确实有阶级差异,但是总体来说,船上的男人们都履行了绅士精神,让本来应该在灾难面前力量弱于青壮年男性从而死亡率理应更高的妇女儿童争取到了更多的机会,说明船上的男士还是很优秀的。
对于数据的EDA到此差不多了,下面要找我们可以选择用来分类的特征。由以上分析可以看出,sex和age两个应该是主要的特征,pclass也可以列入考虑,fare和pclass有一定的关系,也可以利用。之后,我们可以利用sklearn工具包用这几个特征分类一下,查看结果。
2018年02月22日16:55:26
https://github.com/ChiaChuang/MyKagglePrograms/blob/master/titanic%EF%BC%8Ctoy%20problem.ipynb
真是的,无所事事的时候别谈什么将来嘛! —— 漫画家,空知英秋