­

泰坦尼克號之生存預測(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