킹갓 케글을 아는가? 사실 필자도 최근에 알았다. (왜냐면 인공지능을 최근에 시작했음) 인공지능을 하면서 단언코 최고의 커뮤니티는 케글이 아닐까 한다. 다양한 대회들이 열리는 것은 물론이고 세계 각국의 인공지능 능력자들이 서로의 코드를 공유하기 때문에 개인적으로 깃허브보다 낫다고 생각한다. 그리고 Notebook을 사용해서 코드를 진행하면 흐름을 잘 이해할 수 있어서 처음 인공지능을 하는 사람들에게는 적격인 사이트라고 생각한다.

 

https://www.kaggle.com/c/titanic

 

Titanic: Machine Learning from Disaster

Start here! Predict survival on the Titanic and get familiar with ML basics

www.kaggle.com

 

앞서 2. 머신러닝 진행과정 에서 말했다시피 이론만 하고 넘어가면 제대로 모른다. 그러니 위의 Titanic 대회에 참가해 머신러닝의 진행과정을 실전을 통해 이해해보자!

 

참고로 케글 사용법과 타이타닉에 대해 잘 설명해주는 유튜브 동영상은 여기 를 누르면 되고, 필자가 참고한 케글은 여기 를 누르면 된다.

 

 

1.  EDA (탐색적 자료 분석)

 

import numpy as np 
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import missingno as msno
plt.style.use('fivethirtyeight')
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline

# 데이터를 불러오고 보여준다.
data=pd.read_csv('../input/titanic-machine-learning-from-disaster/train.csv')

# 참고로 data.head()는 앞의 5개만을 보여준다.
data.head() 
 
 

데이터를 확인하면 이렇게 나온다.

 

Survived 0은 사망, 1은 생존을 의미
Pclass 선실 클래스
SibSp 탑승한 형제자매, 배우자의 수
Parch 탑승한 부모, 자식의 수
Ticket 티켓 번호
Fare 운임
Cabin 객실번호
Embarked 탑승장소(C: Cherbourg, Q: Queenstown, S: Southampton)

 

위의 라벨들이 의미하는 것을 표로 나타냈다. 당장 저 데이터만 봐도 NaN 값을 볼 수 있는데 그러면 얼마나 많은 데이터들이 누락되어있을까?

 

# train_data의 누락된 자료 비율 파악

for col in train_data.columns :
    msg = '항목 {:>10}\t 비어있는 자료의 비율 : {:.2f}%'.format(col, 100 * (train_data[col].isnull().sum() / train_data[col].shape[0]))
    print(msg)
항목 PassengerId	 비어있는 자료의 비율 : 0.00%
항목   Survived	 비어있는 자료의 비율 : 0.00%
항목     Pclass	 비어있는 자료의 비율 : 0.00%
항목       Name	 비어있는 자료의 비율 : 0.00%
항목        Sex	 비어있는 자료의 비율 : 0.00%
항목        Age	 비어있는 자료의 비율 : 19.87%
항목      SibSp	 비어있는 자료의 비율 : 0.00%
항목      Parch	 비어있는 자료의 비율 : 0.00%
항목     Ticket	 비어있는 자료의 비율 : 0.00%
항목       Fare	 비어있는 자료의 비율 : 0.00%
항목      Cabin	 비어있는 자료의 비율 : 77.10%
항목   Embarked	 비어있는 자료의 비율 : 0.22%

 

# test_data의 누락된 자료 비율 파악

for col in test_data.columns :
    msg = '항목 {:>10}\t 비어있는 자료의 비율 : {:.2f}%'.format(col, 100 * (test_data[col].isnull().sum() / test_data[col].shape[0]))
    print(msg)
항목 PassengerId	 비어있는 자료의 비율 : 0.00%
항목     Pclass	 비어있는 자료의 비율 : 0.00%
항목       Name	 비어있는 자료의 비율 : 0.00%
항목        Sex	 비어있는 자료의 비율 : 0.00%
항목        Age	 비어있는 자료의 비율 : 20.57%
항목      SibSp	 비어있는 자료의 비율 : 0.00%
항목      Parch	 비어있는 자료의 비율 : 0.00%
항목     Ticket	 비어있는 자료의 비율 : 0.00%
항목       Fare	 비어있는 자료의 비율 : 0.24%
항목      Cabin	 비어있는 자료의 비율 : 78.23%
항목   Embarked	 비어있는 자료의 비율 : 0.00%

 

# 누락된 데이터를 시각화 해보자

msno.matrix(df=train_data.iloc[:,:], figsize=(8,8), color=(0.7,0.4,0.2))

train_data의 데이터 시각화 / 디스크 정리 보는 기분

 

 

Cabin과 Age 데이터가 꽤 많이 누락되어있고 Cabin 데이터는 사실상 없다고 보는게 맞겠다. 하지만 데이터가 많이 없다고 무의미한 데이터일까? 대답은 그건 아무도 모른다이다. Cabin같은 경우는 누락된 데이터가 너무 많아 평균값으로 채울 수도 없으니 지우는게 맞다고 본다. 하지만 Age같이 애매하게 누락된 데이터들은 최대한 살려야한다. 사실 이게 또 좋다고 볼 수도 없다. 하지만 데이터가 많을수록 더 정확한 모델이 만들어지기 때문에 최대한 많은 데이터가 필요하므로 사람들은 열심히 열심히 누락된 데이터를 매꾸는 전처리 과정을 거치게 된다. 일단 계속해서 EDA를 하자.

 

f,ax=plt.subplots(1,2,figsize=(18,8))
train_data['Survived'].value_counts().plot.pie(explode=[0,0.1],autopct='%1.1f%%',ax=ax[0],shadow=True)
ax[0].set_title('Survived')
ax[0].set_ylabel('')
sns.countplot('Survived',data=train_data,ax=ax[1])
ax[1].set_title('Survived')
plt.show()

위의 코드로 코딩을 하면 이와 같은 그림이 나온다.

 

앞서 표에서 말했다시피 0은 사망을 뜻한다. 많은 사람들이 죽었음을 알 수 있는 대목이다. 그러면 여기서 궁금해지는 것이 있다. 어떤 사람들이 살아남았을까? 우리는 이것을 확인하기위해 EDA를 사용한다. 그리고 이것을 확인하는 것은 예측을 더 쉽게할 수 있다.

 

# 성별에 따른 사망자와 생존자

f,ax=plt.subplots(1,2,figsize=(18,8))
train_data[['Sex','Survived']].groupby(['Sex']).mean().plot.bar(ax=ax[0])
ax[0].set_title('Survived vs Sex')
sns.countplot('Sex',hue='Survived',data=train_data,ax=ax[1])
ax[1].set_title('Sex:Survived vs Dead')
plt.show()

여자가 압도적으로 생존률이 높았다.

남자가 약 600명, 여자가 약 300명으로 남자 승객이 여성에 비해 압도적으로 높았음에도 불구하고 여성의 생존률이 남성의 생존률보다 더 높은 것을 확인할 수 있다. (사스가 Lady first의 나라) 이런 시각적인 데이터를 보면 타이타닉에 탔던 사람들은 약자를 우선으로 여겼을 확률이 매우 높다. 이런 직관을 판단하기 위해 EDA과정이 필요하다. 그렇다면 약자인 노인과 영아의 생존률은 얼마인지 확인해보자.

 

# 나이에 따른 사망자와 생존자

f,ax=plt.subplots(1,2,figsize=(20,10))
train_data[data['Survived']==0].Age.plot.hist(ax=ax[0],bins=20,edgecolor='black',color='red')
ax[0].set_title('Survived= 0')
x1=list(range(0,85,5))
ax[0].set_xticks(x1)
train_data[train_data['Survived']==1].Age.plot.hist(ax=ax[1],color='green',bins=20,edgecolor='black')
ax[1].set_title('Survived= 1')
x2=list(range(0,85,5))
ax[1].set_xticks(x2)
plt.show()

15세 미만의 아이들의 생존자는 대체로 사망자보다 많다.

 

fig, ax = plt.subplots(1,1, figsize=(9,5))
sns.kdeplot(train_data[train_data['Survived'] == 1]['Age'], ax=ax)
sns.kdeplot(train_data[train_data['Survived'] == 0]['Age'], ax=ax)
plt.legend(['Survived','Dead'])
plt.xlabel('Age')
plt.ylabel('Survived')
plt.show()

위의 막대그래프를 더 직관적으로 나타냈다.

 

위의 그래프들을 보면 죽은 사람과 산 사람이 비슷비슷한 20~60대와는 달리 확실히 15세 미만의 아이들이 생존률이 더 높음을 알 수 있다. (직관이 먹혔다!) 그렇다면 클래스에 따라서는 생존률이 어떻게 나타날까? 대부분 사람들의 직관으로 부자들이 많이 생존했을 것이라고 예측할 수 있다. 과연 그럴까?

 

# 클래스에 따른 사망자와 생존자

pd.crosstab(train_data.Pclass,data.Survived,margins=True).style.background_gradient(cmap='summer_r')

클래스에 따른 생존자와 사망자 수

 

f,ax=plt.subplots(1,2,figsize=(18,8))
train_data['Pclass'].value_counts().plot.bar(color=['#CD7F32','#FFDF00','#D3D3D3'],ax=ax[0])
ax[0].set_title('Number Of Passengers By Pclass')
ax[0].set_ylabel('Count')
sns.countplot('Pclass',hue='Survived',data=train_data,ax=ax[1])
ax[1].set_title('Pclass:Survived vs Dead')
plt.show()

클래스에 따른 데이터를 시각화하였다.

 

3등급의 사람들이 제일 많았으나 3등급의 사망자가 제일 많았다. 1등급은 예상대로 생존자가 사망자보다 더 많았다. (직관이 먹혔다!2) 그렇다면 여기서 갑자기 궁금한 것이 있다. (사실 궁금하다기보다는 코드가 있으니 써먹으려고ㅋㅎ) 클래스 간 성별에 따른 생존률이 위에서 보여진것과 동일할까? 3등급의 사람들은 전체 성별 생존률과는 무관하게 남성이 여성보다 더 많이 살았을 수도 있지 않을까?

 

# 클래스 별 성별에 따른 사망자와 생존자

sns.factorplot('Pclass','Survived',hue='Sex',data=train_data)
plt.show()

응 아니야

 

이건 나의 직관이 틀렸다! 이렇게 이런 저런 직관과 데이터의 분류, 흐름 등을 파악하기 위해 EDA 과정은 반드시 필요하다. 개발자가 데이터를 잘 이해해야 좋은 알고리즘을 선택해 좋은 모델을 만들 수 있기 때문이다. 이렇게 사람의 직관으로 어느정도 추정할 수 있는 데이터와 달리, 전혀 감도 잡을 수 없는 데이터들은 어떻게 사용해야할까? 이 역시 EDA를 통해 데이터의 숨겨져 있는 특징들을 파악할 수 있다. 

 

# 탑승장소를 기반으로한 다양한 데이터 조합들

f,ax=plt.subplots(2,2,figsize=(20,15))
sns.countplot('Embarked',data=train_data,ax=ax[0,0])
ax[0,0].set_title('No. Of Passengers Boarded')
sns.countplot('Embarked',hue='Sex',data=train_data,ax=ax[0,1])
ax[0,1].set_title('Male-Female Split for Embarked')
sns.countplot('Embarked',hue='Survived',data=train_data,ax=ax[1,0])
ax[1,0].set_title('Embarked vs Survived')
sns.countplot('Embarked',hue='Pclass',data=train_data,ax=ax[1,1])
ax[1,1].set_title('Embarked vs Pclass')
plt.subplots_adjust(wspace=0.2,hspace=0.5)
plt.show()

 

sns.factorplot('Pclass','Survived',hue='Sex',col='Embarked',data=train_data)
plt.show()

역시 Lady Frist

 

전체적으로 봤을 때 S 에서 가장 많은 사람이 탑승했다. C와 Q 는 남녀의 비율이 비슷하고, S는 남자가 더 많으며 S의 경우 생존률 낮다.  Pclass와 함께 보면 C가 생존률 높은 이유와 S가 생존률이 낮은 이유가 클래스와 연관이 있음을 알 수 있다. 이렇게 EDA를 사용하면 자칫 보지 않았을 연관성에 대해서도 판단할 수 있게 된다.

 

너무 길어졌으니 전처리 과정은 다음에 설명하겠다.

+ Recent posts