Kaggle入門-泰坦尼克號乘客生存預測
Kaggle是一個數據分析建模的應用競賽平台,企業或者研究者可以將問題背景、數據、期望指標等發布到Kaggle上,以競賽的形式向廣大的數據科學家徵集解決方案。熱愛數據挖掘的小夥伴們可以下載項目數據,使用統計/機器學習/數據挖掘等知識,建立演算法模型,得出結果並提交。所以,想轉行到數據分析的小夥伴,可以通過Kaggle上的項目來提升實戰經驗。
為什麼Kaggle對找工作有幫助?如何入門?1 項目背景
泰坦尼克號是一艘奧林匹克級郵輪,於1912年4月處女航時撞上冰山後沉沒。泰坦尼克號由位於愛爾蘭島貝爾法斯特的哈蘭德與沃爾夫造船廠興建,是當時最大的客運輪船。在它的處女航中,泰坦尼克號從英國南安普敦出發,途經法國瑟堡-奧克特維爾以及愛爾蘭昆士敦,計劃中的目的地為美國紐約。1912年4月14日,船上時間夜裡11時40分,泰坦尼克號撞上冰山;4月15日凌晨2時20分,船裂成兩半後沉入大西洋。泰坦尼克號海難為和平時期死傷人數最慘重的海難之一。船上1500多人喪生。
2 提出問題
- 影響乘客生還率的因素有哪些;
- 預測乘客的生存情況。
3 數據採集
kaggle上下載數據,鏈接如下:
Titanic: Machine Learning from Disastertrain數據用來訓練模型,其中包含了乘客的生存信息。
test數據中沒有乘客的生存信息,這就是我們要預測的。
4 理解數據
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsimport warningswarnings.filterwarnings(ignore)%matplotlib inlinetrain=pd.read_csv(C:/coben/data/train.csv)test=pd.read_csv(C:/coben/data/test.csv)print(訓練數據集:,train.shape,測試數據集:,test.shape)訓練數據集: (891, 12) 測試數據集: (418, 11)train.head(5)
test.head(5)
#合併之後同時處理兩個數據集full=train.append(test,ignore_index=True)full.info()
- Cabin有1014條缺失值;
- Age有263條缺失值;
- Fare有1條缺失值;
- Embarked有2條缺失值。
5 數據預處理
4.1 Fare缺失值處理
用Fare平均值將缺失數據填充。
full[Fare]=full[Fare].fillna(full[Fare].mean())
4.2 Age缺失值處理
Age缺失值很多,可以用隨機森林預測填充缺失值。
# 1表示male,0表示female,用來預測缺失Agesex_mapDict={male:1,female:0}full[Sex]=full[Sex].map(sex_mapDict)from sklearn.ensemble import RandomForestRegressorageDf=full[[Age,Sex,Fare, Parch, SibSp, Pclass]]ageDf_notnull=ageDf.loc[(full.Age.notnull())]ageDf_isnull=ageDf.loc[(full.Age.isnull())]X=ageDf_notnull.values[:,1:]Y=ageDf_notnull.values[:,0]rfr=RandomForestRegressor(n_estimators=1000, n_jobs=-1)rfr.fit(X,Y)predictAges=rfr.predict(ageDf_isnull.values[:, 1:])full.loc[(full.Age.isnull()),Age]=predictAges
4.3 Embarked缺失值處理
full[Embarked].value_counts()
# 用最多的S將Embarked缺失值填充full[Embarked]=full[Embarked].fillna(S)
4.4 Cabin缺失值處理
# Cabin缺失值太多,也許缺失也是一種信息,先用U標記full[Cabin]=full[Cabin].fillna(U)
6 影響乘客生還率的因素分析
6.1 Sex vs Survived
ax=sns.factorplot(x=Survived,col=Sex,col_wrap=2, data=full.loc[0:890,:],kind=count, size=4, aspect=0.8)
- 男性的生還率遠低於女性,外國朋友還是很紳士的,lady first!!
6.2 Pclass vs Survived
ax=sns.factorplot(x=Survived,col=Pclass,col_wrap=3, data=full.loc[0:890,:],kind=count, size=4, aspect=0.8)
- 1等客艙生還人數高於遇難人數;
- 2等客艙遇難人數略高於生還人數;
- 3等客艙遇難人數遠高於生還人數。
6.3 Embarked vs Survived
ax=sns.factorplot(x=Survived,col=Embarked,col_wrap=3, data=full.loc[0:890,:],kind=count, size=4, aspect=0.8)
- 南安普頓上船的乘客,遇難人數是生還人數的兩倍;
- 看來上船港口對生還率也有一定的影響,但是不知道為什麼...(智商捉急啊!)
6.4 Parch vs Survived
ax=sns.factorplot(x=Survived,col=Parch,col_wrap=4, data=full.loc[0:890,:],kind=count, size=4, aspect=0.8)
- 船上沒有父母或者子女的乘客,生還率比較低。
6.5 SibSp vs Survived
ax=sns.factorplot(x=Survived,col=SibSp,col_wrap=4, data=full.loc[0:890,:],kind=count, size=4, aspect=0.8)
- 船上沒有兄弟姐妹或者配偶的乘客,生還率比較低;
- 通過上面兩組對比,可以推測獨自一人在船上的乘客,遇難的可能性比較大。
6.6 Age vs Survived
fig,ax1=plt.subplots(1,1,figsize=(25,4))average_age=full.loc[0:890,:][[Age, Survived]].groupby([Age],as_index=False).mean()sns.barplot(x=Age,y=Survived,data=average_age)
- Age從小到大的生還率對比,肉眼好像看不出什麼信息。
full.loc[0:890,:][Age].describe()
# 進一步分析年齡bins=[0,3,12,18,30,40,50,65,80]full[Age_group]=pd.cut(full[Age],bins)by_age=full.loc[0:890,:].groupby(Age_group)[Survived].mean()by_age
by_age.plot(kind=bar)
- 0~12的嬰兒和兒童生還率遠高於其餘年齡層的乘客;
- 讓女人和小孩先走!!給外國朋友點贊!!
6.7 Fare vs Survived
fig,ax1=plt.subplots(1,1,figsize=(25,4))average_fare=full.loc[0:890,:][[Fare, Survived]].groupby([Fare],as_index=False).mean()sns.barplot(x=Fare,y=Survived,data=average_fare)
- 票價從低到高的生還率對比,肉眼也看不出什麼信息。
full.loc[0:890,:][Fare].describe()
bins=[0,150,300,513]full[Fare_group]=pd.cut(full[Fare],bins)by_fare=full.loc[0:890,:].groupby(Fare_group)[Survived].mean()by_fareby_fare.plot(kind=bar)
by_fare.plot(kind=bar)
- 票價從低到高,生化率明顯上升;
- 300~513票價的乘客,生還率達到了100%;
- 趕緊去賺錢,才是正事啊!!
7 特徵工程
特徵工程(feature engineering)真的很重要!!
特徵工程(feature engineering)真的很重要!!
特徵工程(feature engineering)真的很重要!!
7.1 Embarked
#One-hotembarkedDf=pd.DataFrame()embarkedDf=pd.get_dummies(full[Embarked],prefix=Embarked)embarkedDf.head()
7.2 Title
# 姓名 裡面包含頭銜,可能對生還率有影響。有沒有讓領導先走的情況??def getTitle(name): str1=name.split(,)[1] str2=str1.split(.)[0] str3=str2.strip() return str3titleDf=pd.DataFrame()titleDf[Title]=full[Name].map(getTitle)titleDf.head()
#看一下titleDf中有哪些頭銜分類from collections import CounterCounter(titleDf[Title])
# 將頭銜統一化處理title_Dict={}title_Dict.update(dict.fromkeys([Capt, Col, Major, Dr, Rev], Officer))title_Dict.update(dict.fromkeys([Don, Sir, the Countess, Dona, Lady,Jonkheer], Royalty))title_Dict.update(dict.fromkeys([Mme, Ms, Mrs], Mrs))title_Dict.update(dict.fromkeys([Mlle, Miss], Miss))title_Dict.update(dict.fromkeys([Mr], Mr))title_Dict.update(dict.fromkeys([Master], Master))titleDf[Title]=titleDf[Title].map(title_Dict)
7.3 Cabin
cabinDf=pd.DataFrame()full[Cabin]=full[Cabin].map(lambda c:c[0])cabinDf=pd.get_dummies(full[Cabin],prefix=Cabin)cabinDf.head()
7.4 Pclass
# 客艙等級pclassDf=pd.DataFrame()pclassDf=pd.get_dummies(full[Pclass],prefix=Pclass)pclassDf.head()
7.5 FamilySize
# FamilySizefamilyDf=pd.DataFrame()familyDf[FamilySize]=full[Parch]+full[SibSp]+1familyDf.head()familyDf[Family_Single]=familyDf[FamilySize].map(lambda x:1 if x==1 else 0)familyDf[Family_Small]=familyDf[FamilySize].map(lambda x:1 if 2<=x<=4 else 0)familyDf[Family_Large]=familyDf[FamilySize].map(lambda x:1 if 5<=x else 0)familyDf.head()
7.6 Age_group
age_groupDf=pd.DataFrame()age_groupDf=pd.get_dummies(full[Age_group],prefix=Age_group)age_groupDf.head()
7.7 Fare_group
fare_groupDf=pd.DataFrame()fare_groupDf=pd.get_dummies(full[Fare_group],prefix=Fare_group)fare_groupDf.head()
7.8 特徵選擇
full.head()
full=pd.concat([full,embarkedDf,titleDf,cabinDf,pclassDf,familyDf,age_groupDf,fare_groupDf],axis=1)full.drop([Cabin,Embarked,Name,Pclass,Ticket,Age_group,Fare_group],axis=1,inplace=True)full.head()
8 構建模型
8.1 邏輯回歸
#構建模型sourceRow=891source_X=full.drop([Survived],axis=1).loc[0:sourceRow-1,:]source_y=full.loc[0:sourceRow-1,Survived]pred_X=full.drop([Survived],axis=1).loc[sourceRow:,:]from sklearn.cross_validation import train_test_splittrain_X,test_X,train_y,test_y=train_test_split(source_X, source_y, train_size=0.8)from sklearn.linear_model import LogisticRegressionmodel=LogisticRegression()model.fit(train_X,train_y)#模型評估model.score(test_X,test_y)#方案實施pred_Y=model.predict(pred_X)pred_Y=pred_Y.astype(int)passenger_id=full.loc[sourceRow:,PassengerId]predDf=pd.DataFrame( {PassengerId:passenger_id, Survived:pred_Y})predDf=predDf.reset_index(drop=True)predDf.to_csv(titanic_pred.csv,index=False)
8.2 隨機森林
train_X=full.drop([Survived],axis=1).loc[0:890]train_Y=full[Survived].loc[0:890]test_X=full.drop([Survived],axis=1).loc[891:]from sklearn.linear_model import LogisticRegressionfrom sklearn import cross_validationalg=LogisticRegression(random_state=1)scores=cross_validation.cross_val_score( alg, train_X, train_Y, cv=3)print(scores.mean())from sklearn.ensemble import RandomForestClassifieralg=RandomForestClassifier( random_state=1, n_estimators=150, min_samples_split=4, min_samples_leaf=2)scores=cross_validation.cross_val_score( alg, train_X, train_Y, cv=3)print(scores.mean())# 導出預測結果alg.fit(train_X,train_Y)predictions=alg.predict(test_X)submission=pd.DataFrame({PassengerId:test_X[PassengerId],Survived:predictions})submission=submission.astype(int)submission=submission.reset_index(drop=True)submission.to_csv(titanic_pred.csv,index=False)
9 結果
上傳到kaggle上排名3494,成績一般。以後對機器學習建模理解更多了,再來提高成績。
推薦閱讀:
※一些關於kaggle的比賽方法
※Python機器學習小試...泰坦尼克號開啟的kaggle入門
※Kaggle發布首份數據科學&機器學習從業者現狀調查
※kaggle小黃車競賽 得分:0.41038