【Kaggle入門級競賽top5%排名經驗分享】— 分析篇
來自專欄 Python數據分析17 人贊了文章
作者:xiaoyu
微信公眾號:Python數據科學
知乎:python數據分析師
Kaggle作為公認的數據挖掘競賽平台,有很多公開的優秀項目,而其中作為初學者入門的一個好的項目就是:泰坦尼克號生還者預測。
可能這個項目好多朋友也聽說過,可能很多朋友也做過。但是項目完成後,是否有很好的反思總結呢?很多朋友只是潦草的敷衍過去了,知道大概的套路了就沒再去看。其實,一個再簡單的項目,如果把它做好也能有巨大的收穫。
開始做的時候,也是經過反覆琢磨和嘗試,並從最初的20%到最好的2%,期間學習了很多,不得不說這個項目讓我很好的了解了數據挖掘。
本篇,將會從零開始介紹這個項目,教你如何一步一步的把這個項目做好。由於大部分星球的朋友們已經完成了分析部分的實戰練習,因此將這部分內容拿出來進行簡單的分享。
項目介紹
首先對這個項目進行一下介紹。
數據探索
萬變不離其宗,拿到數據首先粗率的觀察。
"""導入數據"""import pandas as pdimport numpy as npdata_train = pd.read_csv(train.csv)data_test = pd.read_csv(test.csv)df = data_train.append(data_test)
將訓練集和測試集進行合併,以便後續數據內容變換的統一處理。
df.info()print(合併後一共{0}條數據。.format(str(df.shape[0])))print(pd.isnull(df).sum())
df.describe()
異常值初始觀察(主要觀察一下最大與最小值):
- Fare:船票價格平均值33.2,中位數14,平均值比中位數大很多,說明該特徵分布是嚴重的右偏,又看到最大值512,所以512很可能是隱患的異常值。
- Age:最小值為0.17,最大值為80,0.17是大概剛出生一個半月的意思,而80年齡有些過大,需要進一步排查。
- SibSp與Parch:Sibsp最大為8,可能是異常,但又看到Parch最大值為9。這兩個特徵同時出現大的數值,第一放映是這個數值是有可能的,我們進步一觀察。
結論: 通過以上觀察和分析,我們看到了一些可能的異常值,但是也不敢肯定。這需要我們進一步通過可視化來清楚的顯示並結合對業務的理解來確定。
數據可視化
定類/定序特徵分析
import matplotlib.pyplot as pltimport seaborn as sns%matplotlib inlineplt.style.use("bmh")plt.rc(font, family=SimHei, size=13)cat_list = [Pclass,Name,Sex,SibSp,Embarked,Parch,Ticket,Cabin]for n,i in enumerate(cat_list): Cabin_cat_num = df[i].value_counts().index.shape[0] print({0}. {1}特徵的類型數量是: {2}.format(n+1,i,Cabin_cat_num))
結論:從上面各特徵值的類型數量來看:
- 一些比較少數量的特徵如Pclass,Sex,SibSp,Embarked,Parch等可進行可視化分析。
- 剩下特徵如Name(每個人名字都不一樣),或者Ticket和Cabin由於分類太多對於可視化不是太方便,後續對這些特徵單獨分析。
因此,先對上面5種容易的分類進的特徵行可視化。
f, [ax1,ax2,ax3] = plt.subplots(1,3,figsize=(20,5))sns.countplot(x=Sex, hue=Survived, data=data_train, ax=ax1)sns.countplot(x=Pclass, hue=Survived, data=data_train, ax=ax2)sns.countplot(x=Embarked, hue=Survived, data=data_train, ax=ax3)ax1.set_title(Sex特徵分析)ax2.set_title(Pclass特徵分析)ax3.set_title(Embarked特徵分析)f.suptitle(定類/定序數據類型特徵分析,size=20,y=1.1)f, [ax1,ax2] = plt.subplots(1,2,figsize=(20,5))sns.countplot(x=SibSp, hue=Survived, data=data_train, ax=ax1)sns.countplot(x=Parch, hue=Survived, data=data_train, ax=ax2)ax1.set_title(SibSp特徵分析)ax2.set_title(Parch特徵分析)plt.show()
對於上面的定類和定序數據類型,我們分別可以觀察到各特徵值的分布情況,以及與目標變數之間的聯繫。
- Sex: 對於女性而言,男性總人數雖多,但是獲救率明顯很低(先救婦女!!!);
- Pclass: 社會等級為3的總人數最多(也就是大多數人都是普通老百姓),但是獲救率非常低(社會價值高的人優先留下);
- Embarked: 登陸港口S數量最多,但是獲救率也是最低的,C港口獲救率最高;
- SibSp: 兄弟姐妹數量最低為0的人數最多,但是獲救率最低,而為1的獲救率相對較高,超過50%;
- Parch: 情況基本同SibSp一樣,後續可以考慮將二者合併;
就以上5個特徵來看,Sex和Pclass兩個特徵是其中非常有影響的兩個。
以上只是單獨特徵對是否生還的簡單分析,但實際上對目標變數的影響是由多個因素造成的,而不只是單獨的影響。為此,我們需要知道在某個特定條件下的特徵的影響才更加能幫助我們分析:
- 比如我們想看看Pclass是1的情況下,男性和女性生還概率有何不同;
- 更具體的比如我們想看看Pclass是1且為male的情況下,Embarked特徵的影響是什麼樣的;
以下是用FaceGrid進行的具體分析:
# 在不同社會等級下,男性和女性在不同登陸港口下的數量對比grid = sns.FacetGrid(df, col=Pclass, hue=Sex, palette=seismic, size=4)grid.map(sns.countplot, Embarked, alpha=0.8)grid.add_legend()
觀察結果:
- Pclass為1和2的時候,Q港口數量幾乎為零,而Pclass3的Q港口人數甚至比C港口多。這說明社會等級與港口有關聯,根據社會等級與港口的對應關係可推測S和C港口為高級港口,而Q港口為普通港口。
- Pclass為2的港口中,男性與女性在S和C港口的數量分布呈現相反趨勢,與其他Pclass等級截然不同,這說明Pclass2可能是社會中某個共性群體,這個群體多為女性,而男性很少。既然多為女性,且女性生還概率還大,可推測Pclass2的C港口的生還概率也很高。
# 在不同社會等級下,男性和女性在不同登陸港口下的數量對比grid = sns.FacetGrid(data_train, row=Sex, col=Pclass, hue=Survived, palette=seismic, size=4)grid.map(sns.countplot, Embarked, alpha=0.8)grid.add_legend()
定距/定比特徵分析
1. Age分布和特徵分析
# kde分布f,ax = plt.subplots(figsize=(10,5))sns.kdeplot(data_train.loc[(data_train[Survived] == 0),Age] , color=gray,shade=True,label=not survived)sns.kdeplot(data_train.loc[(data_train[Survived] == 1),Age] , color=g,shade=True, label=survived)plt.title(Age特徵分布 - Surviver V.S. Not Survivors, fontsize = 15)plt.xlabel("Age", fontsize = 15)plt.ylabel(Frequency, fontsize = 15)
結論:
很明顯看到,以上Survived與Not Survived特徵分布的主要區別在 0 ~15左右。小於15歲以下的乘客(也就是孩子)獲救率非常高,而大於15歲的乘客分布無明顯區別。
# 箱型圖特徵分析fig, [ax1,ax2] = plt.subplots(1,2,figsize=(20,6))sns.boxplot(x="Pclass", y="Age", data=data_train, ax =ax1)sns.swarmplot(x="Pclass", y="Age", data=data_train, ax =ax1)sns.kdeplot(data_train.loc[(data_train[Pclass] == 3),Age] , color=b,shade=True, label=Pcalss3,ax=ax2)sns.kdeplot(data_train.loc[(data_train[Pclass] == 1),Age] , color=g,shade=True, label=Pclass1,ax=ax2)sns.kdeplot(data_train.loc[(data_train[Pclass] == 2),Age] , color=r,shade=True, label=Pclass2,ax=ax2)ax1.set_title(Age特徵在Pclass下的箱型圖, fontsize = 18)ax2.set_title("Age特徵在Pclass下的kde圖", fontsize = 18)fig.show()
結論:
不同Pclass下的年齡分布也不同,三個分布的中位數大小按 Pclass1 > Pclass2 > Pclass3 排列。這也符合實際情況,Pclass1的乘客是社會上的擁有一定財富和地位的成功人士,年齡比較大,而Pclass3的人數最多,因為大多數人還都是普通人(有錢人畢竟少數),並且這些人多是年輕人,年齡在20-30之間。
# Sex,Pclass分類條件下的 Age年齡對Survived的散點圖grid = sns.FacetGrid(data_train, row=Sex, col=Pclass, hue=Survived, palette=seismic, size=3.5)grid.map(plt.scatter, PassengerId, Age, alpha=0.8)grid.add_legend()
結論:
從散點圖來分析:
- Pclass1和Pclass2的女性幾乎都是Survived的,Pclass3中女性Survived則不是很明顯了;
- Pclass1的男性生還率最高,Pclass2和Pclass3的生還率比較低,但是Pclass2中年齡小的乘客幾乎全部生存;
印證了那個原則:婦女和孩子優先營救。
# Sex,Embarked分類條件下的 Age年齡對Survived的散點圖grid = sns.FacetGrid(data_train, col = "Embarked", row = "Sex", hue = "Survived", palette = seismic, size=3.5)grid = grid.map(plt.scatter, "PassengerId", "Age")grid.add_legend()grid
# Sex,SibSp分類條件下的 Age年齡對Survived的散點圖grid = sns.FacetGrid(data_train, col = "SibSp", row = "Sex", hue = "Survived", palette = seismic)grid = grid.map(plt.scatter, "PassengerId", "Age")grid.add_legend()grid
# Sex,Parch分類條件下的 Age年齡對Survived的散點圖grid = sns.FacetGrid(data_train, col = "Parch", row = "Sex", hue = "Survived", palette = seismic)grid = grid.map(plt.scatter, "PassengerId", "Age")grid.add_legend()grid
2. Fare分布和特徵分析
# 箱型圖特徵分析fig, [ax1,ax2] = plt.subplots(1,2,figsize=(20,6))sns.boxplot(x="Pclass", y="Fare", data=data_train, ax =ax1)sns.swarmplot(x="Pclass", y="Fare", data=data_train, ax =ax1)sns.kdeplot(data_train.loc[(data_train[Pclass] == 3),Fare] , color=b,shade=True, label=Pcalss3,ax=ax2)sns.kdeplot(data_train.loc[(data_train[Pclass] == 1),Fare] , color=g,shade=True, label=Pclass1,ax=ax2)sns.kdeplot(data_train.loc[(data_train[Pclass] == 2),Fare] , color=r,shade=True, label=Pclass2,ax=ax2)ax1.set_title(Fare特徵在Pclass下的箱型圖, fontsize = 18)ax2.set_title("Fare特徵在Pclass下的kde圖", fontsize = 18)fig.show()
結論:
觀察到Pclass1相對於2和3的Fare比較高,因為地位高,財富多。但是Pclass1中有幾個大於500的異常值存在,看一下這些異常數據。
df.loc[df[Fare]>500]
這些異常值中,有兩個名字一樣的Cardeza,又看到Parch都為1,SibSp都為0,Fare,Cabin,Embarked,Ticket都一樣,可推測二人是夫妻。 另外兩個人的Embarked,Ticket,Fare也都一樣,這說明這個大於500的Fare可能不是異常值。後面我們會對這些進行特徵工程來特殊對待。
# Sex和Pclass情況下Fare和Age的散點圖grid = sns.FacetGrid(data_train, row=Sex, col=Pclass, hue=Survived, palette=seismic, size=3.5)grid.map(plt.scatter, Age, Fare, alpha=0.8)grid.add_legend()
g = sns.pairplot(data_train[[uSurvived, uPclass, uSex, uAge, uParch, uFare, uEmbarked]], hue=Survived, palette = seismic, size=4,diag_kind = kde,diag_kws=dict(shade=True),plot_kws=dict(s=50) )g.set(xticklabels=[])
這是上述7個特徵的相互關聯圖的匯總,對角線為特徵自身的kde分布。對於不方便可視化的Name,Cabin,Ticket將在特徵工程中進一步進行處理並挖掘這些數據中到底有什麼信息是非常有價值的。
數據集獲取
公眾號後台回復:泰坦尼克號,獲取源訓練集和測試集。下一篇將著重介紹特徵工程的內容,敬請期待。
關注微信公眾號:Python數據科學,查看更多精彩內容。推薦閱讀:
※【官方中文版】谷歌發布機器學習術語表(完整版)
※基於 XGBoost 對 Santander 銀行用戶購買行為進行預測
※用R語言進行文本挖掘和主題建模
※5種演算法玩轉聚類分析
※Python抓取網頁數據的終極辦法