KAGGLE TITANIC生還率預測——機器學習
導語:本文適合初學者,如果你是大神歡迎參觀指導。
想要機器學習,那麼在kaggle做訓練項目當然是必不可少,kaggle裡面入門級的的項目當屬泰塔尼克號生存預測,Titanic也是個入門級比賽。
我們需要科學上網工具去kaggle主頁面去註冊,找到Titanic拿到數據,偷懶就另說了
https://pan.baidu.com/s/1i6yW0TZa2Mia姐:Kaggle入門,看這一篇就夠了
從左到右依次是提交結果案例(提交結果)、測試數據、訓練數據。
首先得到了數據那麼再來一個大的思路框架,按照這個框架一步一步深入。
我們研究的問題是:在泰坦尼克號中究竟是什麼樣的人更容易存活?
#導入處理數據包import numpy as npimport pandas as pd#訓練數據集train = pd.read_csv("C:/Users/Administrator/Desktop/Titanic/train.csv")test = pd.read_csv("C:/Users/Administrator/Desktop/Titanic/test.csv")print ("訓練數據集:",train.shape,"測試數據集:",test.shape)
為了方便數據清洗,把訓練數據和測試數據合併到一起
#合併數據集,方便同時把兩個數據進行清洗full = train.append( test , ignore_index = True)print("合併後的數據集:",full.shape)
查看數據信息
這裡我們用http://full.info來查看數據類型和總數,看看那些數據有缺失
我們發現數據總共有1309行。
其中數據類型列:年齡(Age)、船艙號(Cabin)裡面有缺失數據:
1)年齡(Age)裡面數據總數是1046條,缺失了1309-1046=263,缺失率263/1309=20%
2)船票價格(Fare)裡面數據總數是1308條,缺失了1條數據
字元串列:
1)登船港口(Embarked)裡面數據總數是1307,只缺失了2條數據,缺失比較少
2)船艙號(Cabin)裡面數據總數是295,缺失了1309-295=1014,缺失率=1014/1309=77.5%,缺失比較大
這為我們下一步數據清洗指明了方向,只有知道哪些數據缺失數據,我們才能有針對性的處理。
可以看到,年齡、船艙號、登錄港口和船票價格有缺失,接下來需要處理一下缺失值。
年齡和船票價格的缺失值填充我們用fillna來填充,利用年齡的均值來填充缺失值,登錄港口我們將缺失值填充為最經常出現值英國南安普頓
#年齡(age)full[Age]=full[Age].fillna(full[Age].mean())#船票價格(Fare)full[Fare]=full[Fare].fillna(full[Fare].mean())#登船港口(Embarked):看一下裡面的數據長啥樣出發地:S=英國南安普頓Southampton途徑地點1:C=法國 瑟堡市Cherbourg途徑地點2:Q=愛爾蘭 昆士敦Queenstownfull[Embarked].head()
#港口只兩個缺失值,我們將缺失值填充為最頻繁出現的值:S=英國南安普頓Southamptonfull[Embarked]=full[Embarked].fillna(S)#船艙號(Cabin),查看裡面的數據長啥樣full[Cabin].head()
#船艙號缺失數據比較多,船艙號(Cabin)缺失值填充為U,表示位置Unknowfull[Cabin]=full[Cabin].fillna(U)
接下來進行數據清洗的第二步,特徵工程:特徵提取和特徵選擇
特徵工程就是最大限度的從原始數據中提取特徵,以供機器學習演算法和模型使用。
特徵提取:性別
將性別映射為數值男(male)對應數值1,女(female)對應數值0sex_mapDict={male:1, female:0}#map函數:對Series每個數據應用自定義的函數計算full[Sex] = full[Sex].map(sex_mapDict)full.head()
特徵提取:登船港口
#查看該數據原始內容full[Embarked].head()
#存放提取後的特徵embarkedDf = pd.DataFrame#使用get_dummies進行one-hot編碼,列名前綴是EmbarkedembarkedDf = pd.get_dummies(full[Embarked],prefix = Embarked)embarkedDf.head()
特徵提取:客艙等級
頭等艙(Pclass=1)、二等艙(Pclass=2)、三等艙(Pclass=3)
#存放提取後的特徵pclassDF = pd.DataFrame()##使用get_dummies進行one-hot編碼,列名前綴是PclasspclassDF = pd.get_dummies(full[Pclass],prefix=Pclass)pclassDF.head()
特徵提取:姓名
先看一下老外的名字有啥特徵
字元串格式: 名,頭銜.姓
定義函數:從姓名中獲取頭銜def getTitle(name): str1 = name.split(,)[1] str2 = str1.split(.)[0] str3=str2.strip() return str3#存放提取後的特徵titleDf = pd.DataFrame()#map函數:對series每個數據應用自定義的函數計算titleDf[Title] = full[Name].map(getTitle)titleDf.head()
看看不同人的名字的頭銜對生存率的影響定義以下幾種頭銜類別:Officer政府官員Royalty王室(皇室)Mr已婚男士Mrs已婚婦女Miss年輕未婚女子Master有技能的人/教師# 姓名中頭銜字元串與定義頭銜類別的映射關係title_mapDict = { "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" }#map函數:對Series每個數據應用自定義的函數計算titleDf[Title] = titleDf[Title].map(title_mapDict)#使用get_dummies進行one-hot編碼titleDf = pd.get_dummies(titleDf[Title])titleDf.head()
#添加one-hot編碼產生的虛擬變數(dummy variables)到泰坦尼克號數據集fullfull = pd.concat([full,titleDf],axis=1)#刪掉姓名這一列full.drop(Name,axis=1,inplace=True)full.head()
特徵提取:客艙號
提取船艙號的首字母做分類使用
lambda 匿名函數Lambda 表達式有何用處?如何使用?
#存放客艙號信息cabinDf = pd.DataFrame()客場號的類別值是首字母,例如:C85 類別映射為首字母Cfull[ Cabin ] = full[ Cabin ].map( lambda c : c[0] )##使用get_dummies進行one-hot編碼,列名前綴是CabincabinDf = pd.get_dummies( full[Cabin] , prefix = Cabin )cabinDf.head()
特徵提取:家庭類別
#存放家庭信息familyDf = pd.DataFrame()家庭人數=同代直系親屬數(Parch)+不同代直系親屬數(SibSp)+乘客自己(因為乘客自己也是家庭成員的一個,所以這裡加1)familyDf[ FamilySize ] = full[ Parch ] + full[ SibSp ] + 1家庭類別:小家庭Family_Single:家庭人數=1中等家庭Family_Small: 2<=家庭人數<=4大家庭Family_Large: 家庭人數>=5#if 條件為真的時候返回if前面內容,否則返回0familyDf[ Family_Single ] = familyDf[ FamilySize ].map( lambda s : 1 if s == 1 else 0 )familyDf[ Family_Small ] = familyDf[ FamilySize ].map( lambda s : 1 if 2 <= s <= 4 else 0 )familyDf[ Family_Large ] = familyDf[ FamilySize ].map( lambda s : 1 if 5 <= s else 0 )familyDf.head()
#添加one-hot編碼產生的虛擬變數(dummy variables)到泰坦尼克號數據集fullfull = pd.concat([full,familyDf],axis=1)full.head()
#到現在我們已經有了這麼多個特徵了full.shape
下面進行特徵選擇,選擇哪些特徵對預測生成情況有影響提高我們的模型的正確率。
計算各個特徵的相關係數
查看各個特徵與生成情況(survived)的相關係數ascending=False 表示按降序排列corrDf[Survived].sort_values(ascending = False)
可以看到女士與生存率有很強的正線性相關,可預測出當時船上遵守著女人孩子優先逃生的紳士原則
利用數據框concat把只請選出的特徵按照列的形式合併生成一個新的數據框,並放到full_X裡面
#特徵選擇full_X = pd.concat( [titleDf,#頭銜 pclassDF,#客艙等級 familyDf,#家庭大小 full[Fare],#船票價格 cabinDf,#客艙號 embarkedDf,#登錄港口 full[Sex]#性別 ],axis=1)full_X.head()
構建模型
1)坦尼克號測試數據集因為是我們最後要提交給Kaggle的,裡面沒有生存情況的值,所以不能用於評估模型。
我們將Kaggle泰坦尼克號項目給我們的測試數據,叫做預測數據集(記為pred,也就是預測英文單詞predict的縮寫)。
也就是我們使用機器學習模型來對其生存情況就那些預測。
2)我們使用Kaggle泰坦尼克號項目給的訓練數據集,做為我們的原始數據集(記為source),
從這個原始數據集中拆分出訓練數據集(記為train:用於模型訓練)和測試數據集(記為test:用於模型評估)。
#原始數據集有891行sourceRow=891sourceRow是我們在最開始合併數據前知道的,原始數據集有總共有891條數據從特徵集合full_X中提取原始數據集提取前891行數據時,我們要減去1,因為行號是從0開始的。#原始數據集:特徵source_X = full_X.loc[0:sourceRow-1,:]#原始數據集:標籤source_y = full.loc[0:sourceRow-1,Survived] #預測數據集:特徵pred_X = full_X.loc[sourceRow:,:]確保這裡原始數據集取的是前891行的數據,不然後面模型會有錯誤#原始數據集有多少行print(原始數據集有多少行:,source_X.shape[0])#預測數據集大小print(原始數據集有多少行:,pred_X.shape[0])
從原始數據集(source)中拆分出訓練數據集(用於模型訓練train),測試數據集(用於模型評估test)train_test_split是交叉驗證中常用的函數,功能是從樣本中隨機的按比例選取train data和test datatrain_data:所要劃分的樣本特徵集train_target:所要劃分的樣本結果test_size:樣本佔比,如果是整數的話就是樣本的數量from sklearn.cross_validation import train_test_split #建立模型用的訓練數據集和測試數據集train_X, test_X, train_y, test_y = train_test_split(source_X , source_y, train_size=.8)#輸出數據集大小print (原始數據集特徵:,source_X.shape, 訓練數據集特徵:,train_X.shape , 測試數據集特徵:,test_X.shape)print (原始數據集標籤:,source_y.shape, 訓練數據集標籤:,train_y.shape , 測試數據集標籤:,test_y.shape)
選擇機器學習演算法,這裡我用的最簡單的邏輯回歸演算法
#第1步:導入演算法from sklearn.linear_model import LogisticRegression#第2步:創建模型:邏輯回歸(logisic regression)model=LogisticRegression()#第3步:訓練模型model.fit(train_X,train_y)
#score得到魔性的正確率model.score(test_X , test_y)
使用預測數據集得到預測結果,並保存到csv文件中,上傳Kaggle就可以看到排名
#使用機器學習模型,對預測數據集中的生存情況進行預測pred_Y = model.predict(pred_X)生成的預測值是浮點數(0.0,1,0)但是Kaggle要求提交的結果是整型(0,1)所以要對數據類型進行轉換pred_Y=pred_Y.astype(int)#乘客idpassenger_id = full.loc[sourceRow:,PassengerId]#數據框:乘客id,預測生存情況的值predDf = pd.DataFrame( { PassengerId: passenger_id , Survived: pred_Y } )predDf.shape
接下來把結果提交給kaggle,看看自己的排名吧!
推薦閱讀:
※如何評價牛津的Prof. Andrew Zisserman?
※Tips for Deep Learning(三):Early Stopping & Regularization
※Lecture8 - Ensemble Learning
※那些年我趕過的時髦技術趨勢
※函數間隔、幾何間隔、最大間隔分類器