Kaggle入門項目之泰坦尼克之災獲救預測
1.案例背景
1912年發生的泰坦尼克之災導致游輪上大部分乘客不幸遇難,乘客中有上流人士和底層群眾,有男女有老幼。事實上,獲救人群並不是隨機的,而是遵循了一定的規律。我們掌握了乘客的部分信息,可以利用機器學習的方法探索乘客獲救的規律並預測其在事故中的生存情況。
數據來源於Kaggle項目提供的Titanic數據集:Titanic:Machine Learning from Disaster
2.分析思路
(1)採集及導入數據
(2)理解數據:對數據進行描述性分析
(3)數據清洗:缺失值處理及特徵工程(feature engineering)
(4)建立模型並預測
(5)提交預測結果
3.數據分析及建模
3.1 導入數據包
import pandas as pd #數據分析import numpy as np from pandas import Series,DataFramedata_train = pd.read_csv ("E:\train.csv")data_test=pd.read_csvdata_train
導入數據源後可看到我們的數據如下圖
那麼這些列名分別表示什麼含義呢?
- Survived => 生存情況(1=存活,0=死亡)
- PassengerId => 乘客ID
- Pclass => 乘客等級(1/2/3等艙位)
- Name => 乘客姓名
- Sex => 性別
- Age => 年齡
- SibSp => 兄弟姐妹數/配偶數
- Parch => 父母與小孩個數
- Ticket => 船票信息
- Fare => 票價
- Cabin => 客艙
- Embarked => 登船港口
3.2 對練習數據進行描述性分析
#查看數據整體情況data_train.info()
我們可以看到年齡和船艙號有缺失值,稍後我們會用一定的數據處理方法將其補全。
#查看數據數值情況data_train.describe()
#導入Python繪圖庫,對數據進行可視化分析import matplotlib.pyplot as pltfig = plt.figure()fig.set(alpha=0.2) # 設定圖表顏色alpha參數#查看獲救總人數plt.subplot2grid((2,3),(0,0)) data_train.Survived.value_counts().plot(kind=bar)# 柱狀圖 plt.title(u"獲救情況 (1為獲救)")plt.ylabel(u"人數")
#查看乘客等級分布plt.subplot2grid((2,3),(0,1)) #第二張圖data_train.Pclass.value_counts().plot(kind="bar")plt.ylabel(u"人數") # 設定縱坐標名稱plt.title(u"乘客等級分布")
#按年齡看獲救分布plt.subplot2grid((2,3),(0,2))plt.scatter(data_train.Survived, data_train.Age)plt.ylabel(u"年齡") plt.grid(b=True, which=major, axis=y) plt.title(u"按年齡看獲救分布 (1為獲救)")
#查看各等級的乘客年齡分布plt.subplot2grid((2,3),(1,0), colspan=2)data_train.Age[data_train.Pclass == 1].plot(kind=kde) #密度圖data_train.Age[data_train.Pclass == 2].plot(kind=kde)data_train.Age[data_train.Pclass == 3].plot(kind=kde)plt.xlabel(u"年齡")# plots an axis lableplt.ylabel(u"密度") plt.title(u"各等級的乘客年齡分布")plt.legend((u頭等艙, u2等艙,u3等艙),loc=best) # sets our legend for our graph.
可能由於財富會隨著年齡累計,因此2/3等艙的乘客更趨向年輕化。
#查看各登船口岸上船人數plt.subplot2grid((2,3),(1,2))data_train.Embarked.value_counts().plot(kind=bar)plt.title(u"各登船口岸上船人數")plt.ylabel(u"人數")
由於南安普頓是始發站,因此在此港口登船人數最多。
#查看不同等級乘客的獲救情況fig = plt.figure()fig.set(alpha=0.2) # 設定圖表顏色alpha參數Survived_0 = data_train.Pclass[data_train.Survived == 0].value_counts()Survived_1 = data_train.Pclass[data_train.Survived == 1].value_counts()df=pd.DataFrame({u獲救:Survived_1, u未獲救:Survived_0})df.plot(kind=bar, stacked=True)plt.title(u"各乘客等級的獲救情況")plt.xlabel(u"乘客等級") plt.ylabel(u"人數") plt.show()
可以看出不同等級艙位對獲救與否有較大影響,頭等艙獲救概率>二等艙>三等艙,該變數應該引起關注。
#查看不同性別的獲救情況fig = plt.figure()fig.set(alpha=0.2) # 設定圖表顏色alpha參數Survived_m = data_train.Survived[data_train.Sex == male].value_counts()Survived_f = data_train.Survived[data_train.Sex == female].value_counts()df=pd.DataFrame({u男性:Survived_m, u女性:Survived_f})df.plot(kind=bar, stacked=True)plt.title(u"按性別看獲救情況")plt.xlabel(u"性別") plt.ylabel(u"人數")plt.show()
發現女性獲救概率遠高於男性,看來在這場災難中女士優先踐行的很好。
# 查看各港口乘客的獲救情況fig = plt.figure()fig.set(alpha=0.2) # 設定圖表顏色alpha參數Survived_0 = data_train.Embarked[data_train.Survived == 0].value_counts()Survived_1 = data_train.Embarked[data_train.Survived == 1].value_counts()df=pd.DataFrame({u獲救:Survived_1, u未獲救:Survived_0})df.plot(kind=bar, stacked=True)plt.title(u"各港口乘客的獲救情況")plt.xlabel(u"港口") plt.ylabel(u"人數") plt.show()
並沒有直觀看出登船港口對獲救情況的影響,該變數需要進一步處理和分析。
3.3 數據清洗
# 導入數據集test,並與train合併,便於數據清洗data_test = pd.read_csv ("E:\test.csv")full=data_train.append(data_test,ignore_index=True)print(合併數據集:,full.shape)
合併數據集: (1309, 12)
full.info() #查看合併後的缺失數據
發現Age,Fare,Embarked,Cabin有數據缺失,根據其數據缺失程度不同,選擇不同的處理方法。
# 缺失數量較少的數值型數據,使用平均值填補缺失值full[Age]=full[Age].fillna(full[Age].mean())full[Fare]=full[Fare].fillna(full[Fare].mean())# 缺失值較少的分類數據,使用出現次數最多的S填補full[Embarked]=full[Embarked].fillna(S)# 缺失較多的Cabin,用特徵因子化法根據數據存在與否賦予其yesorno兩個屬性def set_Cabin_type(df): df.loc[ (df.Cabin.notnull()), Cabin ] = "Yes" df.loc[ (df.Cabin.isnull()), Cabin ] = "No" return dffull = set_Cabin_type(full)
缺失的數據已經填補完畢,但數據清洗並沒有結束。由於在邏輯回歸建模時輸入的數據都需要是數值型數據,因此可以通過處理將類目屬性轉化為0,1的數值屬性。
# 用pandas中的get_dummies對類目進行one-hot編碼CabinDf = pd.get_dummies(full[Cabin], prefix= Cabin)EmbarkedDf = pd.get_dummies(full[Embarked], prefix= Embarked)SexDf = pd.get_dummies(full[Sex], prefix= Sex)PclassDf = pd.get_dummies(full[Pclass], prefix= Pclass)
分類數據已經處理完畢,接下來處理字元串——姓名。觀察原始數據後發現Name中包含不同的頭銜,嘗試提取出特徵用於建模。
# 使用split進行分割def getTitle(name): str1=name.split( , )[1] str2=str1.split( . )[0] #strip() 方法用於移除字元串頭尾指定的字元(默認為空格) str3=str2.strip() return str3titleDf = pd.DataFrame()titleDf[Title] = full[Name].map(getTitle)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", }titleDf[Title] = titleDf[Title].map(title_mapDict)titleDf = pd.get_dummies(titleDf[Title])titleDf.head()
# 連接定義的新屬性df = pd.concat([full, CabinDf, EmbarkedDf, SexDf, PclassDf,titleDf], axis=1)# 刪除不需要的值df.drop([Pclass, Sex, Ticket, Cabin, Embarked,Name], axis=1, inplace=True)df #查看數據
數值屬性已全部轉化完畢,但此時發現Age和Fare兩個變數和其他變數數值差距較大,可能會造成回歸時不能很好的處理,因此要對這兩個變數做收斂處理。
# 引入scikit-learn裡面的preprocessing模塊對其進行scaling,把數值變化範圍縮小到[-1,1]import sklearn.preprocessing as preprocessingscaler = preprocessing.StandardScaler()df[Age] = scaler.fit_transform(df[Age].values.reshape(-1, 1))df[Fare] = scaler.fit_transform(df[Fare].values.reshape(-1, 1))df
3.4 建立模型並預測
# 查看相關係數矩陣corrDf = df.corr() corrDf
# 根據相關係數降序排列corrDf[Survived].sort_values(ascending =False)
# 選取以下特徵組成數據框放入變數df_X中df_X = pd.concat( [titleDf,#頭銜 PclassDf,#客艙等級 df[Age],#年齡 df[Fare],#船票價格 CabinDf,#船艙號 EmbarkedDf,#登船港口 SexDf#性別 ] , axis=1 )df_X.head()
sourceRow=891source_X = df_X.loc[0:sourceRow-1,:]#原始數據集source_y = df.loc[0:sourceRow-1,Survived] print(原始數據集行數:,source_X.shape[0])#預測數據集大小print(預測數據集有行數:,pred_X.shape[0])
原始數據集有行數: 891
預測數據集有行數: 418from 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)
原始數據集特徵: (891, 17) 訓練數據集特徵: (712, 17) 測試數據集特徵: (179, 17)
原始數據集標籤: (891,) 訓練數據集標籤: (712,) 測試數據集標籤: (179,)建立模型,進行邏輯回歸:
from sklearn.linear_model import LogisticRegressionmodel = LogisticRegression()model.fit( train_X , train_y )
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
intercept_scaling=1, max_iter=100, multi_class=ovr, n_jobs=1, penalty=l2, random_state=None, solver=liblinear, tol=0.0001, verbose=0, warm_start=False)model.score(test_X , test_y )#0.8547486033519553
進行結果預測:
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.shapepredDf.head()#保存結果到指定路徑predDf.to_csv( E:\titanic_pred.csv , index = False )
3.5 提交預測
推薦閱讀:
※kaggle小黃車競賽 得分:0.41038
※Zillow簡介(二)如何重構經紀行業的產業鏈?
※Kaggle入門系列:(二)Kaggle簡介
※Titanic: kaggle入門實踐-top10%(附Python代碼)