titanic : Machine Learning from Disaster - kaggle¶
참조 https://www.kaggle.com/daehungwak/guide-kor-dg https://www.kaggle.com/
데이터 분석 순서¶
데이터 셋을 확인한다.
- 데이터가 어떻게 구성되어 있는지 확인
- null data 확인후 향후 수정
탐색적 데이터 분석(EDA, Exploratory Data Analysis)
- 여러 feature 들을 개별적 분석, 상관관계 확인
- 여러 시각화 툴을 사용해 insight를 얻는다
특성 공학(Feature Engineering)
- 모델의 성능을 높일 수 있도록 feature 들을 engineering 합니다.
- one-hot encoding, class로 나누기, 구간으로 나누기, 텍스트 데이터 처리
모델 개발 빛 학습
- sklearn, keras 을 사용해 모델을 만든다.
모델 예측 및 평가
- Train set을 가지고 모델을 학습시킨 후, Test set을 가지고 prediction 한다
라이브러리 및 패키지¶
- 여러 시각화 도구 : matplotlib, seaborn, plotly
- 데이터 분석 도구 : pandas, numpy
- 모델 개발 도구 : sklearn, keras
타이타닉 데이터 Feature 설명¶
- srvival - 생존유무, target 값. (0 = 사망, 1 = 생존)
- class - 티켓 클래스. (1 = 1st, 2 = 2nd, 3 = 3rd)
- sex - 성별
- Age - 나이(세)
- sibsp - 함께 탑승한 형제자매, 배우자 수 총합
- parch - 함께 탑승한 부모, 자녀 수 총합
- ticket - 티켓 넘버
- fare - 탑승 요금
- cabin - 객실 넘버
- bembarked - 탑승 항구
1. 데이터 셋 확인¶
import os # 운영체제에서 제공되는 여러 기능을 파이썬에서 수행할 수 있게 해주는 도구
import numpy as np # 행렬 연산
import pandas as pd # 행과 열로 이루어진 데이터 객체를 만들어 대용량의 데이터들을 처리하는데 편리한 도구
import matplotlib.pyplot as plt # 차트나 플롯을 그려주는 시각화 도구
import seaborn as sns # 데이터 분포 시각화 도구
import keras # 딥러닝 도구
import sklearn # 딥러닝 도구
plt.style.use('seaborn')
sns.set(font_scale=2.5)
import missingno as msno # 누적 데이터에 대한 시각화 도구
import warnings
warnings.filterwarnings('ignore') # 워닝 메세지를 생략
%matplotlib inline
os.listdir("./titanic_dataset")
파일 경로에 있는 파일 리스트 확인
df_train = pd.read_csv("./titanic_dataset/train.csv")
df_test = pd.read_csv("./titanic_dataset/test.csv")
df_submit = pd.read_csv("./titanic_dataset/gender_submission.csv")
df_train.shape
df_train.columns
column 12개로 이루어져 있고, feature 11개, 예측해야 할 feature 은 'Survived' 이다.
df_train.head()
df_train.describe()
describe() 메소드는 각 feature가 가진 통계치를 반환해준다.
df_train.isnull().sum() / df_train.shape[0]
fig, ax = plt.subplots(1, 2, figsize=(18, 8))
df_train['Survived'].value_counts().plot.pie(explode=[0, 0.1],
autopct='%1.1f%%', ax=ax[0], shadow=True)
ax[0].set_title('Pie plot - Survived')
ax[0].set_ylabel('')
sns.countplot('Survived', data=df_train, ax=ax[1])
ax[1].set_title('Count plot - Survived')
plt.show()
explode : pie 그래프간 떨어진 정도를 나타낸다.
autopct : 그래프 위에 반환되는 수치의 형식을 나타낸다.
df_train[['Pclass', 'Survived']].groupby(['Pclass'], as_index=True).count()
# Pclass 그룹 별 생존자 수 합
df_train[['Pclass', 'Survived']].groupby(['Pclass'], as_index=True).sum()
# 위에서 한 작업을 pandas.crosstab 으로 편하게 할 수 있다. - 데이터 재구조화
pd.crosstab(df_train['Pclass'], df_train['Survived'], margins=True)
df_train[['Pclass', 'Survived']].groupby(['Pclass'], as_index=True).mean().plot.bar()
2. Sex 에 따른 생존률¶
fig, ax = plt.subplots(1, 2, figsize=(18,8))
df_train[['Sex', 'Survived']].groupby(['Sex'], as_index=True).mean().plot.bar(ax=ax[0])
ax[0].set_title('Survived vs Sex')
sns.countplot('Sex', hue='Survived', data=df_train, ax=ax[1])
ax[1].set_title('Sex : Survived vs Dead')
plt.show()
3. Both Sex and Pclss¶
sns.factorplot('Pclass', 'Survived', hue='Sex', data=df_train, size=6, aspect=1.5)
4. Age¶
fig, ax = plt.subplots(1, 1, figsize=(9,5))
sns.kdeplot(df_train[df_train['Survived']==1]['Age'], ax=ax)
sns.kdeplot(df_train[df_train['Survived']==0]['Age'], ax=ax)
plt.legend(['Survived == 1', 'Survived == 0'])
plt.show()
plt.figure(figsize=(8, 6))
df_train['Age'][df_train['Pclass'] == 1].plot(kind='kde')
df_train['Age'][df_train['Pclass'] == 2].plot(kind='kde')
df_train['Age'][df_train['Pclass'] == 3].plot(kind='kde')
plt.xlabel('Age')
plt.title('Age Distribution within classes')
plt.legend(['1st class', '2nd class', '3rd class'])
cummulate_survival_ratio = []
for i in range(1, 80):
cummulate_survival_ratio.append(df_train[df_train['Age'] < i]['Survived'].sum()
/ len(df_train[df_train['Age'] < i]['Survived']))
plt.figure(figsize=(7,7))
plt.plot(cummulate_survival_ratio)
plt.title('Survival rate change depending on range of Age')
plt.ylabel('Survival rate')
plt.xlabel('Range of Age(0~x)')
plt.show()
5. Embarked¶
f, ax = plt.subplots(1, 1, figsize=(7,7))
df_train[['Embarked', 'Survived']].groupby(['Embarked'], as_index=True).mean().plot.bar(ax=ax)
fig, ax = plt.subplots(2,2,figsize=(20,15))
sns.countplot('Embarked', data = df_train, ax=ax[0,0])
ax[0,0].set_title('(1) No. of Passengers Boarded')
sns.countplot('Embarked', hue='Sex', data=df_train, ax=ax[0,1])
ax[0,1].set_title('(2) Male-Female Split for Embakrd')
sns.countplot('Embarked', hue='Survived', data=df_train, ax=ax[1,0])
ax[1,0].set_title('(3) Embarked vs Survived')
sns.countplot('Embarked', hue='Pclass', data=df_train, ax=ax[1,1])
ax[1,1].set_title('(4) Embarked vs Pclass')
plt.subplots_adjust(wspace=0.2, hspace=0.5)
plt.show()
6. Family - SibSp(형제 자매) + Parch(부모, 자녀)¶
df_train['FamilySize'] = df_train['SibSp'] + df_train['Parch'] + 1
df_test['FamilySize'] = df_test['SibSp'] + df_test['Parch'] + 1
print('Max: ', df_train['FamilySize'].max())
print('Min: ', df_train['FamilySize'].min())
fig, ax = plt.subplots(1, 3, figsize = (40,10))
sns.countplot('FamilySize', data = df_train, ax=ax[0])
ax[0].set_title('(1) No. Of Passengers Boarded')
sns.countplot('FamilySize', hue='Survived', data = df_train, ax=ax[1])
ax[1].set_title('(2) Survived countplot depending on FamilySize')
df_train[['FamilySize', 'Survived']].groupby(['FamilySize'],
as_index=True).mean().sort_values(by='Survived', ascending=False).plot.bar(ax=ax[2])
ax[2].set_title('(3) Survived rate depending on FamilySize')
plt.subplots_adjust(wspace=0.2, hspace=0.5)
plt.show()
fig, ax = plt.subplots(1, 1, figsize=(8,8))
g = sns.distplot(df_train['Fare'], label='Sewness', ax=ax)
df_test.loc[df_test.Fare.isnull(), 'Fare']= df_test['Fare'].mean()
df_train['Fare'] = df_train['Fare'].map(lambda i: np.log(i) if i > 0 else 0)
df_test['Fare'] = df_test['Fare'].map(lambda i: np.log(i) if i > 0 else 0)
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
g = sns.distplot(df_train['Fare'], color='b', label='Skewness : {:.2f}'.format(df_train['Fare'].skew()), ax=ax)
g = g.legend(loc='best')
8. Cabin¶
# Cabin feature Null 비율 계산
df_train['Cabin'].isnull().sum() / df_train.shape[0]
Null 비율이 77% 으로 모델에 포함시키지 않는다
9. Ticket¶
df_train['Ticket'].value_counts()
티켓 넘버가 매우 다양하다. 어떤 특징을 이끌어내서 생존과 연결시킬수 있을까?
# 이름의 title 위치 파악
df_train[['Name']]
# lets extract the Salutations
# 정규 표현식을 적용하게 해주는 extract 사용
df_train['Initial'] = df_train.Name.str.extract('([A-Za-z]+)\.')
df_test['Initial'] = df_test.Name.str.extract('([A-Za-z]+)\.')
pd.crosstab(df_train['Initial'], df_train['Sex']).T.style.background_gradient(cmap='summer_r')
df_train['Initial'].replace(['Mlle','Mme','Ms','Dr','Major','Lady','Countess','Jonkheer',
'Col','Rev','Capt','Sir','Don', 'Dona'],
['Miss','Miss','Miss','Mr','Mr','Mrs','Mrs',
'Other','Other','Other','Mr','Mr','Mr', 'Mr'],inplace=True)
df_test['Initial'].replace(['Mlle','Mme','Ms','Dr','Major','Lady','Countess','Jonkheer',
'Col','Rev','Capt','Sir','Don', 'Dona'],
['Miss','Miss','Miss','Mr','Mr','Mrs','Mrs',
'Other','Other','Other','Mr','Mr','Mr', 'Mr'],inplace=True)
df_train.groupby('Initial').mean()
df_train.groupby('Initial')['Survived'].mean().plot.bar()
df_train.groupby('Initial').mean()
# null 값들을 각 Initial 별 평균값으로 채워준다.
df_train.loc[(df_train.Age.isnull())&(df_train.Initial=='Mr'),'Age'] = 33
df_train.loc[(df_train.Age.isnull())&(df_train.Initial=='Mrs'),'Age'] = 36
df_train.loc[(df_train.Age.isnull())&(df_train.Initial=='Master'),'Age'] = 5
df_train.loc[(df_train.Age.isnull())&(df_train.Initial=='Miss'),'Age'] = 22
df_train.loc[(df_train.Age.isnull())&(df_train.Initial=='Other'),'Age'] = 46
df_test.loc[(df_test.Age.isnull())&(df_test.Initial=='Mr'),'Age'] = 33
df_test.loc[(df_test.Age.isnull())&(df_test.Initial=='Mrs'),'Age'] = 36
df_test.loc[(df_test.Age.isnull())&(df_test.Initial=='Master'),'Age'] = 5
df_test.loc[(df_test.Age.isnull())&(df_test.Initial=='Miss'),'Age'] = 22
df_test.loc[(df_test.Age.isnull())&(df_test.Initial=='Other'),'Age'] = 46
3.2 Fill Null in Embarked¶
# Null 값이 몇 개인지 확인한다.
df_train['Embarked'].isnull().sum()
# fillna 를 사용하여 null 값을 쉽게 채울 수 있다.
df_train['Embarked'].fillna('S', inplace=True)
3.3 Change Age(continuous to categorical)¶
Age는 현재 Continuous feature 이다. Age를 그룹으로 나누어 category 화 시켜줄 수 있다.
자칫 information loss 가 생길 수도 있지만, 지금은 category화 시켜 진행하겠다.
def category_age(x):
if x < 10:
return 0
elif x < 20:
return 1
elif x < 30:
return 2
elif x < 40:
return 3
elif x < 50:
return 4
elif x < 60:
return 5
elif x < 70:
return 6
else:
return 7
df_train['Age_cat'] = df_train.Age.apply(category_age)
df_test['Age_cat'] = df_test.Age.apply(category_age)
df_train.groupby(['Age_cat'])['PassengerId'].count()
3.4 change Initial, Embarked and Sex(sting to numerical)¶
컴퓨터가 인식할 수 있도록 수치화 시켜준다.
map 메소드를 통해 간단히 할 수 있다.
df_train['Initial'] = df_train['Initial'].map({'Master': 0, 'Miss': 1, 'Mr': 2, 'Mrs': 3, 'Other': 4})
df_test.Initial = df_test.Initial.map({'Master': 0, 'Miss': 1, 'Mr': 2, 'Mrs': 3, 'Other': 4})
df_train['Embarked'] = df_train['Embarked'].map({'C': 0, 'Q': 1, 'S': 2})
df_test['Embarked'] = df_test['Embarked'].map({'C': 0, 'Q': 1, 'S': 2})
df_train['Embarked'].isnull().any() , df_train['Embarked'].dtypes
df_train['Sex'] = df_train['Sex'].map({'female': 0, 'male': 1})
df_test['Sex'] = df_test['Sex'].map({'female': 0, 'male': 1})
df_train.columns
# feature 간의 상관관계를 구한다.(correlation)
# -1 로 갈수록 음의 상관관계
# 1로 갈수록 양의 상관관계
# 0은 상관관계가 없다는 것을 의미
heatmap_data = df_train[['Survived', 'Pclass', 'Sex', 'Fare', 'Embarked',
'FamilySize', 'Initial', 'Age_cat', 'Age']]
# astype : float 형태로 지정(assign), annot : 숫자 표시, annot_kws : 폰트 사이즈
colormap = plt.cm.Blues
plt.figure(figsize=(14, 12))
plt.title('Pearson Correlation of Features', y=1.05, size=15)
sns.heatmap(heatmap_data.astype(float).corr(), linewidths=0.1, vmax=1.0,
square=True, cmap=colormap, linecolor='white', annot=True, annot_kws={"size": 16})
del heatmap_data
3.5 one-hot encoding on initial and Embarked¶
one-hot encoding 이란?</br>
원-핫 인코딩은 집합의 크기를 벡터의 차원으로 하고, 표현하고 싶은 단어의 인덱스에 1의 값을 부여하고, 다른
인덱스에는 0을 부여하는 단어의 벡터 표현 방식이다. 이렇게 표현된 벡터를 one-hot vector 라고 한다.
# pd.get_dummies 를 이용하여 쉽게 one-hot encoding 할 수 있다.
df_train = pd.get_dummies(df_train, columns=['Initial'], prefix='Initial')
df_test = pd.get_dummies(df_test, columns=['Initial'], prefix='Initial')
df_train.head()
df_train = pd.get_dummies(df_train, columns=['Embarked'], prefix='Embarked')
df_test = pd.get_dummies(df_test, columns=['Embarked'], prefix='Embarked')
3.6 Drop columns¶
df_train.drop(['PassengerId', 'Name', 'SibSp', 'Parch', 'Ticket', 'Cabin'], axis=1, inplace=True)
df_test.drop(['PassengerId', 'Name', 'SibSp', 'Parch', 'Ticket', 'Cabin'], axis=1, inplace=True)
df_train.head()
df_train.dtypes
4. 모델 개발 및 학습¶
#importing all the required ML packages
from sklearn.ensemble import RandomForestClassifier # 유명한 randomforestclassfier 입니다.
from sklearn import metrics # 모델의 평가를 위해서 씁니다
from sklearn.model_selection import train_test_split # traning set을 쉽게 나눠주는 함수입니다.
4.1 Preparation - Split dataset into train, valid(dev), test set¶
가장 먼저 학습에 쓰일 데이터와, target label(Survived)를 분리시켜 준다.
X_train = df_train.drop('Survived', axis=1).values
target_label = df_train.Survived.values
X_test = df_test.values
X_train.shape, X_test.shape
# 좋은 모델을 만들기 위해서 Valid(dev) set 을 따로 만들어 모델을 평가한다
# train_test_split(arrays, test_size, train_size, random_state, shuffle, stratify)
# arrays : 분할 시킬 데이터
# test_size : 테스트 데이터셋의 비율이나 갯수
# random_state : 데이터 분할시 셔플이 이루어지는데 이를 위한 시드값
# shuffle : 셔플 여부 설정(default = True)
# stratify : 지정한 데이터의 비율을 유지
# Return : X_train, X_test, Y_train, Y_test : arrays에 데이터와 레이블을 둘 다 넣었을 경우에 반환
X_tr, X_vld, y_tr, y_vld = train_test_split(X_train, target_label
, test_size=0.2, random_state=2018)
4.2 Model generation and prediction¶
sklearn 알고리즘의 하나인 렌덤 포레스트 모델을 생성하고 학습한다
랜덤포레스트는 결정트리기반 모델이며, 여러 결정 트리들을 앙상블한 모델이다.
# 랜덤포레스트 생성, 학습, 예측
model = RandomForestClassifier()
model.fit(X_tr, y_tr)
prediction = model.predict(X_vld)
print('총 {}명 중 {:.2f}% 정확도로 생존을 맞춤'.format(y_vld.shape[0], 100 * metrics.accuracy_score(prediction, y_vld)))
from pandas import Series
feature_importance = model.feature_importances_
Series_feat_imp = Series(feature_importance, index = df_test.columns)
plt.figure(figsize=(8,8))
Series_feat_imp.sort_values(ascending=True).plot.barh()
plt.xlabel("Feature Importance")
plt.ylabel("Feature")
plt.show()
4. Keras를 사용한 NN 모델 개발¶
from keras.models import Sequential
from keras.layers.core import Dense, Dropout
from keras.optimizers import Adam, SGD
nn_model = Sequential()
nn_model.add(Dense(32,activation='relu',input_shape=(14,)))
nn_model.add(Dropout(0.2))
nn_model.add(Dense(64,activation='relu'))
nn_model.add(Dropout(0.2))
nn_model.add(Dense(32,activation='relu'))
nn_model.add(Dropout(0.2))
nn_model.add(Dense(1,activation='sigmoid'))
Loss = 'binary_crossentropy'
nn_model.compile(loss=Loss,optimizer=Adam(),metrics=['accuracy'])
nn_model.summary()
history = nn_model.fit(X_tr,y_tr,
batch_size=64,
epochs=500,
validation_data=(X_vld, y_vld),
verbose=1)
hists = [history]
hist_df = pd.concat([pd.DataFrame(hist.history) for hist in hists], sort=True)
hist_df.index = np.arange(1, len(hist_df)+1)
fig, axs = plt.subplots(nrows=2, sharex=True, figsize=(16, 10))
axs[0].plot(hist_df.val_acc, lw=5, label='Validation Accuracy')
axs[0].plot(hist_df.acc, lw=5, label='Training Accuracy')
axs[0].set_ylabel('Accuracy')
axs[0].set_xlabel('Epoch')
axs[0].grid()
axs[0].legend(loc=0)
axs[1].plot(hist_df.val_loss, lw=5, label='Validation MLogLoss')
axs[1].plot(hist_df.loss, lw=5, label='Training MLogLoss')
axs[1].set_ylabel('MLogLoss')
axs[1].set_xlabel('Epoch')
axs[1].grid()
axs[1].legend(loc=0)
fig.savefig('hist.png', dpi=300)
plt.show();
'AI > Deep Learning' 카테고리의 다른 글
딥러닝: 04. Logistic Classification(로지스틱 회귀) (0) | 2019.07.30 |
---|---|
딥러닝: 03. 다중 선형 회귀(Multi Variable linear regression) (0) | 2019.07.30 |
딥러닝: 02. 경사하강법(Gradient descent algorithm) (0) | 2019.07.30 |
딥러닝 : 01. Tensorflow의 정의 (0) | 2019.07.26 |
딥러닝 : 로지스틱 회귀 코딩 (0) | 2019.07.25 |
댓글