kaggle—first play—Titanic

 

 

玩了好久總算是又靜下心來好好看書,通過一段時間的學習,打算稍微檢驗一下知識的掌握程度,因此去kaggle參加了久聞的泰坦尼克生還預測,如下是正文。html

-----------------------------------------------------------------------------------------算法

一、觀察數據網絡

拿到數據集後,先來了解數據的大體狀況。dom

data.info()
data_des = data.describe() 

        

能夠得知數據集有12列,891行,其中'Age'、'Cabin'、'Embarked'列存在缺失值,全部樣本的平均生還率未0.383838;2等3等艙的人數比1等艙多;平均年齡爲29.6991歲等等。學習

同時明確了須要預測的結果,即'Survived'的預測,是個明顯的二分類問題,優先考慮邏輯迴歸、決策樹、神經網絡等算法。測試

如下爲各列的含義:優化

passengerid_乘客ID    survived_是否獲救(目標)    pclass_乘客等級
name_姓名    sex_性別    age_年齡(缺失)   sibsp_堂兄弟/妹個數    parch_父母/小孩個數   
ticket_船票信息    fare_票價    cabin_客艙號(缺失)    embarked_登船港口(缺失)spa

對數據分組對比,先觀察乘客等級、年齡、性別、登船港口與是否生還的關係:rest

#性別生還率:女性生還率74.2%,男性生還率18.9%
sex_survived = data.groupby(by=['Sex'])['Survived'].agg({'總人數':np.size, '生還人數':np.sum})
sex_survived['未生還人數'] = sex_survived['總人數'] - sex_survived['生還人數']
sex_survived['生還率'] = sex_survived['生還人數'] / sex_survived['總人數']
#乘客等級生還率:1級乘客生還率最高
pclass_survived = data.groupby(by=['Pclass'])['Survived'].agg({'總人數':np.size, '生還人數':np.sum})
pclass_survived['未生還人數'] = pclass_survived['總人數'] - pclass_survived['生還人數']
pclass_survived['生還率'] = pclass_survived['生還人數'] / pclass_survived['總人數']
#各年齡段生還率:0-10歲生還率最高,60歲以上生還率最低
bins = [0,10,20,30,40,50,60,70,80]
data['age_cut'] = pd.cut(data['Age'],bins,right=False)
age_survived = data.groupby(by=['age_cut'])['Survived'].agg({'總人數':np.size, '生還人數':np.sum})
age_survived['未生還人數'] = age_survived['總人數'] - age_survived['生還人數']
age_survived['生還率'] = age_survived['生還人數'] / age_survived['總人數']
#各登船港口生還率:C港生還率最高,S港人數最多、生還率最低
embarked_survived = data.groupby(by=['Embarked'])['Survived'].agg({'總人數':np.size, '生還人數':np.sum})
embarked_survived['未生還人數'] = embarked_survived['總人數'] - embarked_survived['生還人數']
embarked_survived['生還率'] = embarked_survived['生還人數'] / embarked_survived['總人數']

###可視化
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] =False

plt.subplot(221)  #將圖形區域分紅2行*2列,將圖形設置在第1個位置
plt.bar(sex_survived.index, sex_survived['生還人數'], color='b', alpha=0.7)
plt.bar(sex_survived.index, sex_survived['未生還人數'], bottom=sex_survived['生還人數'], color='lightblue')
plt.title('性別獲救狀況')
plt.ylabel('人數') 
plt.grid(b=True, which='major', axis='y')

plt.subplot(222)
plt.bar(pclass_survived.index, pclass_survived['生還人數'], color='b', alpha=0.7)
plt.bar(pclass_survived.index, pclass_survived['未生還人數'], bottom=pclass_survived['生還人數'], color='lightblue')
plt.xticks(pclass_survived.index)
plt.title('乘客等級獲救狀況')
plt.xlabel('乘客等級')
plt.ylabel('人數')
plt.grid(b=True, which='major', axis='y')

plt.subplot(223)
age_survived['age_index'] = age_survived.index.astype(str)
plt.bar(age_survived['age_index'], age_survived['生還人數'], color='b', alpha=0.7)
plt.bar(age_survived['age_index'], age_survived['未生還人數'], bottom=age_survived['生還人數'], color='lightblue')
plt.xticks(age_survived['age_index'])
plt.title('按年齡獲救狀況')
plt.xlabel('年齡分佈')
plt.ylabel('人數')                   
plt.grid(b=True, which='major', axis='y')

使用循環優化代碼後:code

#各個維度的生還率
bins = [0,10,20,30,40,50,60,70,80]
data['age_cut'] = pd.cut(data['Age'],bins,right=False)
dataframe = ['sex_survived', 'pclass_survived', 'age_survived' , 'embarked_survived']
columns = ['Sex', 'Pclass', 'age_cut', 'Embarked']

for name in dataframe:
    for i in range(0,4):
        dataframe[i] = data.groupby(by=[columns[i]])['Survived'].agg({'總人數':np.size, '生還人數':np.sum})
        dataframe[i]['未生還人數'] = dataframe[i]['總人數'] - dataframe[i]['生還人數']
        dataframe[i]['生還率'] = dataframe[i]['生還人數'] / dataframe[i]['總人數']
print(dataframe)
  
#畫圖
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] =False
dataframe[2]['age_index'] = dataframe[2].index.astype(str) 
dataframe[2] = dataframe[2].set_index(dataframe[2]['age_index'])

for j in range(0,4):
    plt.subplot(2,2,j+1)  #將圖形區域分紅2行*2列,將圖形設置在第1個位置
    plt.bar(dataframe[j].index, dataframe[j]['生還人數'], color='b', alpha=0.7)
    plt.bar(dataframe[j].index, dataframe[j]['未生還人數'], bottom=dataframe[j]['生還人數'], color='lightblue')
    plt.title(columns[j])
    plt.ylabel('人數') 
    plt.grid(b=True, which='major', axis='y')

獲得以下的圖形:(寶藍色爲獲救)

數據顯示:女性生還率74.2%,男性生還率18.9%;1級乘客生還率最高;0-10歲生還率最高,60歲以上生還率最低;C港生還率最高,S港人數最多、生還率最低

獲得結論:性別、年齡、乘客等級、登船港口都對是否獲救有較大影響。

另:船票價格與乘客等級相關較強,但與生還率的關係不明顯;堂兄弟、父母/小孩數量對生還結果沒有明顯影響。

 

二、數據處理

 1)年齡的缺失項

因爲年齡對因而否生還的影響仍是比較明顯,且缺失較多(缺失177個,接近20%),因此不能直接忽略缺失項或對缺失項作簡單的均值、中位數等替換。

這裏考慮使用隨機森林對年齡進行預測填補:

https://scikit-learn.org/dev/modules/generated/sklearn.ensemble.RandomForestRegressor.html(隨機森林官方文檔)

#對年齡缺失項作隨機森林進行填補
age_data = data[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]
fcolumns = ['Fare', 'Parch', 'SibSp', 'Pclass']
tcolumns = ['Age']

age_data_known = age_data[age_data.Age.notnull()]
age_data_unknown = age_data[age_data.Age.isnull()]

fdata = age_data_known[fcolumns]#特徵變量
tdata = age_data_known[tcolumns]#目標變量

from sklearn.ensemble import RandomForestRegressor
rfrmodel = RandomForestRegressor(n_jobs=-1)
rfrmodel.fit(fdata, tdata )

predictedAges = rfrmodel.predict(age_data_unknown[fcolumns])
data.loc[data['Age'].isnull(), 'Age'] = predictedAges

#對登船港口的2個缺失項用衆數進行填補
data.loc[data['Embarked'].isnull(), 'Embarked'] = 'S'

2)非數值型特徵的虛擬化

因爲性別、登船港口還都是字符型數據,因此須要對這兩個特徵作虛擬變換

#設置訓練集及虛擬變量
data_train = pd.DataFrame([])
data_train[['ID', 'age', 'pclass', 'sibsp', 'parch', 'fare', 'survived']] = data[['PassengerId', 'Age','Pclass','SibSp','Parch','Fare','Survived']]
#性別
data_train[['sex_female','sex_male']] = pd.get_dummies(data['Sex'])
#登船港口
data_train[['embarked_C','embarked_Q','embarked_S']] = pd.get_dummies(data['Embarked'])
data_train = data_train.set_index('ID')

3)數值特徵標準化

因爲年齡、船票價格兩個特徵跨度很大,因此對這兩個特徵作標準化處理

import sklearn.preprocessing as preprocessing
scaler = preprocessing.MinMaxScaler()
data_train['age'] = scaler.fit_transform(np.array(data_train['age']).reshape(891,-891))
data_train['fare'] = scaler.fit_transform(np.array(data_train['fare']).reshape(891,-891))

 

三、模型創建

首先使用邏輯迴歸模型

https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html(邏輯迴歸官方文檔)

from sklearn import linear_model
lrModel = linear_model.LogisticRegression(penalty='l1')

inputcolumns = ['age', 'pclass', 'sibsp', 'parch', 'fare', 'sex_female',
       'sex_male', 'embarked_C', 'embarked_Q', 'embarked_S']
outpucolumns = ['survived']

lrModel.fit(data_train[inputcolumns], data_train[outpucolumns])
lrModel.score(data_train[inputcolumns], data_train[outpucolumns])#模型評分0.8

 

四、測試集處理

data2 = pd.read_csv(r'D:\kaggle\datafile\titanic\test.csv')
data2.info()#年齡缺失,船票價格存在一個缺失項
data2.loc[data2['Fare'].isnull(), 'Fare'] = data2['Fare'].mean()
#年齡缺失項處理
age_data2 = data2[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]
age_data2_known = age_data2[age_data2.Age.notnull()]
age_data2_unknown = age_data2[age_data2.Age.isnull()]

fdata2 = age_data2_known[fcolumns]#特徵變量
tdata2 = age_data2_known[tcolumns]#目標變量

rfrmodel.fit(fdata2, tdata2)
predictedAges2 = rfrmodel.predict(age_data2_unknown[fcolumns])
data2.loc[data2['Age'].isnull(), 'Age'] = predictedAges2
#構建訓練集
data_test = pd.DataFrame([])
data_test[['ID', 'age', 'pclass', 'sibsp', 'parch', 'fare']] = data2[['PassengerId', 'Age','Pclass','SibSp','Parch','Fare']]
#虛擬變量
data_test[['sex_female','sex_male']] = pd.get_dummies(data2['Sex'])#性別
data_test[['embarked_C','embarked_Q','embarked_S']] = pd.get_dummies(data2['Embarked'])#登船港口
#數值標準化
data_test['age'] = scaler.fit_transform(np.array(data_test['age']).reshape(418,-418))
data_test['fare'] = scaler.fit_transform(np.array(data_test['fare']).reshape(418,-418))
#獲得測試集預測結果
predictions = lrModel.predict(data_test[inputcolumns])
result = pd.DataFrame({'PassengerId':data_test['PassengerId'], 'Survived':predictions})

 如此就可以獲得初步預測的結果了,後續會更新後面的優化等。

相關文章
相關標籤/搜索