泰坦尼克號存活預測
這篇文章的代碼大概54個部分,幾百行代碼。雖然不是很多,但一旦發生錯誤找起來比較麻煩,所以在編寫這段項目的過程中,我利用jupyter notebook中的標題和注釋進行各部分的分類,方便查找各部分的不足進行補救。這也是我在這個項目中的養成的一個習慣,下面的代碼由於過多,所以只展現部分核心代碼。
項目流程
這個比賽項目的目的就是預測在泰坦尼克號中那些人可以存活下來,所以圍繞這個目標,我的思路是這樣的:
- 導入模塊和數據
- 查看整體信息
- 填補缺失值
- 提取特徵值
- 構建和評估模型
- 選取模型進行預測
導入模塊和數據
這裡面主要分為輔助性模塊(warnings),處理數據模塊(pandas, numpy), 數據可視化模塊(matplotlib, seaborn)和機器學習(sklearn)這四類,且這些模塊是機器學習中比較常用的模塊。模型中我主要導入了邏輯回歸(Logistic Regression),隨機森林(Random Forest),鄰近演算法(KNN),決策樹(Decision Tree)。
本文所需數據是從Kaggle比賽項目中下載下來的train.csv(訓練數據)和test.csv(測試數據)。
查看整體信息
這部分是我認為最重要的部分之一,主要是對整體數據的一個了解和分析,並確定對這些數據要如何處理。下面我將主要說明一下我的思路。
這裡面訓練數據總共891條,訓練數據418條,其中數字部分5個(不包括Survived),對象部分5個。其中像Name,Sex,Cabin,Embarked需要先對特徵值進行處理,而其他數字部分對特徵值進行分類提取就可以。
這是對數據中缺失值進行統計,其中Cabin和Age的數據缺失比較多。Cabin這部分不能進行預測填補數據,所以用『N』來代替所有缺失值。Age這部分我打算用常用的方法,就是用Age的中間值來填充缺失值。對於數據可以合併處理,但為了處理的細緻一點,我選擇分開處理。
填補缺失值
這個比賽項目中,需要填補的缺失值有Age,Cabin,Embarked,Fare。常用填補缺失值的方法主要是以下三種:
- 數值類型,用平均值取代
- 分類數據,用最常見的值取代
- 使用模型預測缺失值,如KNN
首先填補數值類型的數據(Age,Fare),利用平均值或者中間值進行取代。其中Age在訓練數據中缺失了約20%的數據量,在測試數據中缺失了約10%的數據量。這裡填補Age和Fare的方法類似。
然後填補分類數據(Cabin,Embarked),利用最常見的值或者N(Unkown)值來取代。其中Cabin在訓練數據和測試數據中缺失了約78%的數據量。因為Cabin的缺失數據量過大,所以用N來取代。而Embarked只有兩個所以用最常見的『S』來取代。
提取特徵值
這裡主要是對各部分特徵值進行分類並處理提取,主要分為數值類型,分類數據和字元串:
- 數值類型:Age,Fare,SibSp,Parch(直接進行分類提取)
- 分類數據:Sex, Embarked, Pclass(對特徵值部分進行提取)
- 字元串:Name, Cabin, Ticket(先對字元串進行處理,再對特徵值進行提取)
這裡面對於主要利用One-host的方法對特徵值進行分類提取,主要是對特徵值進行分類比較細,觀察和提取對生存有利的特徵值。
提取Age的特徵值
對於Age本身的數值不進行處理,但為了方便觀察,我按照年齡對其進行分類提取,分為Child(兒童),Teenager(少年),Youth(青年),Middle_aged(中年),older(老年),並去掉了數據中Age的數據。
train_Age = pd.DataFrame()test_Age = pd.DataFrame()train_Age[Age]= train[Age]train_Age[Child] = train_Age[Age].map(lambda a:1 if 0<= a <= 6 else 0)train_Age[Teenager] = train_Age[Age].map(lambda a:1 if 7<= a <= 17 else 0)train_Age[Youth] = train_Age[Age].map(lambda a:1 if 18<= a <= 30 else 0)train_Age[Middle_aged] = train_Age[Age].map(lambda a:1 if 31<= a <= 50 else 0)train_Age[older] = train_Age[Age].map(lambda a:1 if 51<= a else 0)test_Age[Age]= test[Age]test_Age[Child] = test_Age[Age].map(lambda a:1 if 0<= a <= 6 else 0)test_Age[Teenager] = test_Age[Age].map(lambda a:1 if 7<= a <= 17 else 0)test_Age[Youth] = test_Age[Age].map(lambda a:1 if 18<= a <= 30 else 0)test_Age[Middle_aged] = test_Age[Age].map(lambda a:1 if 31<= a <= 50 else 0)test_Age[older] = test_Age[Age].map(lambda a:1 if 51<= a else 0)train_Age.head()train = pd.concat([train,train_Age],axis=1)train.drop(Age,axis=1,inplace=True)test = pd.concat([test,test_Age],axis=1)test.drop(Age,axis=1,inplace=True)train.head()
提取SibSp和Parch的特徵值
泰坦尼克號中很多人是和家人一同出遊的,所以這裡對SibSp和Parch的合併處理,以表示泰坦尼克號中家庭的成員的多寡,並剔除原數據中這兩項。
train_Family = pd.DataFrame()test_Family = pd.DataFrame()train_Family[FamilySize] = train[Parch]+train[SibSp]+1test_Family[FamilySize] = test[Parch]+test[SibSp]+1train_Family[Family_Single] = train_Family[FamilySize].map(lambda f:1 if f == 1 else 0)train_Family[Family_Small] = train_Family[FamilySize].map(lambda f:1 if 2 <= f <= 4 else 0)train_Family[Family_Large] = train_Family[FamilySize].map(lambda f:1 if 5 <= f else 0)test_Family[Family_Single] = test_Family[FamilySize].map(lambda f:1 if f == 1 else 0)test_Family[Family_Small] = test_Family[FamilySize].map(lambda f:1 if 2 <= f <= 4 else 0)test_Family[Family_Large] = test_Family[FamilySize].map(lambda f:1 if 5 <= f else 0)train_Family.head()
提取Sex的特徵值
這部分我直接用機器學習講Sex中的male轉換為數值1,female轉換為數值0,這樣就完成了其特徵值的提取
提取Embarked和Pclass的特徵值
利用One-host的方法,也就是對Embarked中的C,Q,S進行分類處理,並提取其特徵值,Pclass方法相同就不再這裡闡述了。
提取Name和Cabin的特徵值
提取字元串就是要先對其進行預處理,Name中我最感興趣的就是其頭銜我利用字元串分割手法提取其頭銜,並進行分類。而對於Cabin中我只需要提取其船艙類別(C,N等),所以我對其進行切割處理後,用One-host提取特徵值。
測試數據比訓練數據中多了一個Dona。這裡我主要按照國際常用的方法將其分為Officer,Royalty,Mr,Mrs,Miss,Master這6類。
在測試數據中沒有Cabin_T,所以可以將其刪除。
Ticket數據比較複雜,而且重複的比較多(家族的票是相同的),所以這裡不提取這個特徵值。
提取影響生存的特徵值
這些數值提取完畢後,我們需要對其進行評估篩選出影響生存的特徵值,這裡面我主要篩選出Sex,Fare,Child,Pclass,Title,Cabin,Embarked這幾項數據。下圖顯示的是這幾項數據和生存的相關性。
構建和評估模型
我利用之前篩選出的特徵值構建模型,並分別用邏輯回歸(Logistic Regression),隨機森林(Random Forest),鄰近演算法(KNN),決策樹(Decision Tree)進行評估(其他方法也用過,這四個最具代表性)。其中隨機森林(Random Forest)和決策樹(Decision Tree)對模型的預測最好,所以選擇其中之一。
選取模型進行預測
最後用隨機森林的方法對數據進行預測,並保存提交至Kaggle進行評分。
random_forest = RandomForestClassifier(n_estimators=250, max_depth=5, criterion=gini)random_forest.fit(X_train, Y_train)Y_pred = random_forest.predict(X_test)pred = pd.DataFrame( { PassengerId: passenger_id , Survived: Y_pred } )pred.shapepred.head()pred.to_csv( titanic_pred.csv , index = False )
總結
首先對於這個項目給我帶來的兩大好處,其一是處理大量文件代碼是,在理清思路後,對各部分進行標註,不但方便自己找錯誤;其二是利用kaggle平台學習別人的代碼,改善自己代碼中的不足,達到自學的目的。
其次這個項目其實很多代碼我沒有寫上但在處理每個問題是,每段代碼都要信息核查處理,而且每段代碼如何運用也熟記於心。所以這裡主要就是分為兩個方面,一方面就是機器學習的整體思路就是我之前列的提綱,另一方面就是採取何種方法填充缺失值,如何提取想要的特徵值,如何選取模型等細節上的把我和處理。
最後這個項目的分數其實意義不大,如果對整體數據進行提取其實可以提高很多,但本身這麼做沒什麼意義。所以主要利用這個平台多跟高手們交流為主。
推薦閱讀:
※《機器學習實戰》學習總結(五)——Logistic回歸
※Python 實戰:股票數據定向爬蟲
※Mac上提升python運算速度-PyPy初體驗