Kaggle-Titanic生還預測(Top5%)代碼分享

Kaggle-Titanic生還預測(Top5%)代碼分享

來自專欄天池&kaggle4 人贊了文章

Titanic作為kaggle的極佳入門賽事,受到眾多數據挖掘愛好者的關注,通過性別、年齡、船票、船艙位置、票價等特徵預測乘客最後是否生還,項目涵蓋了數據挖掘常用如缺失值填補、離散變數轉換、特徵組合等方法。雖說是入門項目,然而想跑高分也不是那麼容易...本方案最後得分0.81818,排名434/9774。在此就分析總體思路、數據預處理方式、特徵工程、模型選擇方面做介紹。

kernel上傳GitHub:

alige32/Kaggle-Titanic-kernel?

github.com圖標

數據分析三件套!

import pandas as pdimport numpy as npimport matplotlib.pyplot as plt

先來看下數據

indatas=pd.read_csv(rC:UsersjackDesktopprivate itanic rain.csv)datas.info()out<class pandas.core.frame.DataFrame>RangeIndex: 891 entries, 0 to 890Data columns (total 12 columns):PassengerId 891 non-null int64Survived 891 non-null int64Pclass 891 non-null int64Name 891 non-null objectSex 891 non-null objectAge 714 non-null float64SibSp 891 non-null int64Parch 891 non-null int64Ticket 891 non-null objectFare 891 non-null float64Cabin 204 non-null objectEmbarked 889 non-null objectdtypes: float64(2), int64(5), object(5)memory usage: 83.6+ KB

訓練集一共891條數據,12個特徵,其中Age、Cabin、Embarked存在缺失值,因為缺失值的填補對結果影響非常重要,讓我們詳細看一看...

inprint(訓練集樣本個數及維度:,datas.shape)print(特徵缺失值匯總:
,datas.isnull().sum().sort_values(ascending=False))out訓練集樣本個數及維度: (891, 12)特徵缺失值匯總: Cabin 687Age 177Embarked 2Fare 0Ticket 0Parch 0SibSp 0Sex 0Name 0Pclass 0Survived 0PassengerId 0

Cabin缺失值較多,對於這種一般直接用離散變數區分(即用0、1區分是否為缺失值)。年齡前期考慮用中位數或平均值的方式替換,但最終沒有採用這種方式,原因往後結合畫圖分析。Embarked為登船口(S、C、Q),只有兩個缺失值,考慮根據現有的其他特徵推測一下。

缺失值初步分析完畢,讓我們看一下各特徵與最後結果的關係吧!

嗯,女士優先

倉位等級越高,獲救幾率越大,從票價也能看出

登船口對生還的影響?這個不是很理解,但數據告訴我們的,暫時這樣認為吧...

+

似乎家人、兄弟姐妹數量為1和2時獲救幾率高點?其實不是很明顯,所以做了個組合特徵family,即兩組特徵之和

這樣看就明朗多了,家族人數為1、2、3時生還率較高。而3以上可能由於資源有限只能救一個,拉低了整體獲救率,或者同時遇難...還有單身狗,死!

小孩明顯偏高。國外16歲成年,符合電影里說的婦女和兒童先走。

畫圖分析到此,特徵數值化應該應該有了一個思路。gender根據男女替換為0,1;登船口暫時根據S、C、Q替換為1,0,2(順序很重要,C口生還率偏高,而樹模型會根據信息增益選擇最佳切分點。當然也可以考慮one-hot,但最後用了xgboost演算法,不是很推薦特徵one-hot處理);parch、sisbo特徵去掉,加入family特徵,人數1、2、3為一個類別;年齡16歲以下為一個類別;Cabin由於缺失值過多,有缺失值的先作為一個類別吧;Fare和Pclass不做處理;PassengerId、Name、Ticket沒想好怎麼處理,先去掉再說。

特徵工程前,先進行缺失值的填補。做完總結了一下,本次項目提分很大程度在於缺失值處理上,對數據挖掘、特別是中小型數據集,缺失值的填補特別重要。

登船口的位置可能與最後的船艙等級有很大關係,根據該乘客的Pclass,相同的人里大部分登船口為C,故填補C

datas.Embarked.fillna(C,inplace=True)

另外做了部分年齡的填補,因為根據年齡段只分了兩個類別,故考慮找出身份為未成年的乘客Age為空的進行填補。思路是根據暫時考慮最後去掉的Name特徵,排除名字里含有Mr、Mrs

Miss、Dr的,剩下的乘客中如果年齡為空,則填補到15歲以下。

特徵工程後的數據如下:

# 處理後特徵pro_datas.head()

保留了6個特徵,並加了一個組合特徵。

先這樣吧!

最後模型選擇了隨機森林、GBDT、XGboost,XGboost效果最好,調參的話用了網格超參數,簡單設置了max_depth、和n_estimators的範圍

# 大殺器inxgc=XGBClassifier()xgc_param = { n_estimators: range(30, 50, 2), max_depth: range(2, 7, 1)}gc=GridSearchCV(xgc,param_grid=xgc_param,cv=5)gc.fit(x_train,y_train)# y_predict=gc.predict(x_test)print("訓練集樣本為:",x_train.shape[0])print("測試集樣本為:",x_test.shape[0])print("預測率為:",gc.score(x_test,y_test))print("交叉驗證最好結果:",gc.best_score_)print("交叉驗證最好參數模型:",gc.best_estimator_)out訓練集樣本為: 668測試集樣本為: 223預測率為: 0.820627802690583交叉驗證最好結果: 0.8278443113772455交叉驗證最好參數模型: XGBClassifier(base_score=0.5, booster=gbtree, colsample_bylevel=1, colsample_bytree=1, gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=4, min_child_weight=1, missing=None, n_estimators=48, n_jobs=1, nthread=None, objective=binary:logistic, random_state=0, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None, silent=True, subsample=1)

XGboost很好兼顧了訓練集效果和防過擬合,驗證過程中其實不是得分最高的一次,卻在最後排名最高...另外交叉驗證的時候折數高低也會有影響,過低可能欠擬合,5折是我試驗最好的結果。

模型建好就完了?拿衣服!我們還需要對最終test數據做預測,並按照規定格式去提交。

導入測試數據,看下缺失值情況

intest_datas=pd.read_csv(rC:UsersaligeDesktop itatic est.csv)print(測試集樣本個數及維度:,test_datas.shape)print(特徵缺失值匯總:
,test_datas.isnull().sum().sort_values(ascending=False))out測試集樣本個數及維度: (418, 11)特徵缺失值匯總 Cabin 327Age 86Fare 1Embarked 0Ticket 0Parch 0SibSp 0Sex 0Name 0Pclass 0PassengerId 0dtype: int64

Cabin和Age的處理與訓練集一致,Fare由於訓練集中不存在缺失值,這裡需要額外處理一下。為了邏輯嚴謹,還是先畫個圖吧...

唔...有錢真的可以為所欲為...

所以,考慮到社會地位對票價的影響,取了登船口和船艙等級兩個特徵。以該乘客登船口和船艙類別相同的其他乘客的Fare中位數進行填補。

test_datas.loc[(test_datas.Fare.isnull()), Fare ] = test_datas[(test_datas.Embarked==S)&(test_datas.Pclass==3)].Fare.median()

填補工作完成,以訓練集特徵工程的模式把測試集走一輪,用訓練好的模型對測試數據進行預測。

pre_y=gc.predict(_test_data_handle)

最後組織提交格式。

result = pd.DataFrame({PassengerId:test_datas[PassengerId], Survived:pre_y.astype(np.int32)})result.to_csv(r"C:UsersaligeDesktopdemo.csv", index=False)

把生成csv在kaggle上submission,大功告成!提交後分數是0.81818,相當吉利(逃...其實還是有一些可以優化的點的,比如:

  1. 重點挖掘下姓名,家族與獲救間的關係
  2. Ticket連號票與獲救的關係
  3. 加入新的組合,乘客是否為母親(名字里含有Mrs及parch>0)
  4. 缺失值填補Cabin部分和Age部分再做細一些
  5. 嘗試模型融合,GBDT+XGBOOST做加權融合或最近比較流行的stack融合等

有興趣可以往這些方向多做嘗試。

最後附一張深圳天氣好的照片


推薦閱讀:

TAG:機器學習 | Kaggle | 數據挖掘 |