很久之前練習(xí)過(guò)的一個(gè)kaggle項(xiàng)目,有點(diǎn)記不清了珠十,今天來(lái)溫習(xí)下劝赔,嘻嘻~
kaggle給初學(xué)者或者富有挑戰(zhàn)能力的選手們提供了一個(gè)非常好的平臺(tái)喂江,希望自己以后盡量抽時(shí)間多做幾個(gè)這種項(xiàng)目,與大牛們一起交流學(xué)習(xí)~
1.下載理解數(shù)據(jù)集
下載地址:https://www.kaggle.com/c/titanic/data(需要注冊(cè)kaggle才能下載哦~)
下載完數(shù)據(jù)集要理解每個(gè)字段的含義悴能,項(xiàng)目背景等鳄炉,這個(gè) 很重要哦~
2.加載查看數(shù)據(jù)分布、缺失搜骡、異常情況
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
train=pd.read_csv("F:/titanic/train.csv")
test=pd.read_csv("F:/titanic/test.csv")
train.head() #大概看一下數(shù)據(jù)長(zhǎng)什么樣
#查看數(shù)據(jù)類型拂盯,缺失情況等信息
train.info()
test.info()
通過(guò)上面的信息,我們可以得到:
- 訓(xùn)練集共有891個(gè)樣本记靡,測(cè)試集共有418個(gè)樣本
- 訓(xùn)練集和測(cè)試集中Cabin這個(gè)特征缺失都比較多谈竿,了解到這個(gè)特征的意思是客艙號(hào)碼,跟我們要預(yù)測(cè)的船員是否生存關(guān)系應(yīng)該不大摸吠,因此后期考慮將這個(gè)特征刪除
- 訓(xùn)練集和測(cè)試集中Age這個(gè)特征都有缺失空凸,但是缺失不多,可以通過(guò)眾數(shù)寸痢、中位數(shù)呀洲、均值、插值啼止、特殊值等填充道逗,鑒于時(shí)間和成本因素翰苫,后面我直接用眾數(shù)填充奔缠,有精力的可以多嘗試幾種方法,選擇最好的進(jìn)行填充
- Embarked僅在訓(xùn)練集中有缺失了赌,缺失2個(gè)巩那,也是不多吏夯,且了解到這個(gè)特征的意思是登船港此蜈,共有3個(gè)不同的取值,因此后面直接用眾數(shù)進(jìn)行填充
- Fare僅在測(cè)試集中有1個(gè)缺失噪生,且了解到這個(gè)特征的意思是旅客票價(jià)裆赵,應(yīng)該跟Pclass(Ticket class )相關(guān)性比較高,后面將結(jié)合Pclass進(jìn)行填充
好了跺嗽,知道了數(shù)據(jù)大概的缺失情況战授,我們下面看一下他們的統(tǒng)計(jì)性描述信息:
train.describe()
test.describe()
通過(guò)上面的統(tǒng)計(jì)描述信息,我們可以發(fā)現(xiàn):
- 訓(xùn)練集中平均38%左右的人生還
- Pclass即船票類型共分三等抛蚁,分別是1陈醒、2、3
- 數(shù)據(jù)集中年齡最大的是80瞧甩,最小的是0.17钉跷,年齡在50歲以上的人很少,大部分集中在20-40歲之間
- 船票價(jià)格差距較大肚逸,支付高價(jià)格的人很少
- 帶父母或孩子出行的乘客很少
- PassengerId只是每位乘客的一個(gè)唯一標(biāo)識(shí)爷辙,訓(xùn)練模型時(shí)可將該特征去掉
上面描述的都是數(shù)值型的特征信息,也可以查看字符型的特征信息:
train.describe(include=["O"])
通過(guò)對(duì)訓(xùn)練集的特征統(tǒng)計(jì)信息朦促,可以發(fā)現(xiàn):
- Name這個(gè)特征所有的名字都不一樣膝晾,但從名字中可能獲取不到更多的信息,但是發(fā)現(xiàn)名字都帶有Miss务冕、Mr血当、Mrs這種稱謂信息,后續(xù)可以在特征工程時(shí)構(gòu)建此類信息
- Sex特征中禀忆,男性占比更大臊旭,891人中577都是男性
- Embarked特征中,共3個(gè)不同的取值箩退,S即Southampton頻次最高离熏,644次
3.數(shù)據(jù)探索,挖掘各個(gè)特征與目標(biāo)特征之間的關(guān)系
先看一下這些數(shù)值特征與目標(biāo)特征間的線性相關(guān)性:
import seaborn as sns
#Seaborn是對(duì)matplotlib的extend戴涝,是一個(gè)數(shù)據(jù)可視化庫(kù)滋戳,提供更高級(jí)的API封裝,在應(yīng)用中更加的方便靈活
corrmat=train.drop('PassengerId',axis=1).corr()
f, ax = plt.subplots(figsize=(10, 7))
plt.xticks(rotation='90')
sns.heatmap(corrmat, square=True, linewidths=.5, annot=True)
plt.show()
通過(guò)上圖啥刻,可以發(fā)現(xiàn):
- 是否生存與Fare程正相關(guān)奸鸯,相關(guān)性系數(shù)為0.26,與Pclass程負(fù)相關(guān)郑什,相關(guān)性系數(shù)為0.34府喳,從實(shí)際含義也可以理解,因?yàn)槠眱r(jià)越高蘑拯,船票類型就越小钝满,最好的船票是1等票,因此申窘,F(xiàn)are與Pclass的相關(guān)性系數(shù)也很高弯蚜,0.55
- Parch與SibSp相關(guān)性也很高,為0.415,
下面我們?cè)賳为?dú)對(duì)這些特征進(jìn)行分析:
(1)對(duì)Pclass進(jìn)行分析
train[['Survived','Pclass']].groupby(['Pclass']).mean()
通過(guò)上面的結(jié)果剃法,可以發(fā)現(xiàn)Pclass等級(jí)越高碎捺,存活率越高,這是一個(gè)比較重要的特征
(2)對(duì)Age進(jìn)行分析
target = sns.FacetGrid(train,col='Survived')
target.map(plt.hist,'Age',bins=20)
通過(guò)上圖贷洲,可以發(fā)現(xiàn):
- 大部分乘客年齡都在20-40歲之間
- 0-10歲之間存活下來(lái)的兒童較多收厨,大量13-35歲之間的乘客沒(méi)有存活下來(lái),年齡最大(80歲)的老爺爺存活下來(lái)
- 并不是年齡越大或者越小存活率越大优构,因此我們需要對(duì)年齡進(jìn)行分段诵叁,具體劃分方法可以通過(guò)人為經(jīng)驗(yàn)、圖像觀察钦椭、決策樹(shù)輔助等劃分
(3)對(duì)SibSp和Parch進(jìn)行分析
train[['Survived','SibSp']].groupby(['SibSp']).mean()
train[['Survived','Parch']].groupby(['Parch']).mean()
通過(guò)上圖拧额,可以發(fā)現(xiàn):
- 是否生存與SibSp、Parch線性相關(guān)性不是很明顯彪腔,可以看后期模型中的效果再做判斷
(4)對(duì)Fare進(jìn)行分析
target = sns.FacetGrid(train,col='Survived')
target.map(plt.hist,'Fare',bins=20)
通過(guò)上圖侥锦,可以發(fā)現(xiàn):
- 票價(jià)越低,存活率越低
- 這個(gè)可以跟Pclass對(duì)應(yīng)德挣,船票等級(jí)越高恭垦,存活率越高,但這兩個(gè)特征具有高度共線性格嗅,后期如果用線性回歸之類的模型可以只用其中的一個(gè)特征
(4)對(duì)Embarked進(jìn)行分析
train[['Survived','Embarked']].groupby(['Embarked']).mean()
可以發(fā)現(xiàn):
- 從C口進(jìn)入的乘客存活率更高番挺,從S口進(jìn)入的乘客存活率最低,改特征是定性特征吗浩,很多模型都無(wú)法直接運(yùn)行建芙,后續(xù)可以對(duì)改特征進(jìn)行亞編碼
(5)對(duì)Sex分析
train[['Survived','Sex']].groupby(['Sex']).mean()
可以發(fā)現(xiàn):
- 女性的存活率明顯高于男性,因此這個(gè)特征可能對(duì)最后的預(yù)測(cè)結(jié)果非常重要懂扼,后期需要進(jìn)行亞編碼禁荸,或者直接0、1二值化
(6)對(duì)Pclass和Age一起分析
target = sns.FacetGrid(train,col='Survived',row='Pclass')
target.map(plt.hist,'Age',bins=20)
可以發(fā)現(xiàn):
- 船票類型是3阀湿,年齡在15-40歲之間的乘客存活率很低
- 船票類型是2或3赶熟,年齡在0-15歲之間存活率很高
- 是否能存活與年齡和船票類型都有關(guān),可以在特征工程時(shí)構(gòu)造這樣一個(gè)特征
還可以分析很多特征組合的特點(diǎn)陷嘴,充分發(fā)揮你的想象力映砖,腦洞大開(kāi),這里就不再分析了灾挨,進(jìn)行下一個(gè)環(huán)節(jié)咯~
4.數(shù)據(jù)清洗邑退、特征變換等
經(jīng)過(guò)上面的分析竹宋,我們需要:
- 刪掉PassengerId、Cabin這兩個(gè)特征地技,Ticket這個(gè)特征貌似也沒(méi)有太大的用處蜈七,這里也直接刪除掉,然后對(duì)Age進(jìn)行缺失值填充莫矗,這里用眾數(shù)填充飒硅,Embarked也用眾數(shù)填充,F(xiàn)are只在測(cè)試集中有缺失作谚,可以根據(jù)Pclass用訓(xùn)練集中的Fare均值進(jìn)行填充
- Embarked和Sex進(jìn)行亞編碼
- Age分段和亞編碼
- Name提取稱謂信息和亞編碼
del train['PassengerId']
del train['Cabin']
del train['Ticket']
train = train.fillna({"Age":train.Age.mean(),'Embarked':"S"})
train['Name']=train['Name'].map(lambda line: line.split(",")[1].split(".")[0])
train.head()
發(fā)現(xiàn)稱謂除了 Mr三娩、 Miss、 Mrs妹懒、 Master雀监,其他的都很少,所以這里把剩下的都統(tǒng)一改成other
train['Name']=train['Name'].map(lambda line: (line.strip() if line.strip() in ['Mr','Mrs','Miss','Master'] else 'other'))
train['Name'].value_counts()
train[['Survived','Name']].groupby(['Name']).mean().sort_values(by='Survived')
可以發(fā)現(xiàn)彬伦,Mrs和Miss的存活率更高滔悉,Mr的存活率最低,后續(xù)我們也要將這個(gè)特征亞編碼后加入模型中訓(xùn)練
下面對(duì)Age進(jìn)行分段单绑,這里就直接根據(jù)前面的分析自己定義分段區(qū)間回官,有精力可以用決策樹(shù)輔助分段,效果應(yīng)該會(huì)更好
def age_parse(line):
if line <=15:
return '0-15'
elif 15<line<=35:
return '15-35'
elif 35<line<=50:
return '35-50'
else:
return '>50'
train['Age']=train['Age'].map(age_parse)
train.head()
下面對(duì)定性特征統(tǒng)一亞編碼:
train = pd.get_dummies(train)
train.head()
#去除亞編碼后線性相關(guān)變量
del train['Name_other']
del train['Age_>50']
del train['Embarked_S']
del train['Sex_female']
特征標(biāo)準(zhǔn)化
由于Fare這個(gè)特征含有較大的數(shù)值搂橙,為了避免由于量綱帶來(lái)的問(wèn)題歉提,我們將它進(jìn)行標(biāo)準(zhǔn)化
from sklearn import preprocessing
scaler = preprocessing.StandardScaler().fit(np.array(train['Fare']).reshape(891,1))
fare = scaler.transform(np.array(train['Fare']).reshape(891,1))
train['Fare'] = fare
train.head()
注意: 測(cè)試集所有特征變換,特征清洗都是基于訓(xùn)練集來(lái)的区转,例如:如果訓(xùn)練集用訓(xùn)練集的A特征均值填充A特征的缺失值苔巨,那么測(cè)試集也要用訓(xùn)練集中A特征的均值填充缺失值,鑒于時(shí)間和精力有限废离,這里我只對(duì)訓(xùn)練集統(tǒng)一進(jìn)行處理侄泽,測(cè)試集先不做處理,以后有時(shí)間再進(jìn)行處理(捂臉)蜻韭,由于數(shù)據(jù)處理存在許多轉(zhuǎn)換步驟悼尾,需要按一定的順序執(zhí)行,可以推薦用sklearn中的pipeline模塊肖方,可以對(duì)訓(xùn)練集和測(cè)試集統(tǒng)一數(shù)據(jù)處理闺魏,非常好用~
5.構(gòu)造特征工程
這個(gè)環(huán)節(jié)就可以充分發(fā)揮你的想象力,構(gòu)造與目標(biāo)變量相關(guān)的線性特征俯画、非線性特征析桥、交叉特征等,可以構(gòu)造很多,后面特征篩選的時(shí)候過(guò)濾掉就好泡仗,例如可以構(gòu)造Age與Pclass的交叉特征埋虹,構(gòu)造Pclass與稱謂的交叉特征,sklearn也提供了相應(yīng)的函數(shù)沮焕,如果有兩個(gè)特征(x1,x2),構(gòu)造2次多項(xiàng)式特征吨岭,則完后會(huì)生成(1, X1, X2, X1^2, X1X2, X2^ 2)拉宗,這里我直接用特征構(gòu)造函數(shù)峦树,直接構(gòu)造所有特征的2次多項(xiàng)式特征(也可以構(gòu)造3次或者更高次,可以看下效果對(duì)比旦事,這里我就直接生成2次多項(xiàng)式特征了)
survived = train['Survived']
from sklearn import preprocessing
#構(gòu)造2次多項(xiàng)式魁巩, 默認(rèn)也是2次,設(shè)置參數(shù)include_bias= False,不包含偏差項(xiàng)數(shù)據(jù)
poly = preprocessing.PolynomialFeatures(2,include_bias=False)
poly_train = poly.fit_transform(train.drop(['Survived'],axis=1))
poly.get_feature_names()[0:20]
train_df =pd.DataFrame(poly_train)
train_df .columns=poly.get_feature_names()#特征重命名
train_df.head()
注意:這里的列名x0姐浮,x1...與圖一中除了‘Survived’的列名是一一對(duì)應(yīng)的谷遂,因?yàn)槊Q太長(zhǎng),所以會(huì)自動(dòng)生成新的名字
生成了這么多特征卖鲤,我們可以看一下他們與目標(biāo)特征的相關(guān)性:
可以發(fā)現(xiàn):
x0與x6肾扰,即Pclass與Name_mr相關(guān)性系數(shù)很高,x0與x10蛋逾,即Pclass與Age_15-35相關(guān)性也很高集晚,進(jìn)一步查看下關(guān)系:
train_df[['Survived','x0','x6']].groupby(['x0','x6']).mean().sort_values(by='Survived')
train_df[['Survived','x0','x10']].groupby(['x0','x10']).mean().sort_values(by='Survived')
可以發(fā)現(xiàn):
- 如果是Mr,那無(wú)論她的船票類型是什么区匣,她的生存率都很高偷拔,但如果不是Mr,那只有他的船票類型是1等的時(shí)候亏钩,他的存活率才會(huì)較高莲绰,但還是沒(méi)有Mr的高,因此這兩個(gè)特征是非常重要的
- 如果年齡在15-35之間姑丑,只有船票類型是1等的時(shí)候存活率才會(huì)較高蛤签,因此這兩個(gè)特征也是非常重要的
后續(xù)還可以再對(duì)其他的特征進(jìn)行類似的分析~