­

泰坦尼克号之生存预测(1)

  • 2019 年 10 月 5 日
  • 筆記

泰坦尼克号之生存预测(1)

0.说在前面1.数据预处理2.作者的话

0.说在前面

有几天没更新机器学习了,我终于来更新了,对的,你今天看到的就是机器学习系列内容!

上一节一起学习了one-hot编码,那么本节主要偏重实践,一起践行one-hot!

昨天周末,有点时间,就来玩了一下kaggle上面的经典比赛—泰坦尼克号生存预测问题!

在接下来的几篇文章中,我将给大家介绍学习Kaggle比赛的一个完整流程,今天先来带大家一起学习一下泰坦尼克号的数据预处理部分。

比赛官网:https://www.kaggle.com/c/titanic

1.数据预处理

数据初识

这里主要是对数据进行介绍,下载的数据集分为train与test以及gender_submission,分别是训练集,测试集以及生成提交文件的参考文件。

train与test各列分别为:

PassengerId  乘客ID  Pclass  客舱等级(1/2/3等舱位)  Name  乘客姓名  Sex  性别  Age  年龄  SibSp 兄弟姐妹数或配偶数  Parch 父母数或子女数  Ticket 船票编号  Fare 船票价格  Cabin  客舱号  Embarked  登船港口

导包

import seaborn as sns  from matplotlib import pyplot as plt  import pandas as pd  %matplotlib inline  import warnings  from sklearn.model_selection import train_test_split  warnings.filterwarnings('ignore')

数据导入

这里将训练集与测试集导入,并通过concat将数据整合一块,做个缺失值分析处理。

tannike_train=pd.read_csv('./train.csv')  tannike_test=pd.read_csv('./test.csv')  join_data=pd.concat([tannike_train,tannike_test],ignore_index=True)

数据预处理及特征工程

统计缺失值

join_data.isna().sum()

结果:

Age             263  Cabin          1014  Embarked          2  Fare              1  Name              0  Parch             0  PassengerId       0  Pclass            0  Sex               0  SibSp             0  Survived        418  Ticket            0  dtype: int64

从这个结果中我们发现:

Age与Cabin以缺失值较多,而Fare与Embarked缺失值较少,可以考虑用中位数,均值或者众数等方式解决

缺失值处理

fare_mean = tannike_train['Fare'].mean()  tannike_test.loc[pd.isnull(tannike_test.Fare),'Fare'] = fare_mean  embarked_mode = tannike_train['Embarked'].mode()  tannike_train.loc[pd.isna(tannike_train.Embarked),['Embarked']] = embarked_mode[0]  tannike_train.loc[pd.isna(tannike_train.Age),['Age']] = tannike_train['Age'].mean()  tannike_test.loc[pd.isna(tannike_test.Age),['Age']] = tannike_test['Age'].mean()

查看缺失值,以Embarked为例:

tannike_train.Embarked.isna().sum()

输出为0,则表示缺失值被处理完毕!

数据划分

这里直接划分成训练集与测试集的原因是对比与label数据的误差度。

label = tannike_train['Survived']  tannike_train.drop('Survived',axis=1,inplace=True)    X_train,X_test,Y_train,Y_test = train_test_split(tannike_train,label,test_size = 0.3,random_state = 1)    X_train['Survived'] = Y_train  X_test['Survived'] = Y_test 

切分数据为训练集,测试集!

性别与生存

我们先来看一下性别与生存关系:

sex_Sur = pd.crosstab(tannike_train.Sex,tannike_train.Survived)  sex_Sur.rename(columns={0.0:'dead',1.0:'survived'},inplace=True)  sex_Sur

输出:

Survived    dead    survived  Sex  female    81  233  male    468 109

数据可视化:

# stacked属性设置多个柱状图是否叠加  sex_Sur.plot.bar(stacked=True,color=['#f441f1','#b6f442'])  plt.xticks(rotation=0,size='x-large')  plt.xlabel('')

条状图转为饼图:

sex_Sur.plot.pie(subplots=True,figsize=(10,5),colors=('#b6f442','#41d0f4'))

综合上述两图,我们发现女性的存活率要比男性高!Age可以作为一个重要特征!

特征工程处理:

上周机器学习我们讲了one-hot编码如何使用,这里就直接使用了,将数据转为0,1数据

tannike_train['Sex'] = tannike_train['Sex'].apply(lambda x: 1 if x == 'male' else 0)  tannike_test['Sex'] = tannike_test['Sex'].apply(lambda x: 1 if x == 'male' else 0)  # one-hot编码  tannike_train = pd.get_dummies(data= tannike_train,columns=['Sex'])  tannike_test = pd.get_dummies(data= tannike_test,columns=['Sex'])

年龄与存活

研究年龄与存活关联:

survived_age=tannike_train[tannike_train.Survived==1]['Age']  dead_age=tannike_train[tannike_train.Survived==0]['Age']  age_frame=pd.concat([survived_age,dead_age],axis=1)  age_frame.columns=['Survived','Dead']  age_frame.head()

输出数据(前5行数据):

    Survived    Dead  0    NaN     22.0  1    38.0    NaN  2    26.0    NaN  3    35.0    NaN  4    NaN     35.0

可视化

# 为避免颜色覆盖,使用alpha通道属性  age_frame.plot(kind='hist',bins=30,alpha=0.3,figsize=(10,6))

上图发现:

年龄低于5岁的,存活率相对较高!而在75岁以后存活率也高,在中间的15到35之间存活率相对较高,其他的就比较低了,我们可以在做特征工程时候,对其做年龄划分处理,比如:低中高等。

特征工程处理:

tannike_train['Small_Age'] = np.int32(tannike_train['Age'] <= 5)  tannike_train['Old_Age'] = np.int32(tannike_train['Age'] >= 65)  tannike_train['Middle_Age'] = np.int32((tannike_train['Age'] >= 15) & (tannike_train['Age'] <= 25))    tannike_test['Small_Age'] = np.int32(tannike_test['Age'] <= 5)  tannike_test['Old_Age'] = np.int32(tannike_test['Age'] >= 65)  tannike_test['Middle_Age'] = np.int32((tannike_test['Age'] >= 15) & (tannike_test['Age'] <= 25))  

名字与存活

首先来统计一下各个名字开头的数量,比如Ms开头的数量:

# 比如名字为Attalah, Miss. Malake,我们提取出目的是Miss,运用两次lambda  X_train['Name_Title'] = X_train['Name'].apply(lambda x: x.split(',')[1]).apply(lambda x: x.split()[0])  X_test['Name_Title'] = X_test['Name'].apply(lambda x: x.split(',')[1]).apply(lambda x: x.split()[0])  X_train.groupby('Name_Title')['Survived'].count()

输出:

Name_Title  Capt.        1  Col.         2  Don.         1  Dr.          4  Lady.        1  Major.       1  Master.     27  Miss.      126  Mlle.        1  Mme.         1  Mr.        365  Mrs.        87  Rev.         5  the          1  Name: Survived, dtype: int64

交叉数据:训练与测试集可视化对比差异:

# 条形图上的误差棒则表示各类的数值相对于条形图所显示的值的误差  # seaborn的barplot()利用矩阵条的高度反映数值变量的集中趋势,以及使用errorbar功能(差棒图)来估计变量之间的差值统计  fig, (axis1,axis2) = plt.subplots(1,2,figsize=(15,5))  sns.barplot('Name_Title', 'Survived', data=X_train.sort_values('Name_Title'), ax=axis1)  sns.barplot('Name_Title', 'Survived', data=X_test.sort_values('Name_Title'), ax=axis2) 

下面这个图显示的数据变量的集中趋势!

对比这个数据,得出如下结论:

对于不同的名字开头,他的生存率不同,这里根据存活率平均程度高低依次下分。

特征工程处理:

通过定义一个函数来对名字的存活性高低,进行详细排序:

def Name_Title_Code(x):      if x == 'Mr.':          return 1      if (x=='Ms.') or (x=='Lady.') or (x == 'Mlle.') or (x =='Mme.') or (x == 'the.') or (x =='Sir.') or (x=='Major'):          return 2      if (x == 'Mrs.'):          return 3      if x == 'Miss.':          return 4      if x == 'Master.':          return 5      if x == 'Dr.':          return 6      return 7

对真正的训练集与测试集进行one-hot编码

tannike_train['Name_Title'] = tannike_train['Name'].apply(lambda x: x.split(',')[1]).apply(lambda x: x.split()[0])  tannike_test['Name_Title'] = tannike_test['Name'].apply(lambda x: x.split(',')[1]).apply(lambda x: x.split()[0])    tannike_train['Name_Title'] = tannike_train['Name_Title'].apply(Name_Title_Code)  tannike_test['Name_Title'] = tannike_test['Name_Title'].apply(Name_Title_Code)  tannike_train = pd.get_dummies(columns = ['Name_Title'], data = tannike_train)  tannike_test = pd.get_dummies(columns = ['Name_Title'], data = tannike_test)

船票编号与存活

获取船票第一个字母:

def Ticket_First_Let(x):      return x[0]

交叉数据集:训练与测试集处理:

X_train['Ticket_First_Letter'] = X_train['Ticket'].apply(Ticket_First_Let)  X_test['Ticket_First_Letter'] = X_test['Ticket'].apply(Ticket_First_Let)

可视化船票编号与存活关系

fig, (axis1,axis2) = plt.subplots(1,2,figsize=(15,5))  sns.barplot('Ticket_First_Letter', 'Survived', data=X_train.sort_values('Ticket_First_Letter'), ax=axis1)  sns.barplot('Ticket_First_Letter', 'Survived', data=X_test.sort_values('Ticket_First_Letter'), ax=axis2) 

同理,我们发现票的前面数字的编号对生存也是有影响!

这里对不同的票编号封装成函数,进行处理!

def Ticket_First_Letter_Code(x):      if (x == 'F'):          return 1      if x == '1' or x=='P' or x=='9':          return 2      if x == '2':          return 3      if x == 'C':          return 4      if x == 'S':          return 5      if x == '6':          return 6      if x == '7':          return 7      if x == 'A':          return 8      if x == 'W':          return 9      return 10

真实训练集与测试集处理:

one-hot编码处理:

tannike_train['Ticket_First_Letter'] = tannike_train['Ticket'].apply(Ticket_First_Let)  tannike_test['Ticket_First_Letter'] = tannike_test['Ticket'].apply(Ticket_First_Let)    tannike_train['Ticket_First_Letter'] = tannike_train['Ticket_First_Letter'].apply(Ticket_First_Letter_Code)  tannike_test['Ticket_First_Letter'] = tannike_test['Ticket_First_Letter'].apply(Ticket_First_Letter_Code)  tannike_train = pd.get_dummies(columns = ['Ticket_First_Letter'], data = tannike_train)  tannike_test = pd.get_dummies(columns = ['Ticket_First_Letter'], data = tannike_test) 

由于篇幅问题,最后的cabin及SibSp等Pclass等特征下节分享!

参考文章:https://blog.csdn.net/wydyttxs/article/details/76695205