Kaggle-Titanic生還預測(Top5%)代碼分享
來自專欄天池&kaggle4 人贊了文章
Titanic作為kaggle的極佳入門賽事,受到眾多數據挖掘愛好者的關注,通過性別、年齡、船票、船艙位置、票價等特徵預測乘客最後是否生還,項目涵蓋了數據挖掘常用如缺失值填補、離散變數轉換、特徵組合等方法。雖說是入門項目,然而想跑高分也不是那麼容易...本方案最後得分0.81818,排名434/9774。在此就分析總體思路、數據預處理方式、特徵工程、模型選擇方面做介紹。
kernel上傳GitHub:
alige32/Kaggle-Titanic-kernel數據分析三件套!
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),只有兩個缺失值,考慮根據現有的其他特徵推測一下。
缺失值初步分析完畢,讓我們看一下各特徵與最後結果的關係吧!
畫圖分析到此,特徵數值化應該應該有了一個思路。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()
先這樣吧!
最後模型選擇了隨機森林、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,相當吉利(逃...其實還是有一些可以優化的點的,比如:
- 重點挖掘下姓名,家族與獲救間的關係
- Ticket連號票與獲救的關係
- 加入新的組合,乘客是否為母親(名字里含有Mrs及parch>0)
- 缺失值填補Cabin部分和Age部分再做細一些
- 嘗試模型融合,GBDT+XGBOOST做加權融合或最近比較流行的stack融合等
有興趣可以往這些方向多做嘗試。
最後附一張深圳天氣好的照片
推薦閱讀: