상세 컨텐츠

본문 제목

[K-DIGITAL] 세미프로젝트2. 타이타닉 생존자 예측 모델 만들기(1)

PYTHON/K-DIGITAL

by ranlan 2021. 7. 5. 16:43

본문

728x90

멋쟁이사자처럼 X K-DIGITAL Training - 07.05

 

 

[github] https://github.com/ijo0r98/likelion-kdigital/tree/main/semi-project-2

 

ijo0r98/likelion-kdigital

멋쟁이사자처럼 & K-DIGITAL. Contribute to ijo0r98/likelion-kdigital development by creating an account on GitHub.

github.com


 

타이타닉 생존자 예측(1) 데이터 전처리부터 다양한 모델 예측까지

 

 

 

 

0. 라이브러리

import warnings
warnings.filterwarnings("ignore")

import pandas as pd
import numpy as np

 

 

1. Data Preparing

data_df = pd.read_csv('titanic.csv')

data_df

y_data = data_df[['Survived']] # target data
del data_df['Survived']

 

* 컬럼 정보

- PassengerId : 각 승객 고유번호
- Survived : 생존여부
- Pclass : 객실 등급 (1 / 2 / 3)
- Name : 승객 이름
- Sex : 성별
- Age : 나이
- SibSp : 동반한 형재자매, 배우자 수
- Parch : 동반한 부모, 자식 수
- Ticket : 티켓 고유번호
- Fare : 티켓 요금
- Cabin : 객실 번호
- Embarked : 승선한 항 (C-Cherbourg / Q-Queenstown / S-Southampton)

 

 

 

2. Feature Engineering & Feature Selection

2-1. 결측치 확인

data_df.isnull().sum()

missionno 라이브러리로 결측치 시각화

import quilt
import missingno as msno
import matplotlib.pyplot as plt

msno.matrix(data_df)
msno.bar(data_df)

matirx
bar

→ 결측치 있는 열: Age, Cabin, Embarked

 

 

2-1-1) Cabin (객실번호)

- 해당 열 삭제

del data_df['Cabin']

 

2-1-2) Embarked (승선한 항)

data_df[data_df.Embarked.isnull()]

- 두 승객 모두 1등급에 탑승한 승객

- 두 승객과 동일하게 1등급에 탑승한 승객들의 Embarked별 요금의 평균 구하여 비교

# 1등급 승객
class1st = data_df[data_df.Pclass == 1]

# 1등급 승객 중 각 Embarked별 Fare 평균
class1st_C = class1st[class1st.Embarked == 'C']['Fare'].mean()
class1st_S = class1st[class1st.Embarked == 'S']['Fare'].mean()
class1st_Q = class1st[class1st.Embarked == 'Q']['Fare'].mean()

print("Boarded from Cherbourg:", class1st_C)
print("Boarded from Southampton:", class1st_S)
print("Boarded from Queenstown:", class1st_Q)

>> Boarded from Cherbourg: 104.71852941176469

     Boarded from Southampton: 70.36486220472443

     Boarded from Queenstown: 90.0

 

- 1등급 승객 중 Embarked가 S, Q인 승객과 요금이 비슷함으로 두 항구에서 승선한 승객들의 비율 계산

# df.shape[0] >> 행의 수 (전체 데이터 수)
print("Southampton:", str(round(class1st[class1st['Embarked'] == 'S'].shape[0] / class1st.shape[0]*100, 2)) + "%")
print("Queenstown:", str(round(class1st[class1st['Embarked'] == 'Q'].shape[0] / class1st.shape[0]*100, 2)) + "%")

>> Southampton: 58.8%

     Queenstown: 0.93%

 

- 둘 중 비율이 더 높은 S로 대체

data_df['Embarked'][61] = 'S'
data_df['Embarked'][829] = 'S'

 

2-1-3) Age (나이)

- 이름에 포함된 Mr, Mrs, Miss 등을 기준으로 이름 그룹 나눔

def get_name_group(name):
    # Braund, Mr. Owen Harris	
    start = name.find(', ')
    end = name.find('.')
    return name[start+1:end]

data_df['name_group'] = data_df.Name.apply(get_name_group)

- 이름 그룹별로 나이 평균을 계산

age_group_mean = dict(data_df.groupby(['name_group'])['Age'].mean())

age_group_mean

- 나이 정보가 없는 승객의 경우 해당 승객이 속한 이름 그룹의 나이 평균값으로 정보 대체

for index in data_df[data_df.Age.isnull()].index:
    name = data_df.loc[index, 'name_group']
    data_df.loc[index, 'Age'] = age_group_mean[name]

 

 

2-2. Feature 수치화, 범주화

2-2-1) Sex (성별)

# ('male', 'female') -> (0, 1)
data_df['Sex']=data_df['Sex'].replace(['male', 'female'], [0, 1])

 

2-2-2) Age (나이)

data_df['age_group'] = data_df['Age'].apply(lambda x: int(x/10))

2-2-3) Embarked (승선한 항)

def embarked_categorized(em):
    if em == 'S':
        return 0
    elif em == 'C':
        return 1
    else:
        return 2

data_df['emb_cat'] = data_df.Embarked.apply(embarked_categorized)

2-2-4) SibSp & Parch → companion (동행 여부)

- 티켓 번호가 같을 시 일행으로 보고 동일한 티켓의 수를 일행(companion) 수라고 가정

count_dict = dict(data_df['Ticket'].value_counts())
data_df['companion'] = data_df['Ticket'].apply(lambda  x : count_dict[x])

- Sibsp, Parch 둘 다 0이고 티켓 넘버가 같은 것도 없을 경우 일행이 없는 것으로 간주

- 일행이 없을 때 0, 있을 때는 1

data_df['companion'] = [0 if data_df['SibSp'][x] == 0 and data_df['Parch'][x] == 0 and count_dict[data_df['Ticket'][x]] == 1 else 1 for x in data_df.index ]

 

2-2-5) Fare (요금)

data_df['fare_cat'] = pd.qcut(data_df['Fare'], 5) # 범주화
data_df['fare_cat'] = data_df['fare_cat'].astype('category').cat.codes ]

- pandas.qcut() : 주어진 개수의 범주로 나누기

  pandas.cut() : 동일한 길이의 범주로 나누기

- astype('category') : 데이터 타입 'category'로 변경  예) 정수형은 .astype(‘int’)

- cat : 특수 메서드로 카테고리 속성, codes나 categorical 메서드 등에 쉽게 접근

 

 

2-3. Feature 선택 (X_data)

data_df.columns

>> Index(['PassengerId', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch', 'Ticket', 'Fare', 'Embarked', 'name_group', 'age_group', 'emb_cat', 'companion', 'fare_cat'], dtype='object')

 

X_data = data_df[['Pclass', 'Sex', 'age_group', 'fare_cat', 'emb_cat', 'companion']]

X_data

 

 

 

3. Train / Test Data Split

- test data 30% / train data 70% / random_state=0 (랜덤 패턴)

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_data, y_data, test_size=0.3, random_state=0)

 

 

 

4. Create Model & Train & Predict

(온갖 모델은 다 해볼 예정 ..! 🙄)

 

* 교차 검증 (CV, Cross Validation)

고정된 test set으로 모델의 성능을 검증하게 되면 test data에 과적합(overfitting)하게 됨

이를 해결하기 위해 train set을 train set과 validation set으로 분리하여 validation set을 사용하여 검증

총 데이터 개수가 적은 데이터셋에 대하여 정확도를 향상시킬 수 있음

 

* k-fold 교차검증

k 개의 fold를 만들어서 진행하는 교차 검증

(보통 회귀 모델에 사용되며 데이터가 독립적이고 동일한 분포를 가진 경우 사용)

1) 전체 데이터셋을 training set과 test set으로 나눈다

2) training set을 training + validation set 으로 사용하기 위해 k개의 fold로 나눈다.

3) 첫 번째 fold를 validation set으로 사용하고 나머지를 training set으로 사용

4) 모델을 학습시킨 뒤 validation set으로 평가

5) 다음 차례 fold로 3~4번 반복

6) 총 k개의 성능 결과가 나오며 이 k개의 평균을 해당 학습 모델의 성능이라 한다.

 

코드 예시)

from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score

# k-fold 설정
k_fold = KFold(n_splits=10, shuffle=True, random_state=0)

# 모델 생성
dt = DecisionTreeClassifier()

# 교차 검증 수행
score = cross_val_score(dt, iris.data, iris.target, cv=kfold, scoring="accuracy")

* sklearn의 kFold는 label을 고르게 분배하지 않아 shuffle=True 설정해주는 것이 좋음

- kFold(fold 수(k), 데이터 분할 전 섞을지 여부, 랜덤 패턴)

- cross_val_score(model, feature, target, cv설정값, scoring 평가 방법) : kfold 교차검증 수행하여 평균값으로 모델의 정확도(성능)를 알려줌

 

* StratifiedKFold 교차검증

더 고르게 분할됨

kfold = StratifiedKFold(n_splits=3)

 

* 모델의 성능 평가

주어진 test set에 대한 모델의 성능 평가

- accuracy_score() : sklearn 메서드

from sklearn.metrics import accuracy_score

accuracy_score(y_test, dt.predict(x_test))

- score() : 모델 객체 메서드 

model.score(x_test, y_test)

 

 

4-0. 라이브러리

import warnings 
warnings.filterwarnings(action='ignore')

# model
from sklearn import linear_model
from sklearn.neighbors import KNeighborsClassifier # kNN
from sklearn.tree import DecisionTreeClassifier # DC
from sklearn.ensemble import RandomForestClassifier # RF
from sklearn.naive_bayes import GaussianNB # NB
from sklearn.svm import SVC # SVC
from xgboost import XGBClassifier # XGB

from sklearn.metrics import accuracy_score # 모델 정확도 평가 (accuracy)

# k-fold
from sklearn.model_selection import KFold 
from sklearn.model_selection import cross_val_score

 

4-1. KNN

clf_kNN = KNeighborsClassifier(n_neighbors = 13)
scoring = 'accuracy'
score = cross_val_score(clf_kNN, X_data, y_data, cv=k_fold, n_jobs=1, scoring=scoring)

print(round(np.mean(score)*100,2))

>> 79.34

clf_kNN.fit(X_train, y_train)

>> KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=None, n_neighbors=13, p=2, weights='uniform')

predict_kNN = clf_kNN.predict(X_test)
accuracy_kNN = accuracy_score(y_test,predict_kNN)

>> 0.7873134328358209

 

4-2. Decision Tree

clf_DT = DecisionTreeClassifier()
scoring = 'accuracy'
score = cross_val_score(clf_DT, X_data, y_data, cv=k_fold, n_jobs=1, scoring=scoring)

>> 81.25

clf_DT.fit(X_train, y_train)

>> DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None, max_features=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort=False, random_state=None, splitter='best')

predict_DT = clf_DT.predict(X_test)
accuracy_DT = accuracy_score(y_test,predict_DT)

>> 0.8059701492537313

 

4-3. Random Forest

clf_RF = RandomForestClassifier(n_estimators=13)
scoring = 'accuracy'
score = cross_val_score(clf_RF, X_data, y_data, cv=k_fold, n_jobs=1, scoring=scoring)

>> 82.04

clf_RF.fit(X_train, y_train)

>> RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=None, max_features='auto', max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=13, n_jobs=None, oob_score=False, random_state=None, verbose=0, warm_start=False)

predict_RF = clf_RF.predict(X_test)
accuracy_RF = accuracy_score(y_test,predict_RF)

>> 0.8246268656716418

 

4-4. Naive Bayes

clf_NB = GaussianNB()
scoring = 'accuracy'
score = cross_val_score(clf_NB, X_data, y_data, cv=k_fold, n_jobs=1, scoring=scoring)

>> 75.98

clf_NB.fit(X_train, y_train)

>> GaussianNB(priors=None, var_smoothing=1e-09)

predict_NB = clf_NB.predict(X_test)
accuracy_NB = accuracy_score(y_test,predict_NB)

>> 0.7723880597014925

 

4-5. SVM

clf_SVC = SVC(probability=True)
scoring = 'accuracy'
score = cross_val_score(clf_SVC, X_data, y_data, cv=k_fold, n_jobs=1, scoring=scoring)

>> 81.37

clf_SVC.fit(X_train, y_train)

>> SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape='ovr', degree=3, gamma='auto_deprecated', kernel='rbf', max_iter=-1, probability=True, random_state=None, shrinking=True, tol=0.001, verbose=False)

predict_SVC = clf_SVC.predict(X_test)
accuracy_SVC = accuracy_score(y_test,predict_SVC)

>> 0.8059701492537313

 

4-6. Logistic Regression

clf_LR = linear_model.LogisticRegression()
scoring = 'accuracy'
score = cross_val_score(clf_LR, X_data, y_data, cv=k_fold, n_jobs=1, scoring=scoring)

>> 78.68

clf_LR.fit(X_train, y_train)

>> LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, max_iter=100, multi_class='warn', n_jobs=None, penalty='l2', random_state=None, solver='warn', tol=0.0001, verbose=0, warm_start=False)

predict_LR = clf_LR.predict(X_test)
accuracy_LR = accuracy_score(y_test,predict_LR)

>> 0.7947761194029851

 

4-7. XGBoost

clf_XGB = XGBClassifier(seed = 0, n_jobs = -1, learning_rate = 0.1, n_estimators = 100, max_depth = 3) 
scoring = 'accuracy'
score = cross_val_score(clf_XGB, X_data, y_data, cv=k_fold, n_jobs=1, scoring=scoring)

>> 81.37

clf_XGB.fit(X_train, y_train)

>> XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1, colsample_bytree=1, gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3, min_child_weight=1, missing=None, n_estimators=100, n_jobs=-1, nthread=None, objective='binary:logistic', random_state=0, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=0, silent=True, subsample=1)

predict_XGB = clf_XGB.predict(X_test)
accuracy_XGB = accuracy_score(y_test, predict_XGB)

>> 0.835820895522388

 

728x90

관련글 더보기

댓글 영역