본문 바로가기

ML

[ML] 타이타닉 생존자 예측하기

타이타닉 데이터 셋으로 생존자를 예측하여 캐글 경진대회를 입문해보고자 한다.

순서는 EDA - Feature Engineering - Modeling으로 진행된다.

cf. 캐글 경진대회란?

👉 Kaggle이 궁금해? Kaggle의 모든 것! : 네이버 블로그 (naver.com)

 


타이타닉 데이터 셋

데이터 셋에는 승객의 정보, 생존에 대한 정보가 들어있다.

승객의 정보를 토대로 해당 승객이 생존했는지를 예측하는 것이 목표이다.

주어진 데이터셋은 아래와 같다.

# 상위 5개의 row 조회
train.head()
 
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
 
  • Survived : 0 = 사망, 1 = 생존
  • pclass : Ticket class 1 = 1st, 2 = 2nd, 3 = 3rd
  • sibsp : (siblings + spouses) 형제나 배우자
  • parch : (parents + children) 부모나 자식
  • ticket : Ticket number
  • fare : 요금
  • cabin : 객실 번호
  • embarked : 선착장 정보 C = Cherbourg, Q = Queenstown, S = Southampton

이미 알려진 타이타닉의 정보를 토대로 아래의 내용을 유추할 수 있다.

- 아래부터 가라앉았으므로 3등석보다 1등석의 생존 확률이 높음

- 여성과 아이들의 생존 확률이 높음

 


Data Formation

Feature Engineering을 하기 전에 데이터의 형태를 살펴볼 필요가 있다.
 

1. shape

train.shape
(418, 11)
test.shape
(891, 12)

train 세트에는 891명의 승객 정보가 있고, 12개의 column이 있다.

test 세트에는 418명의 승객 정보가 있고, 11개의 column이 있다.

train 세트와 비교했을 때, test 세트의 column이 하나 부족하다.

=> 예측해야할 데이터인 Survived column은 test에 없기 때문!

 

2. isnull()

pandas에서 제공하는 isnull() 함수로 결측치를 확인할 수 있다.

결측치는 평균값을 대입하거나 데이터 자체를 삭제하는 등의 방법으로 Feature Engineering 단계에서 보정해야 한다.

train.isnull().sum()
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64
 

 

test.isnull().sum()
PassengerId      0
Pclass           0
Name             0
Sex              0
Age             86
SibSp            0
Parch            0
Ticket           0
Fare             1
Cabin          327
Embarked         0
dtype: int64

👉 Age, Cabin, Fare의 정보가 부족함을 알 수 있다.

 


Visualization

bar chart (막대그래프)를 이용해 각 피쳐에 대한 생존, 사망을 시각화하자.

# 변수로 집어넣은 feature에 대해 bar chart를 그리는 함수
def bar_chart(feature):
    survived = train[train['Survived']==1][feature].value_counts()
    dead = train[train['Survived']==0][feature].value_counts()
    df = pd.DataFrame([survived,dead])
    df.index = ['Survived','Dead']
    df.plot(kind='bar',stacked=True, figsize=(10,5))
 

 

bar_chart('Sex')
👉 여성이 남성보다 많이 살아남았다.

 

 

bar_chart('Pclass')
👉 1등석의 생존 확률이 가장 높으며, 3등석이 가장 많이 사망했다.

 

 

bar_chart('SibSp')
👉 형제나 배우자가 없는 경우 사망 확률이 더 높다.

 

 

bar_chart('Parch')
👉 부모나 자식이 없는 경우 사망 확률이 더 높다.

 

 

bar_chart('Embarked')
👉 S 선착장에서 탑승한 경우 사망 확룔이 더 높다.

 

 


Feature engineering

Feature engineering은 데이터에 대한 도메인 지식을 바탕으로 feature을 기계가 학습하기 쉽게 바꾸는 작업을 말한다.

ex. 시간에 대해 학습할 때, 오후 2시 를 14:00으로 바꿀 수 있음

본 실습에서 feature engineering은 아래의 과정으로 진행된다.

 

1. feature를 유의미한 numerical vector로 나타내기

기계가 학습할 수 있도록 문자형, 범주형 데이터를 숫자로 바꿔준다.

  • Name에서 유의미한 정보인 Mr, Miss, Mrs를 추출하여 숫자로 매핑
  • Sex에서 'male', 'female'을 각각 0, 1로 매핑
  • Age의 이산형 변수가 유의미하도록 binning
  • 선착장 정보 'S', 'Q', 'C'를 각각 0, 1, 2로 매핑
  • 객실 번호에서 가장 앞 알파벳을 숫자로 매핑
  • SibSp(형제나 베우자)와 Parch(부모나 자식)을 묶어 FamilySize 피쳐로 나타내기

2. null data를 보정

  • Age의 NaN 데이터를 Title의 중간값으로 보정
    ex. Title이 Miss인 사람의 나이가 null이면, Miss의 나이 중간값 대입
  • Fare의 null 데이터를 각 좌석의 중간값으로 보정
    ex. 1등석의 요금이 null이면, 1등석 요금의 중간값 대입

3. 필요 없는 feature 제거

 

👉 Feature Engineering을 적용하여 필요한 데이터를 숫자로만 나타낼 수 있다.

❕ Feature Engineering 이전

PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S

❕ Feature Engineering 이후

Survived Pclass Sex Age Fare Cabin Embarked Title FamilySize
0 3 0 1 0 2.0 0 0 0.4
1 1 1 3 2 0.8 1 2 0.4
1 3 1 1 0 2.0 0 1 0.0
1 1 1 2 2 0.8 0 2 0.4
0 3 0 2 0 2.0 0 0 0.0

자세한 과정은 깃허브에 정리해두었습니다. (깃허브 바로가기)

 


Modeling

여러 모델을 이용해 데이터를 학습하고, 교차검증 점수로 모델의 성능을 평가해보자.

사용하는 모델 : KNN, DecisionTree, RandomForest, Naive Bayes, GradientBoosting, XGB, LightGBM, CatBoosting, Ensenble

(본 실습에서는 교차검증의 개념, 모델의 원리는 다루지 않습니다.)

# 교차 검증에 필요한 라이브러리 임포트
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
k_fold = KFold(n_splits=10, shuffle=True, random_state=0)

# 분류기 모델 임포트
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import GradientBoostingClassifier
from xgboost import XGBClassifier

 

❕ KNN

clf = KNeighborsClassifier(n_neighbors = 13)
scoring = 'accuracy'
score1 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score1)*100, 2)
82.04

 

❕ Decision Tree
 
clf = DecisionTreeClassifier()
score2 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score2)*100, 2)
80.02

 

❕ Random Forest

clf = RandomForestClassifier(n_estimators=13)
score3 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score3)*100, 2)
81.59
 

❕ Naive Bayes

clf = GaussianNB()
score4 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score4)*100, 2)
78.56

 

❕ Gradient Boost

clf = GradientBoostingClassifier(n_estimators = 100)
score5 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score5)*100, 2)
83.16

 

❕ XGBoost

clf = XGBClassifier()
score6 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score6)*100, 2)
83.5

 

❕ Light GBM

Colab에서 Light GBM 설치 방법 : https://url.kr/nkq8fo

from lightgbm import LGBMClassifier
clf = LGBMClassifier()
score7 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score7)*100, 2)
82.94

 

 

❕ Cat Boost

Colab에서 Cat Boost 설치 방법 : https://url.kr/1gwrtm

from catboost import CatBoostClassifier
clf = CatBoostClassifier(silent=True)
score8 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score8)*100, 2)
82.83
 
 

❕ 앙상블 학습

KNN, Random Forest, Cat Boost로 앙상블 학습을 해보자.

from sklearn.ensemble import VotingClassifier

# 개별 모델 생성
knn = KNeighborsClassifier(n_neighbors = 13)
rf = RandomForestClassifier(n_estimators=13)
cb = CatBoostClassifier(silent=True)

voting_model = VotingClassifier(
    estimators=[('knn',knn),('rf',rf),('cb',cb)],
    voting='soft'
)

score10 = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)

round(np.mean(score10)*100, 2)
83.5

 


Submission

교차 검증의 점수가 가장 좋았던 XGB 모델로 제출 파일을 만들어보자.

clf = XGBClassifier() # 모델 생성
clf.fit(train_data, target) # 모델 학습

test_data = test.drop("PassengerId", axis=1).copy() # PassengerId 없는 데이이터 얕은 복사
prediction = clf.predict(test_data)

캐글에서 요구한 형식에 맞게 예측값과 PassengerId로 Data frame을 만들고, csv 파일로 변환한다.

submission = pd.DataFrame({
        "PassengerId": test["PassengerId"],
        "Survived": prediction
    })

submission.to_csv('submission.csv', index=False)

 

결과!!

13000명 중 11187 등으로 상위 80%라는 처참한 성적을 받았다😥

 

타이타닉 예제만 따로 연구할 정도로 데이터셋이 널리 알려져 있어서 낮은 성적을 받아도 실망하지 말라는 조언을 들었지만..!

그래도 뭔가 슬펐다😓

계속 모델에 대해 배우며 좀 더 정확도를 높일 방법을 찾아갈 계획이다!!🔥

 

소스코드 : Pytorch/titanic_solution.ipynb at main · nayonsoso/Pytorch (github.com)

참고 강의 : https://youtu.be/aqp_9HV58Ls (강추!!)

 

GitHub - nayonsoso/Pytorch

Contribute to nayonsoso/Pytorch development by creating an account on GitHub.

github.com

'ML' 카테고리의 다른 글

[ML] 교차 검증  (0) 2022.02.20
[ML] Fashion MNIST  (0) 2022.02.13
[ML] CNN  (0) 2022.01.23
[ML] 소프트맥스 회귀 (Softmax Regression)  (1) 2022.01.09
[ML] 특성 공학과 규제  (1) 2021.11.05