타이타닉 데이터 분석(3)

0. 현재 상황 파악하기

안녕하세요! 오늘이 타이타닉 관련 마지막 포스팅이 될 것 같습니다. 지금까지 Titanic 데이터셋을 분석한 것을 토대로, 오늘은 사이킷런을 이용해 다양한 모델을 훈련시키고 그에 대한 정확성 검증, 그리고 마지막으로 Kaggle에 제출까지 해보도록 하겠습니다!

먼저 지난 포스트 에서 데이터 전처리와 Feature Engineering을 한 거 기억나시나요? 그 데이터를 불러와보겠습니다.

import pandas as pd
train = pd.read_csv('kaggle/titanic/train_pre.csv')
test = pd.read_csv('kaggle/titanic/test_pre.csv')

train.head()
PassengerId Survived Pclass Sex SibSp Parch Embarked Prefix AgeCut FareCut
0 1 0 3 0 1 0 0 0 1 0
1 2 1 1 1 1 0 1 2 3 3
2 3 1 3 1 0 0 0 1 1 1
3 4 1 1 1 1 0 0 2 2 3
4 5 0 3 0 0 0 0 0 2 1
test.head()
PassengerId Pclass Sex SibSp Parch Embarked Prefix AgeCut FareCut
0 892 3 0 0 0 2 0 2 0
1 893 3 1 1 0 0 2 3 0
2 894 2 0 0 0 2 0 3 1
3 895 3 0 0 0 0 0 1 1
4 896 3 1 1 1 0 2 0 1

모든 행이 NaN 없이 정수로 깔끔하게 정리되어 있는 것을 확인할 수 있습니다.


1. 훈련 데이터와 라벨 분리하기

위에서 보셨듯이 데이터가 정수형으로 예쁘게 전처리가 완료되어 있지만, 아직 모델을 저 데이터셋으로 훈련시킬 수는 없습니다. 모델이 이 데이터를 학습하는 과정은 ‘지도 학습’ 이기 때문에, 라벨을 분리시킬 필요가 있습니다. 쉽게 말하면 문제지와 정답을 분리하는 것이죠.
이 데이터에서의 라벨Survived 행이 될 겁니다.

label = train['Survived']
train.drop('Survived', axis=1, inplace=True)

train.head()
PassengerId Pclass Sex SibSp Parch Embarked Prefix AgeCut FareCut
0 1 3 0 1 0 0 0 1 0
1 2 1 1 1 0 1 2 3 3
2 3 3 1 0 0 0 1 1 1
3 4 1 1 1 0 0 2 2 3
4 5 3 0 0 0 0 0 2 1

2. 식별자 행 분리시키기

좋습니다. 이제 라벨도 따로 분리시켰습니다. 이제 마지막으로 식별자 행은 예측에 아무런 도움이 되지 않기 때문에, 아예 식별자로 만들어 버리거나, 테이블에서 Drop해버리는 것이 좋습니다. 여기서는 set_index()로 식별자라고 명시해주겠습니다.

train.set_index('PassengerId', inplace=True)
test.set_index('PassengerId', inplace=True)

train.head()
Pclass Sex SibSp Parch Embarked Prefix AgeCut FareCut
PassengerId
1 3 0 1 0 0 0 1 0
2 1 1 1 0 1 2 3 3
3 3 1 0 0 0 1 1 1
4 1 1 1 0 0 2 2 3
5 3 0 0 0 0 0 2 1
test.head()
Pclass Sex SibSp Parch Embarked Prefix AgeCut FareCut
PassengerId
892 3 0 0 0 2 0 2 0
893 3 1 1 0 0 2 3 0
894 2 0 0 0 2 0 3 1
895 3 0 0 0 0 0 1 1
896 3 1 1 1 0 2 0 1

좋습니다. 이제 준비 끝!


3. Train 데이터로 여러 모델 교차 검증하기

이제 저렇게 고생해서 얻은 데이터를 모델에 넣고 test 데이터를 예측할 일만 남았습니다. 모델은 사이킷런 라이브러리에서 제공하는 분류기를 사용할겁니다. 먼저 필요한 라이브러리들을 import하겠습니다.

from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB

위에서부터 SVM, KNN, 결정 트리, 랜덤 포레스트, 나이브 베이즈 모델입니다. 이 모델들의 작동 원리는 저도 아직 얕게 알고 있으며 현재 배우는 단계입니다. 하지만 이 모델들은 사이킷런에서 제공하는 대표적인 분류 모형이기 때문에, 이 5개의 분류기를 타이타닉 데이터에 적용시켜 보고 K-Fold를 이용해서 정확성을 검증하고, 가장 좋은 점수를 받은 모델을 선택하도록 하겠습니다.
그러기 위해서 교차 검증에 필요한 라이브러리도 추가로 import 하도록 하겠습니다. 교차 검증에 대해서 모르시는 분들은 우선 보시고, 나중에 따로 관련된 포스팅을 하도록 하겠습니다.

import numpy as np
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
k_fold = KFold(n_splits=20, shuffle=True, random_state=0)

이제 사이킷런으로 모델을 생성하고, 교차 검증하며 점수를 매기겠습니다.

clf = SVC(gamma='auto')
scoring = 'accuracy'
score = cross_val_score(clf, train, label, cv=k_fold, n_jobs=1, scoring=scoring)
print(score)
print("점수 평균 : " + str(round(np.mean(score)*100, 2)))
[0.73333333 0.71111111 0.71111111 0.75555556 0.91111111 0.84444444
 0.73333333 0.86666667 0.93333333 0.86363636 0.84090909 0.75
 0.90909091 0.88636364 0.79545455 0.77272727 0.79545455 0.84090909
 0.90909091 0.86363636]
점수 평균 : 82.14

clf = KNeighborsClassifier(n_neighbors = 13)
scoring = 'accuracy'
score = cross_val_score(clf, train, label, cv=k_fold, n_jobs=1, scoring=scoring)
print(score)
print("점수 평균 : " + str(round(np.mean(score)*100, 2)))
[0.75555556 0.71111111 0.71111111 0.73333333 0.86666667 0.84444444
 0.71111111 0.88888889 0.86666667 0.88636364 0.81818182 0.75
 0.90909091 0.88636364 0.75       0.75       0.77272727 0.88636364
 0.90909091 0.86363636]
점수 평균 : 81.35

clf = DecisionTreeClassifier()
scoring = 'accuracy'
score = cross_val_score(clf, train, label, cv=k_fold, n_jobs=1, scoring=scoring)
print(score)
print("점수 평균 : " + str(round(np.mean(score)*100, 2)))
[0.82222222 0.64444444 0.75555556 0.73333333 0.86666667 0.8
 0.64444444 0.84444444 0.84444444 0.81818182 0.77272727 0.79545455
 0.93181818 0.86363636 0.84090909 0.77272727 0.79545455 0.84090909
 0.72727273 0.79545455]
점수 평균 : 79.55

clf = RandomForestClassifier(n_estimators=20)
scoring = 'accuracy'
score = cross_val_score(clf, train, label, cv=k_fold, n_jobs=1, scoring=scoring)
print(score)
print("점수 평균 : " + str(round(np.mean(score)*100, 2)))
[0.8        0.66666667 0.75555556 0.77777778 0.88888889 0.82222222
 0.64444444 0.86666667 0.84444444 0.86363636 0.81818182 0.79545455
 0.90909091 0.84090909 0.75       0.75       0.81818182 0.84090909
 0.72727273 0.84090909]
점수 평균 : 80.11

clf = GaussianNB()
scoring = 'accuracy'
score = cross_val_score(clf, train, label, cv=k_fold, n_jobs=1, scoring=scoring)
print(score)
print("점수 평균 : " + str(round(np.mean(score)*100, 2)))
[0.71111111 0.66666667 0.75555556 0.73333333 0.86666667 0.82222222
 0.71111111 0.88888889 0.86666667 0.88636364 0.79545455 0.72727273
 0.88636364 0.81818182 0.79545455 0.70454545 0.75       0.79545455
 0.79545455 0.88636364]
점수 평균 : 79.32


4. SVM으로 승객 생사 예측하기

확인해보니 SVM이 가장 평균 점수가 높습니다. 그러므로 훈련 데이터를 사용해서 SVM 모델을 만들고, test 데이터로 예측 값을 뽑아보겠습니다.

clf = SVC(gamma='auto')
clf.fit(train, label)
prediction = clf.predict(test)

pred = pd.DataFrame({"PassengerId" : test.index, 
                    "Survived" : prediction})
pred.head(10)
PassengerId Survived
0 892 0
1 893 1
2 894 0
3 895 0
4 896 1
5 897 0
6 898 1
7 899 0
8 900 1
9 901 0

이제 진짜 끝났습니다! Kaggle에 제출만 하면 되는데, 제출하려면 우리의 Prediction을 csv 형식으로 저장해서 업로드하면 됩니다. 제출 형식에 Index는 빠져 있기 때문에, Index는 빼고 저장하겠습니다.

pred.to_csv('kaggle/titanic/submission.csv', index=False)

5. Kaggle에 제출하고 결과 확인하기

자 이제 정말 제출하는 일만 남았습니다. 제출은 여기에서 하시면 됩니다. 저는 이미 제출한 상태이기 때문에 점수만 알려드리자면, 0.77511을 받았습니다. 대충 중위권 정도인 것 같습니다. 나중에 숙련돼서 하이퍼파라미터 세팅과 데이터 전처리를 더 잘하게 되면 더 좋은 점수를 얻을 수 있지 않을까 싶습니다. 감사합니다!

댓글남기기