本次筆記主要記錄了一個機器學(xué)習(xí)的入門實戰(zhàn)者填,泰坦尼克號生存預(yù)測刻伊。主要涉及的知識點有,python的pandas包描验,機器學(xué)習(xí)包sklearn白嘁。
背景知識:
泰坦尼克號是英國一艘奧林匹克級郵輪,在1912年4月10日膘流,從南安普頓港碼頭出發(fā)絮缅,途徑法國和愛爾蘭,在駛向美國紐約的時候呼股,與一座冰山相撞耕魄,最終沉沒。在2224名船員及乘客中彭谁,逾1500人喪生吸奴。本次案例主要是通過機器學(xué)習(xí)方法對418人的生存狀況進行預(yù)測。案例取自kaggle: https://www.kaggle.com/c/titanic缠局。同時则奥,kaggle上提供了泰坦尼克號案例的訓(xùn)練集train.csv和測試集test.csv。
一甩鳄、提出問題
數(shù)據(jù)取自kaggle逞度,本次問題主要是探究泰坦尼克號中,各個特征與生存狀況的關(guān)系妙啃,并利用機器學(xué)習(xí)方法對生存狀況進行預(yù)測档泽。
二俊戳、 理解數(shù)據(jù)
首先導(dǎo)入數(shù)據(jù)集train.csv和test.csv:
import pandas as pd
import numpy as np
#導(dǎo)入訓(xùn)練集
train = pd.read_csv("train.csv")
#導(dǎo)入測試集
test = pd.read_csv("test.csv")
#查看測試集和訓(xùn)練集數(shù)據(jù)形狀
print("Train data: ",train.shape)
print("Test data: ",test.shape)
full=train.append(test,ignore_index=True,sort=False)
print("Full data:", full.shape)
full.head()
由以上代碼可以得出,訓(xùn)練數(shù)據(jù)為891行馆匿,12個字段抑胎,測試數(shù)據(jù)為418行,11個字段渐北,缺少的這一行字段便是要預(yù)測的生存狀況阿逃。
以下給出12個字段的含義解釋:
1. PassengerId:乘客ID
2. Survived:生存狀況;1:生存赃蛛;死亡:0
3. Pclass:船艙等級恃锉;1:一等;2:二等呕臂;3:三等
4. Name:乘客姓名
5. Sex:乘客性別
6. Age:乘客年齡
7. SibSp:乘客的兄弟姐妹以及配偶數(shù)量
8. Parch:乘客的父母與子女?dāng)?shù)量
9. Ticket:票的編號
10. Fare:船票費用
11. Cabin:乘客船艙座位號
12. Embarked:乘客登船的港口破托,有三個可選值:S:南安普頓,C:法國瑟堡Q:愛爾蘭昆士敦
full.info()
--------------------------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 12 columns):
PassengerId 1309 non-null int64
Survived 891 non-null float64
Pclass 1309 non-null int64
Name 1309 non-null object
Sex 1309 non-null object
Age 1046 non-null float64
SibSp 1309 non-null int64
Parch 1309 non-null int64
Ticket 1309 non-null object
Fare 1308 non-null float64
Cabin 295 non-null object
Embarked 1307 non-null object
dtypes: float64(3), int64(4), object(5)
memory usage: 122.8+ KB
通過分析可以得出歧蒋,總數(shù)據(jù)為1309土砂,其中Survived, Age, Fare, Cabin, Embarked均有缺失值,其中Survived的缺失值是所需要求的生存狀況谜洽,其他值則需要通過數(shù)據(jù)清洗的方法來補全萝映。
三、數(shù)據(jù)清洗
- Fare為數(shù)值類型阐虚,缺失值為1序臂,因此采用平均值進行填充。
- Embarked為字符串類型敌呈,缺失值為2贸宏,因此采用眾數(shù)進行填充。
- Cabin為字符串類型磕洪,缺失過多,缺失值為1014诫龙,缺失率為77.46%析显,原因可能為很多乘客沒有艙位號,因此將缺失值用U來替代签赃,表示未知谷异。
- Age為數(shù)值類型,缺失值為263锦聊,本次采用平均值進行填充歹嘹,由于年齡對于生存影響可能相對較大,因此下次會介紹如何使用機器學(xué)習(xí)方法進行填充孔庭。
# Fare缺失值填充
full.Fare = full.Fare.fillna(full.Fare.mean())
# Embarked缺失值填充
full.Embarked = full.Embarked.fillna(full.Embarked.mode()[0])
# Cabin缺失值填充
full.Cabin = full.Cabin.fillna('U')
# Age本次使用平均值填充
full.Age = full.Age.fillna(full.Age.mean())
在處理完缺失值以后尺上,還需要對字符串類型的數(shù)值進行one-hot編碼材蛛,方便機器學(xué)習(xí)算法識別。這里對Sex, Cabin, Embarked進行重新編碼怎抛。
# 對Sex進行編碼
sex = {'male':1,'female':0}
sex_num = full.Sex.map(sex)
sex_num.head()
# 對Embarked進行編碼
embarked = pd.DataFrame()
embarked = pd.get_dummies(full.Embarked,prefix="Embarked")
embarked.head()
# 對Pcclass進行編碼
pclass = pd.DataFrame()
pclass = pd.get_dummies(full.Pclass,prefix="Pclass")
pclass.head()
接下來將對名字的頭銜進行提取卑吭,因為不同的頭銜和職位可能會對生存情況產(chǎn)生影響。同時马绝,在提取名字頭銜后豆赏,會定義一個新字典作為身份,用來映射頭銜與身份的關(guān)系富稻,并對身份進行one-hot編碼掷邦。
# 提取名字中的頭銜
title = pd.DataFrame()
title['title'] = full.Name.map(lambda name:name.split(',')[1].split('.')[0].strip())
# 用groupby方法列出各種頭銜
title.groupby('title').count()
# 創(chuàng)建身份字典
position = {
'Capt':'Officer',
'Col':'Officer',
'Dr' :'Officer',
'Don':'Royalty',
'Dona':'Royalty',
'Jonkheer':'Royalty',
'Lady':'Miss',
'Major':'Officer',
'Master':'Master',
'Mlle':'Miss',
'Mme':'Mrs',
'Mr':'Mr',
'Mrs':'Mrs',
'Ms':'Miss',
'Rev':'Officer',
'Sir':'Royalty',
'the Countess':'Royalty'
}
# 將字典映射到頭銜上
title['title'] = title['title'].map(position)
------------------------------
title
Master 61
Miss 5
Mr 757
Mrs 198
Officer 23
Royalty 5
Name: Name, dtype: int64
# 進行one-hot編碼
title = pd.get_dummies(title['title'])
完成上述步驟后,可以獲得one-hot表格如下:
接下來對Cabin列進行分類處理椭赋,首先提取首字母抚岗,然后按照首字母進行one-hot編碼。
# 提取cabin首字母
cabin = full.Cabin.map(lambda cabin:cabin[0])
# 進行one-hot編碼
cabin = pd.get_dummies(cabin,prefix='Cabin')
Parch字段和SibSp字段纹份,其實可以歸類為家庭成員的個數(shù)苟跪,可以將兩者相加組成一個新字段作為家庭成員數(shù)量
family = full.Parch+full.SibSp +1
最后,將原始數(shù)據(jù)復(fù)制保留一份蔓涧,并將重新編碼的字段包括(Pclass, Name,Sex,Age,SibSp,Parch,Cabin,Embarked)以及無用字段Ticket刪除件已。
# 復(fù)制一份原始數(shù)據(jù)
full_origin = train.append(test,ignore_index=True,sort=False)
# 建立一份新數(shù)據(jù)繼續(xù)繼續(xù)操作
full_data = full
# 刪除無用字段及重新編碼字段
full_data = full_data.drop(['Cabin','Name','Sex','Pclass','Embarked','Parch','SibSp','Ticket'],axis=1)
# 將重新編碼后的字段加入新數(shù)據(jù)
full_data = pd.concat([full_data,sex_num,embarked,pclass,title,cabin,family],axis=1)
# 最終得到數(shù)據(jù)如下
--------------------------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 27 columns):
PassengerId 1309 non-null int64
Survived 891 non-null float64
Age 1309 non-null float64
Fare 1309 non-null float64
Sex 1309 non-null int64
Embarked_C 1309 non-null uint8
Embarked_Q 1309 non-null uint8
Embarked_S 1309 non-null uint8
Pclass_1 1309 non-null uint8
Pclass_2 1309 non-null uint8
Pclass_3 1309 non-null uint8
Master 1309 non-null uint8
Miss 1309 non-null uint8
Mr 1309 non-null uint8
Mrs 1309 non-null uint8
Officer 1309 non-null uint8
Royalty 1309 non-null uint8
Cabin_A 1309 non-null uint8
Cabin_B 1309 non-null uint8
Cabin_C 1309 non-null uint8
Cabin_D 1309 non-null uint8
Cabin_E 1309 non-null uint8
Cabin_F 1309 non-null uint8
Cabin_G 1309 non-null uint8
Cabin_T 1309 non-null uint8
Cabin_U 1309 non-null uint8
Family 1309 non-null int64
dtypes: float64(3), int64(3), uint8(21)
memory usage: 88.3 KB
四、 建模與評估
- 首先利用corr()函數(shù)建立相關(guān)系數(shù)矩陣元暴,并提取出生存字段的相關(guān)系數(shù)并進行排序篷扩。
# 建立相關(guān)系數(shù)矩陣
corrDf = full_data.corr()
# 對生存字段的相關(guān)系數(shù)進行排序
print(corrDf['Survived'].sort_values(ascending=False))
----------------------------------------
Survived 1.000000
Mrs 0.341994
Pclass_1 0.285904
Fare 0.257307
Cabin_B 0.175095
Embarked_C 0.168240
Cabin_D 0.150716
Cabin_E 0.145321
Cabin_C 0.114652
Pclass_2 0.093349
Master 0.085221
Miss 0.085083
Cabin_F 0.057935
Cabin_A 0.022287
Family 0.016639
Royalty 0.016040
Cabin_G 0.016040
Embarked_Q 0.003650
PassengerId -0.005007
Cabin_T -0.026456
Officer -0.031316
Age -0.070323
Embarked_S -0.149683
Cabin_U -0.316912
Pclass_3 -0.322308
Sex -0.543351
Mr -0.549199
Name: Survived, dtype: float64
經(jīng)過排序后發(fā)現(xiàn),呈正相關(guān)的字段有:頭銜茉盏,客艙等級鉴未,船票價格,船艙號等鸠姨;呈負相關(guān)的的字段有:頭銜铜秆,性別,客艙等級讶迁,船艙號连茧。
- 原訓(xùn)練數(shù)據(jù)為891行,因此將處理后的新數(shù)據(jù)集拆分成訓(xùn)練集和測試集
from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LogisticRegression
# 訓(xùn)練數(shù)據(jù)數(shù)量
trainNum = 891
# 截取訓(xùn)練數(shù)據(jù)
data_X = full_data.loc[0:trainNum-1,:]
data_X = data_X.drop('Survived',axis=1)
data_y = full_data.loc[0:trainNum-1,'Survived']
# 配置訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù)
X_train,X_test,y_train,y_test = train_test_split(data_X,data_y,train_size=0.8)
print('Orginal data x:', data_X.shape)
print('Train data x:',X_train.shape)
print('Test data x:',X_test.shape)
print('Orginal data y: ', data_y.shape)
print('Train data y: ',y_train.shape)
print('Test data y: ',y_test.shape)
- 導(dǎo)入模型算法巍糯,代入數(shù)據(jù)訓(xùn)練模型
# 導(dǎo)入邏輯回歸模型
model = LogisticRegression()
# 使用訓(xùn)練數(shù)據(jù)訓(xùn)練模型
model.fit(X_train, y_train)
# 測試模型準(zhǔn)確度
print(model.score(X_test,y_test))
利用訓(xùn)練數(shù)據(jù)中的測試集進行測試啸驯,發(fā)現(xiàn)模型準(zhǔn)確率為86.6%
- 利用訓(xùn)練好的模型對測試集進行預(yù)測
# 取出測試集
X_predict = full_data.loc[trainNum:,:]
X_predict = X_predict.drop(['Survived'],axis=1)
# 將測試基代入模型進行預(yù)測
y_predict = model.predict(X_predict)
# 對測試集進行格式化
y_predict = y_predict.astype(int)
# 將預(yù)測結(jié)果用passengerId進行保存
passengerId = full_data.loc[trainNum:,'PassengerId']
predictDf = pd.DataFrame({'PassengerId':passengerId,'Survived':y_predict})