1. 程式人生 > >使用seaborn探索泰坦尼克號上乘客能否獲救

使用seaborn探索泰坦尼克號上乘客能否獲救

titanic資料集是個著名的資料集.kaggle上的titanic乘客生還率預測比賽是一個很好的入門機器學習的比賽.

資料集下載可以去https://www.kaggle.com/c/titanic/data.

本身寫這個系列筆記是作為自己機器學習的記錄,也為了加深自己對機器學習相關知識的理解.但是寫了前兩篇seaborn的筆記以後,感覺缺乏實際的比賽資料的例子,寫起來比較枯燥,讀的人看的可能也很枯燥,瀏覽量也寥寥.讀的人可能看完了會有一種,"哦,這樣啊,原來如此,懂了懂了",然鵝,一拿到真實的資料,還是一籌莫展,無從下手.

所以,今天就拿真實的資料來學習一下seaborn要怎麼用.怎麼在開始正式的機器學習演算法之前探索我們的資料關係.

 

titanic資料集給出了891行,12列已經標記的資料.即我們已知train.csv中891名乘客是否生還.我們需要預測test.csv中的418名乘客是否能夠生還.

首先看一眼我們的資料.

Variable Definition Key
survival Survival 0 = No, 1 = Yes
pclass Ticket class 1 = 1st, 2 = 2nd, 3 = 3rd
sex Sex  
Age Age in years  
sibsp # of siblings / spouses aboard the Titanic  
parch # of parents / children aboard the Titanic  
ticket Ticket number  
fare Passenger fare  
cabin Cabin number  
embarked Port of Embarkation C = Cherbourg, Q = Queenstown, S = Southampton

意思是一名名字叫harris的22歲男性乘客,乘坐三等倉,船上有1個兄弟姐妹/配偶,0個父母/子女,在Southampton上船,票價7.25,在此次災難中沒有生還.

拿到資料,我有幾個簡單的設想

  1. 票的級別越高,越容易獲救 其實就是有錢有地位的容易獲救
  2. 票價越高越容易獲救  同上
  3. 兄弟姐妹或者父母子女多,容易獲救  因為可以互相幫助
  4. 女性更容易獲救
  5. 孩子更容易獲救

好了,下面用seaborn來畫畫圖,觀察一下我們的資料,看看我拿到資料後第一想法對不對.

我主要用catplot 和 displot來繪圖. 

先來看看Pclass和Survived的關係.

catplot顧名思義,主要用來繪製分類資料(Categorical values).kind表示繪製什麼樣的圖,bar,box,violin等等.

sns.catplot(x="Pclass",y="Survived", kind="bar", data=titanic_train);

以此為例,我們的資料集中Pclass的取值共有3種,1,2,3,分別表示一等票,二等票,三等票.

當我們選擇bar圖時,y軸繪製出的是一個矩形,表示的是"Survived"這個資料的均值.(預設是均值,也可以調整為中位值).由於我們的Survived取值只有0(遇難了),1(獲救了).那麼均值等於獲救比例.

 

 

很明顯1等票的生還率更高.

 

再來看下票價和生還之間的關係.

票價的資料各種各樣,不像Pclass就3種.

sns.catplot(y="Fare",x="Survived", kind="bar", data=titanic_train);

很明顯,獲救的人平均票價更高.

fare的值很多,我們想看看具體有哪些,大致的分佈,可以用box.

sns.catplot(y="Fare",x="Survived", kind="box", data=titanic_train);

box繪圖,會繪製出一個箱體,並標註出資料的25%(Q1),50%(Q2),75%(Q3)及outlier處的位置.

其中怎麼判斷哪些點是屬於異常值呢?根據IQR=Q3-Q1.   距離Q1或Q3的距離超過1.5IQR的就算是異常.

比如,下圖的Q1=12 Q2=26 Q3=57.那麼IQR=Q3-Q1=45.  超過Q3+1.5IQR=57+67.5=124.5的就會被算成異常點.會用黑色的小菱形繪製出來.

如果我們想要繪製出概率估計圖.則可以用displot,或者kdeplot.這個在之前的文章裡介紹過了.

sns.kdeplot(titanic_train["Fare"][(titanic_train["Survived"] == 1) & (titanic_train["Fare"].notnull())], shade=1, color='red')
sns.kdeplot(titanic_train["Fare"][(titanic_train["Survived"] == 0) & (titanic_train["Fare"].notnull())], shade=1, color='green');

 

可以得到同樣的結論,票價高的,獲救概率更高一點.  

 

注意:知識點來了

不止這一點,我們還看到,fare的分佈並不是正態分佈的,分佈的極其不規則,也就是所謂的資料偏移,可以看到高收入的分佈概率是很低的,但是高收入的樣本分佈確並不少,即假如我們把100認為高票價,一個人的票價是100以上的概率是很低的,但是在100-500之間分佈的確很多,各種各樣的都有.那機器學習演算法在處理這個資料的時候就要注意了,要對資料做處理,可以用log函式做轉換,或者你把0-20,20-50,50-100,100+的分別歸類為1(很低),2(一般),3(較貴),4(很貴),用這種思想也可以.

實際上,對這個資料的處理,讓我最終的預測率直接提高了2個百分點.

titanic_train["Fare"].skew()

可以通過這個skew()來檢測資料的偏移度.如果資料偏移度比較高的話,如果skew()>0.75,一般需要對資料做分佈變換,可以使用log變換.

這個skew()>0.75中的0.75怎麼來的,我不太清楚,可能是一種經驗值.我們的這個例子中skew()值已經接近5了.

 

下面來驗證我們的猜想3,家人越多越容易得救

sns.catplot(x="SibSp",y="Survived", kind="bar", data=titanic_train);
sns.catplot(x="Parch",y="Survived", kind="bar", data=titanic_train);

 

可以看到和我們的猜想並不一致,當有一個兄弟姐妹的時候,獲救概率大概有0.55.而有4個兄弟姐妹的時候,獲救概率反而只有0.15了.

在父母子女上,也是類似的,當父母子女達到5個的時候,獲救概率反而低了.

titanic_train["family"] = titanic_train["SibSp"] + titanic_train["Parch"] + 1

sns.catplot(x="family",y="Survived", kind="bar", data=titanic_train);

我們建立一個新特徵,家庭成員數,可以看到,當家庭人數比較少的時候,生還概率大.當家庭過於龐大,生還概率更低了.

猜想,是不是人少的時候,可以互相幫助,人多了,尋找家人會更困難,導致本可以獲救的最終因為尋找家人也沒活下來?

 

接下來看我們的猜想4,女人更容易獲救

sns.catplot(x="Sex",y="Survived", kind="bar", data=titanic_train);

結論顯而易見,女性獲救概率高得多,lady first。

 

再來探索一下年齡與獲救的關係,驗證我們的猜想5.

sns.catplot(y="Age",x="Survived", kind="bar", data=titanic_train);

生還乘客的平均年齡是低了一點,但是兩者區別不大,也都在正常區間,似乎看不出來什麼.

我們來看看概率估計.

sns.kdeplot(titanic_train["Age"][(titanic_train["Survived"] == 1) & (titanic_train["Age"].notnull())], shade=1, color='red')
sns.kdeplot(titanic_train["Age"][(titanic_train["Survived"] == 0) & (titanic_train["Age"].notnull())], shade=1, color='green');

 

這個圖就很明顯了,在age很小的時候,紅線(獲救)明顯有個波峰.說明在這個年級段,獲救概率更高.   在age很大的時候(60歲以上),

綠線在紅線之上,說明老人更可能遇難.

 

至此我們的5個猜想基本被驗證,除了猜想3.  說明直覺還是比較準的嘛.

現在還剩下Name,Ticket,Cabin,Embarked這4個特徵與Survived的關係沒有驗證.

其中Name,Ticket,Cabin都是不規則的字串,需要做更多的特徵工程,找到其中的規律以後,才好觀察資料之間的關係.Embarked的取值只有S,C,Q3種.我們來看下Embarked與Survived的關係.

老套路:

sns.catplot(y="Survived", x = "Embarked",data = titanic_train, kind="bar")

C = Cherbourg, Q = Queenstown, S = Southampton

說實話,這個真的非常出乎我的意料.我原以為,是否生還和上船港口沒有關係,三者的生還概率應該是基本一樣才對.

然後我就開始胡思亂想了,總不能Cherbourg登船的人命好吧,越想越沒道理.或者說Cherbourg登船的人都坐在船的某個位置,受到冰山撞擊比較小?又或者只是因為樣本數量太少了,是個偶然的巧合?

然後我想到是不是這個港口登船的都是有錢人?

sns.catplot(y="Fare", x = "Embarked",data = titanic_train, kind="bar")

sns.catplot(x="Pclass", hue="Embarked",  data=titanic_train,kind="count")

 

 

這麼一看,還真是.所以Embarked=C的乘客生還概率高不是什麼偶然.

所以這就引發了一個問題,資料之間其實有關聯的,比如Embarked和Fare就有一定的相關性.我們可以用heatmap來探索各個特徵資料之間的相關性.

sns.heatmap(titanic_train.corr(),annot=True,fmt ='.2f')

titanic_train.corr()計算出來的是各個特徵的皮爾遜相關係數.皮爾遜相關係數。 wiki上解釋一大堆,說實在的裡面很多數學和統計學上的公式我沒看懂.其實我們也不需要搞的特別清楚這些數學公式.   說白了,皮爾遜相關係數就是求兩個向量之間的距離或者說夾角,越小越相關.(這個說法不嚴謹,但是原理上這麼理解是沒問題的).皮爾遜相關係數求出來在-1到1之間.

因為是求向量之間距離,所以展示的只有特徵值是數字型的特徵,Embarked特徵的值是字元,所以沒展示.你可以把字元對映成數字,比如S-->1,C-->2,Q-->3,再計算皮爾遜相關係數.當然這樣做是有問題的.因為,S,C,Q本來不存在大小關係,這麼對映以後存在了大小關係.這裡涉及到一個one-hot編碼問題.有興趣的自己搜尋一下,這篇就先不講了.

 

ok,以上就是本篇文章使用seaborn探索titanic資料的內容,更多有趣有用的關於資料預處理視覺化,關於seaborn使用等著大家去學習探索.希望這篇文章對大家有幫助和啟發.