機(jī)器學(xué)習(xí)入門實(shí)戰(zhàn) -- Titanic乘客生還預(yù)測
本文主要是對泰坦尼克號沉船事件進(jìn)行預(yù)測:在當(dāng)時的情況下,什么樣的人更容易存活俗冻?
在Kaggle中泰坦尼克項(xiàng)目主界面的Data欄獲取礁叔,有測試數(shù)據(jù)、訓(xùn)練數(shù)據(jù)和提交格式三個文件迄薄,本平臺已在云端配置好相關(guān)數(shù)據(jù)琅关,運(yùn)行下面的代碼塊即可讀取相應(yīng)的數(shù)據(jù)集。
In?[?]:
#首先導(dǎo)入相關(guān)的python包
import pandas as pd
import numpy as np
import sklearn as sk
In?[?]:
#讀取泰坦尼克數(shù)據(jù)集
import sys
sys.path.append('/home/ubuntu/MyFiles/PublicData/')
import os
import datasets_path
In?[?]:
#訓(xùn)練數(shù)據(jù)
train = pd.read_csv(datasets_path.titanic_train_dir)
#測試數(shù)據(jù)
test = pd.read_csv(datasets_path.titanic_test_dir)
print('訓(xùn)練集數(shù)量:',len(train), '測試集數(shù)量:',len(test))
In?[?]:
#合并兩個數(shù)據(jù)集噪奄,對數(shù)據(jù)集進(jìn)行數(shù)據(jù)清洗
Full = train.append(test)
print('合并后的數(shù)據(jù)集:',Full.shape)
在處理數(shù)據(jù)之前死姚,我們先觀察數(shù)據(jù)的形式對數(shù)據(jù)有一個大概的理解
In?[?]:
#查看數(shù)據(jù)的前5行
Full.head()
查看數(shù)據(jù)集的統(tǒng)計(jì)信息,查看是否有異常數(shù)據(jù)勤篮。
In?[?]:
#按列獲取數(shù)據(jù)類型的描述統(tǒng)計(jì)信息,非數(shù)字類型數(shù)據(jù)不會被統(tǒng)計(jì)
Full.describe()
按列查看數(shù)據(jù)關(guān)于不同特征屬性的數(shù)量都毒,檢查數(shù)據(jù)是否有缺失值
In?[?]:
#查看每一列的數(shù)據(jù)類型和數(shù)據(jù)總數(shù)
Full.info()
可以看到船艙號(Cabin)缺失的數(shù)據(jù)較多,接下來需要對相應(yīng)的特征屬性補(bǔ)全缺失值碰缔。在這個例子中账劲,對于數(shù)值型數(shù)據(jù),我們采用平均值填補(bǔ)金抡;非數(shù)值型采用眾數(shù)填補(bǔ)瀑焦。
In?[?]:
#票價(Fare)為數(shù)值型數(shù)據(jù),缺失一條可以采用均值補(bǔ)充
Full['Fare'] = Full['Fare'].fillna(Full['Fare'].mean())
In?[?]:
#年齡(Age)同理
Full['Age'] = Full['Age'].fillna(Full['Age'].mean())
In?[?]:
#Embarked為非數(shù)值型數(shù)據(jù)梗肝,采用眾數(shù)填充
print('眾數(shù):',Full['Embarked'].mode())
Full['Embarked'] = Full['Embarked'].fillna('S')
In?[?]:
#Cabin為字符串變量榛瓮,用U補(bǔ)充表示UnKnown
Full['Cabin'] = Full['Cabin'].fillna('U')
In?[?]:
#查看填充結(jié)果
Full['Embarked'].value_counts()
對于字符型特征屬性,需要轉(zhuǎn)換為數(shù)值類型替代通常使用One-hot編碼巫击,比如性別(Sex)
In?[?]:
#對于特征屬性(Sex)禀晓,男(male = 1)精续;女(female = 0)。
Sex_dict = {'male':1, 'female':0}
#下面使用map函數(shù)對數(shù)據(jù)進(jìn)行轉(zhuǎn)換粹懒,map函數(shù)對Series的內(nèi)個數(shù)據(jù)元素應(yīng)用自定義的函數(shù)計(jì)算
Full['Sex'] = Full['Sex'].map(Sex_dict)
Full.head()
#One-hot編碼是對操作2個類別以上的采集型編碼重付,因?yàn)樾詣e只有兩個類別,所以不需要使用One-hot編碼凫乖。
使用數(shù)據(jù)框的get_dummies( )方法可以實(shí)現(xiàn)One-hot編碼确垫。所以,重編碼后新的特征帽芽,需要新建一個數(shù)據(jù)框存儲下來:
Embarked的值分別為S删掀,C,Q
In?[?]:
Full['Embarked'].head()
In?[?]:
embarkerDF = pd.DataFrame()
embarkerDF = pd.get_dummies(Full['Embarked'], prefix='Embarked')
embarkerDF.head()
添加One-hot編碼產(chǎn)生的虛擬變量到數(shù)據(jù)集Full嚣镜,并將原有的Embarked屬性刪除
In?[?]:
Full = pd.concat([Full, embarkerDF], axis=1)
#刪除Embarked
Full.drop('Embarked', axis=1, inplace=True)
Full.head()
接下來處理特征屬性Name
In?[?]:
#定義函數(shù)爬迟,從姓名中提取頭銜
def getTitle(name):
? ? Name = name.split(',')[1] #split按指定符號分割字符串
? ? title = Name.split('.')[0]
? ? Title = title.strip() #移除字符串首尾制定的字符默認(rèn)為空格
? ? return Title
In?[?]:
#同上,先新建一個數(shù)據(jù)框存放處理后的數(shù)據(jù)
titleDF = pd.DataFrame()
titleDF['Title'] = Full['Name'].map(getTitle)
titleDF['Title'].head(),Full['Name'].head()
In?[?]:
'''
數(shù)據(jù)集中的頭銜有很多菊匿,為了簡化我們將其映射為下面幾種頭銜類別付呕,并對其One-hot處理
例如:Ms已婚男士,Mrs已婚女士跌捆,Officer政府官員徽职,Royalty皇室成員,Miss年輕未婚女子佩厚,Master有技能的人員
'''
title_dict = {'Capt':'Officer',
? ? ? ? ? ? ? 'Col': 'Officer',
? ? ? ? ? ? ? 'Major':'Officer',
? ? ? ? ? ? ? 'Jonkheer':'Royalty',
? ? ? ? ? ? ? 'Don':'Royalty',
? ? ? ? ? ? ? 'Sir':'Royalty',
? ? ? ? ? ? ? 'Dr':'Officer',
? ? ? ? ? ? ? 'Rev':'Officer',
? ? ? ? ? ? ? 'the Countess':'Royalty',
? ? ? ? ? ? ? 'Dona':'Royalty',
? ? ? ? ? ? ? 'Mme':'Mrs',
? ? ? ? ? ? ? 'Mlle':'Miss',
? ? ? ? ? ? ? 'Ms':'Mrs',
? ? ? ? ? ? ? 'Mr':'Mr',
? ? ? ? ? ? ? 'Mrs':'Mrs',
? ? ? ? ? ? ? 'Miss':'Miss',
? ? ? ? ? ? ? 'Master':'Master',
? ? ? ? ? ? ? 'Lady':'Royalty'}
titleDF['Title'] = titleDF['Title'].map(title_dict)
titleDF = pd.get_dummies(titleDF['Title'])
titleDF.head()
In?[?]:
#將titleDF添加到Full數(shù)據(jù)集并刪除特征屬性Name
Full = pd.concat([Full,titleDF], axis=1)
Full.drop('Name', axis=1, inplace=True)
Full.head()
In?[?]:
#家庭情況信息處理
familyDF = pd.DataFrame()
familyDF['family_size'] = Full['Parch'] + Full['SibSp'] + 1#家庭人數(shù)=同代親屬(Parch)+不同代親屬(SibSp)+乘客本身
familyDF['family_single'] = familyDF['family_size'].map(lambda s:1 if s==1 else 0)
familyDF['family_small'] = familyDF['family_size'].map(lambda s:1 if 2<=s<=4 else 0)
familyDF['family_large'] = familyDF['family_size'].map(lambda s:1 if s>4 else 0)
familyDF.head()
In?[?]:
Full = pd.concat([Full, familyDF], axis=1)
Full.head()
選取原則:根據(jù)所有變量的相關(guān)系數(shù)矩陣姆钉,篩選出與預(yù)測標(biāo)簽Survived最相關(guān)的特征變量。
In?[?]:
corrDF = Full.corr()
corrDF
這里選擇‘Survived’列抄瓦,按列降序排列潮瓶,就能看到哪些特征最正相關(guān),哪些特征最負(fù)相關(guān)钙姊,將其篩選出來作為模型的特征輸入毯辅。
In?[?]:
#按相關(guān)系數(shù)降序排列
corrDF['Survived'].sort_values(ascending = False)
選擇title_df, pclass_df, family_df, Fare, cabin_df, Sex作為特征。
構(gòu)建整體數(shù)據(jù)集的特征數(shù)據(jù)框full_x(包含1309行整體數(shù)據(jù)集特征)煞额,再使用loc屬性拆分出891行原始數(shù)據(jù)集特征source_x和標(biāo)簽source_y思恐、481行測試數(shù)據(jù)集特征test_x:
In?[?]:
Full_X = pd.concat([titleDF,
? ? ? ? ? ? ? ? ? Full['Pclass'],
? ? ? ? ? ? ? ? ? familyDF,
? ? ? ? ? ? ? ? ? Full['Fare'],
? ? ? ? ? ? ? ? ? embarkerDF,
? ? ? ? ? ? ? ? ? Full['Sex'],
? ? ? ? ? ? ? ? ? Full['Age']], axis=1)
Full_X.head()
建模的時候,需要將原始數(shù)據(jù)集進(jìn)行二八拆分:80%訓(xùn)練集+20%測試集膊毁。
訓(xùn)練集用于訓(xùn)練模型胀莹;測試集用于評估模型效果。
建模:
因?yàn)楸纠龥]有測試集的真實(shí)標(biāo)記婚温,所以從訓(xùn)練集中拆分出訓(xùn)練集和驗(yàn)證集以調(diào)整我們的模型描焰。(可以上傳模型提交到Kaggle驗(yàn)證自己模型的效果)
In?[?]:
#訓(xùn)練集特征屬性
Row = 891
data_x = Full_X.loc[:Row-1,:]
#訓(xùn)練集標(biāo)簽
data_y = Full.loc[:Row-1, 'Survived']
predict_x = Full_X.iloc[Row:, :]
#loc會從0開始選取到指定的位置,所以Row需要減1
In?[?]:
data_x.shape,data_y.shape,predict_x.shape
依據(jù)8:2的比例劃分訓(xùn)練集與驗(yàn)證集的數(shù)量
In?[?]:
from sklearn.cross_validation import train_test_split
#劃分訓(xùn)練集與驗(yàn)證集
train_x, val_x, train_y, val_y = train_test_split(data_x,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? data_y,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? train_size=0.8)
開始訓(xùn)練一個機(jī)器學(xué)習(xí)算法
這里我們選擇較為簡單的邏輯回歸算法
In?[?]:
#導(dǎo)入算法
from sklearn.linear_model import LogisticRegression
#建立模型
model = LogisticRegression(C=1, max_iter=100)
In?[?]:
#訓(xùn)練模型
model.fit(train_x, train_y)
使用model.score方法栅螟,通過測試集得到模型預(yù)測準(zhǔn)確率荆秦。
In?[?]:
model.score(val_x, val_y)
保存結(jié)果上傳到Kaggle看看結(jié)果如何?
In?[?]:
pred_y = model.predict(predict_x)
pred_y = pred_y.astype(int)
passenger_id = Full.iloc[891:,4]
predDF = pd.DataFrame({'PassengerId':passenger_id,
? ? ? ? ? ? ? ? ? ? ? 'Survived':pred_y})
predDF.shape
predDF.head()
In?[?]:
predDF.to_csv('titanic_pred.csv', index=False)
易學(xué)智能云平臺任一主機(jī)后可體驗(yàn)本案例的操作與交互式運(yùn)行效果逆日。傳送門https://www.easyaiforum.cn/instanceList
更多學(xué)習(xí)案例請?jiān)L問https://www.easyaiforum.cn/case