인생마커
article thumbnail

 라이브러리 및 데이터 가져오기

 

import warnings warnings.filterwarnings("ignore") 
import pandas as pd 
import numpy as np 
import matplotlib.pyplot as plt from sklearn.preprocessing 
import LabelEncoder from sklearn 
import datasets, model_selection, linear_model, ensemble,neighbors from sklearn.metrics 
import mean_squared_error,accuracy_score from sklearn.model_selection 
import train_test_split from sklearn.svm import SVC from sklearn.ensemble 
import ExtraTreesClassifier from sklearn.ensemble 
import RandomForestClassifier from xgboost 
import plot_importance from xgboost 
import XGBClassifier

 

라이브러리는 위 기재된 것 보다 아래 더 있습니다.

 

타이타닉 데이터는 kaggle 에서 받을 수 있습니다.

 

 

 

Titanic - Machine Learning from Disaster

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

www.kaggle.com

 

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

 

 

원본 데이터를 받으면 위와 같은 모습을 하고 있습니다.

 

raw가 891개 있고 Age나 Cabin은 결측값이 많은 것을 확인할 수 있습니다.

 

data_df = data_df.drop(['PassengerId','Ticket','Cabin'],axis = 1)

 

예측 결과에 영향을 끼치지 않을 것 같은 PassengerId Ticket Cabin은 제외하였습니다.

 

y_data = data_df[['Survived']] x_data = data_df.copy() del x_data['Survived']

 

y_data에 생존유무를 넣어주고

 

x_data에 그 외 모든 데이터를 넣어줍니다.

 

dataframe.info() 함수로 데이터프레임의 정보를 확인할 수 있습니다.

 

결측치가 age열이 가장 많고 다음 승선항이 2개 있습니다.

 

Age 결측치를 어떻게 채워 넣을 것인가가 중요한 포인트가 될 것 같습니다.

 


 

데이터 전처리에 앞서 직관적으로 봤을 때 생존율과 크게 연관이 있을 것 같지 않은 열들도 많이 남겨두긴 했습니다.

 

특정 컬럼의 데이터와 생존율의 상관관계를 정확히 파악하기 위해선 시각화가 우선 진행되어야 합니다.

 

성별

 

타이타닉호의 생존율은 남성보다 여성이 압도적으로 높았습니다.

 

보통 재난 상황에서 근력이 좋은 남성이 더 높을 것이라는 고정관념이 있었는데 의외의 결과가 도출되었습니다.

 

 

승선항

 

승선항끼리도 생존율에 차이가 많이 나네요.

 

어떤 객실이었는지에 따라 승선항이 구분되는 것으로 생각됩니다.

 

직계가족

 

이건 같이 탑승한 부모/자식의 직계가족의 숫자별 생존율입니다.

 

사실 2 이후로는 데이터가 급감해서 결과에 영향을 주기엔 미비하다고 판단이 되어서
이 후 따로 전처리를 진행한 컬럼입니다.

 

 

배우자/형제,자매

 

직계가족이 아닌 배우자나 형제 자매의 숫자입니다.

 

이 데이터도 마찬가지로 2 이후에 표본이 급감합니다.

 

여기서 주목할만한 점은 parch와 sibsp의 0 과 1 이 근 20%로 일관되게 차이가 나는 점인데요.

 

동행인의 유무가 생존율 20%의 차이를 일관성 있게 보여주고 있습니다.

 

이를 근거로 나중에 parch와 sibsp를 합쳐서 동행인의 유무 column 으로 전처리를 진행했습니다.

 

 

n등실

 

n등실 별 생존율입니다.

 

타이타닉 구조를 확인해보면

 

 

등급별로 객실의 위치가 다른데 생존율에 차이는 여기서 기반한다고 판단됩니다.

 

 

나이

 

당연하게도 건장할수록 생존율이 높아지겠다고 생각했지만 10대부터 50대 까지는 의미있는 차이는 없었습니다.

 

다만, 60대부터는 생존율이 급감합니다.

 

40, 50대 일수록 등실이 좋을 확률이 높은 것도 있고 이런 요소들도 영향이 있기때문에 단편적으로 생각할 수는 없습니다.

 

 

요금

 

요금을 높게 지불한 사람일수록 생존율이 높게 나타납니다.

 

일관된 양의 상관관계를 보여주는데, 객실과도 연관이 있어 보입니다.

 

그리고 여기서 주목할만한 점은 Max값이 512라는 점입니다.

 

단위는 모르겠으나 상위 25%의 요금을 지불한 사람이 31만큼의 요금을 지불했는데 100%의 값이 512인 것은 문제가 있어 보이므로 oulier로 판단, outlier의 영향을 없애는 방향으로 전처리를 생각했습니다.

 

위 데이터들이 얼마나 accu에 좋은 영향을 줄 지는 확신이 서진 않지만, 적어도 생존율과 조금의 연관성은 있어 보입니다.


데이터전처리

 

먼저 parch열과 sibsp 열을 '동행인 유무' 열로 바꿔줍니다.

 

x_data['member'] = x_data['Parch'] + x_data['SibSp'] x_data = x_data.drop(['Parch','SibSp'],axis = 1) # 가족 유무 별 열추가 # Parch SibSp 열 삭제
for i in range(len(x_data)): if x_data['member'][i] > 1 : x_data['member'][i] = 1 #값이 1 이상이면 1로 변경

 

그리고 성별 열의 값을 숫자로 변경합니다.

 

x_data['Sex']=LabelEncoder().fit(['female','male']).transform(x_data['Sex'])

 

승선항의 결측치를 채우고 숫자로 바꿔줍니다.

 

승선항은 결측치가 2개 밖에 없으므로 최빈값인 "S"를 넣어줬습니다.

 

x_data['Embarked']=LabelEncoder().fit(['S','Q','C']).transform(x_data['Embarked']) x_data['Embarked'] = x_data['Embarked'].fillna('S')

 

 

Age 결측치 처리

x_data_test = [x_data] # combining train and test dataset for dataset in x_data_test: dataset['Title'] = dataset['Name'].str.extract(' ([A-Za-z]+)\.', expand=False) x_data['Title'].value_counts()

 

탑승자의 이름을 호칭 별로 구분해서 나열한 다음

 

해당 호칭의 나이 평균값을 구해서 결측치의 호칭에 맞는 평균값을 넣습니다.

이 방법은 타이타닉 생존율 예측에서 많이 사용되는 방법으로 결측치를 최대한 의미있는 data로 할당해 accu를 높일 수 있습니다.

 

name_mapping = {"Mr": 0, "Miss": 1, "Mrs": 2, "Master": 3, "Dr": 4, "Rev": 4, "Col": 4, "Major": 4, "Mlle": 4,"Countess": 4, "Ms": 4, "Lady": 4, "Jonkheer": 4, "Don": 4, "Dona" : 4, "Mme": 4,"Capt": 4,"Sir": 4 } for dataset in x_data_test : dataset['Title'] = dataset['Title'].map(name_mapping) x_data.head()

 

각 호칭에 맞는 번호를 주고 Title이라는 칼럼을 만들었습니다.

 

master 이후는 데이터가 적어서 4로 통일시킵니다.

 

 

그런 다음 결측치임과 동시에 Title이 n인 경우 n의 평균값을 할당하고 나이와 요금을 스케일링 합니다.

 

from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import RobustScaler ct = ColumnTransformer([ ('age', StandardScaler(), ['Age']), ('fare', RobustScaler(), ['Fare']) ], remainder='passthrough')

 

여기서 fare의 outlier를 생각해 RobustScaler라는 스케일러를 사용했습니다. (아래 포스팅 참조)

 

 

[Python] 어떤 스케일러를 쓸 것인가?

* 본 포스트는 개인연구/학습 기록 용도로 작성되고 있습니다. By MK on January 10, 2019 데이터를 모델링하기 전에는 반드시 스케일링 과정을 거쳐야 한다. 스케일링을 통해 다차원의 값들을 비교 분

mkjjo.github.io

 

완성된 데이터프레임

 


Hyper parameter, Model instance 생성

 

x_train, x_test, y_train, y_test = model_selection.train_test_split(x_data, y_data, test_size=0.3, random_state=0)

 

먼저 train,test셋으로 데이터를 분할합니다.

 

params = {'n_estimators': 1000, 'max_depth': 5, 'min_samples_split': 5, 'learning_rate': 0.01} #하이퍼 파라미터 svc_params = {'C': 1, 'gamma': 0.1, 'kernel': 'rbf'}

 

params는 gradient Boosting과 XGB에 사용했고 밑은 SupportVectorMachine의 하이퍼 파라미터입니다.

 

최적의 하이퍼 파라미터 값을 찾아주는 라이브러리도 있습니다.

 

 

 

sklearn.model_selection.GridSearchCV — scikit-learn 0.24.2 documentation

 

scikit-learn.org

 

모델 스태킹을 위한 라이브러리도 import 해줍니다.

 

from vecstack import StackingTransformer #Stacking (ExtraTreesClassifier, RandomForestClassifier, XGBClassifier)

 

 

이제 모델 객체를 만들 차례입니다.

 

 

다양한 모델을 사용해봤습니다.

 

데이터 전처리에 시간이 들고 모델링 자체는 별로 안걸립니다.

 

모델에 데이터를 트레이닝 하기 전에 교차검증으로 데이터를 점검해줍니다.

 

k-Fold cross validation 을 사용했습니다.

 

from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold kfold = KFold(n_splits = 5,shuffle = True,random_state=0) XGBModel_score = cross_val_score(XGBModel, x_train, y_train, cv=kfold) logisticModel_score = cross_val_score(logisticModel, x_train, y_train, cv=kfold) KnnModel_score = cross_val_score(KnnModel, x_train, y_train, cv=kfold) GBModel_score = cross_val_score(GBModel, x_train, y_train, cv =kfold) RanModel_score = cross_val_score(RanModel, x_train, y_train, cv = kfold) svc_score = cross_val_score(svc, x_train, y_train, cv = kfold) ETModel_score = cross_val_score(ETModel, x_train, y_train, cv = kfold) print('logisticModel 검증 점수 : ', logisticModel_score) print("logisticModel 검증 평균 점수 :",logisticModel_score.mean(),"\n") print('KnnModel 검증 점수 : ', KnnModel_score) print("KnnModel 검증 평균 점수 : ",KnnModel_score.mean(),"\n") print('GBModel 검증 점수 : ', GBModel_score) print("GBModel 검증 평균 점수 :",GBModel_score.mean(),"\n") print('XGBModel교차 검증 점수 : ', XGBModel_score) print("XGBModel교차 검증 평균 점수 :",XGBModel_score.mean(),"\n") print('RanModel 검증 점수 : ', RanModel_score) print("RanModel 검증 평균 점수 :",RanModel_score.mean(),"\n") print('svc_score 검증 점수 : ', svc_score) print("svc_score 검증 평균 점수 :",svc_score.mean(),"\n") print('ETModel_score 검증 점수 : ', ETModel_score) print("ETModel_score 검증 평균 점수 :",ETModel_score.mean(),"\n")

 

데이터가 트레이닝 데이터와 테스트 데이터로만 나뉘어져있기 때문에

 

테스트 결과 값을 좋게 만들려고 데이터를 타이트하게 조이다보면 Overfitting 날 수도 있습니다.

 

train 데이터를 갯수에 맞게 나누고 1개를 제외한 나머지를 학습시키고 1개로 결과를 확인하고 하는 과정을 반복하면

test 데이터 외의 값들로 결과를 확인할 수 있어서 모델의 안정성을 알 수 있습니다.

 

만약, test데이터의 결과값으로만 성능을 맞춰서 데이터처리를 한다면 오버피팅된 데이터셋이 교차검증에서 드러나게 될 것입니다.

 

 

 

교차 검증(cross validation)

이번 시간에는 머신러닝에서 평가에 필수적으로 사용되는 교차 검증(cross validation)에 대해서 알아보자....

blog.naver.com

 

 

교차검증 결과


Model training

 

logisticModel.fit(x_train, y_train) #로지스틱 train KnnModel.fit(x_train, y_train) #KNN GBModel.fit(x_train, y_train)#GB train XGBModel.fit(x_train, y_train)#XGB train RanModel.fit(x_train, y_train)#Random Forest train ETModel.fit(x_train, y_train)#Extra trees train svc.fit(x_train, y_train) #SVM train stack = stack.fit(x_train, y_train) #Stacking S_train = stack.transform(x_train) S_test = stack.transform(x_test) #Stacking StackModel = XGBClassifier(seed = 0, n_jobs = -1, learning_rate = 0.01, n_estimators = 1000, max_depth = 5) StackModel = StackModel.fit(S_train, y_train) y_pred = StackModel.predict(S_test) #Stacking

 

각각의 모델을 학습하고 테스트하다보니 원본에는 위 요소들이 cell 별로 나뉘어져있습니다.

 

 

이런식으로 모델객체를 list에 넣어서 loop 돌리면 코드가 간결해집니다.

 

이제 성능을 확인해 볼까요?

 

 

gradient boosting이 가장 높게 나왔습니다.

 

이 test set에서 85퍼센트는 꽤 높은 수치입니다.

 

 

ROC curve가 직각일 때가 이상적인 모습입니다.

 

 

 

Receiver operating characteristic - Wikipedia

Diagnostic plot Terminology and derivationsfrom a confusion matrix condition positive (P) the number of real positive cases in the data condition negative (N) the number of real negative cases in the data true positive (TP) eqv. with hit true negative (TN)

en.wikipedia.org


고찰

위 포스팅은 하이퍼파라미터 세팅에 다소 소극적이어서 각 모델을 지엽적으로 파보고 Hyper Parameter를 세팅하는 과정을 거친다면 더 나은 결과를 도출할 수 있을거라 기대됩니다.

 

 

 

Cottonwood-moa - Overview

느린 것(慢)을 두려워하지 말고(不怕), 멈춰 있는 것(站)을 두려워하라(只怕). - Cottonwood-moa

github.com

 

'인공지능' 카테고리의 다른 글

(ML/DL)Heart Attack 예측 모델  (0) 2021.07.26
네이버기반 맛집 분석  (2) 2021.07.14
profile

인생마커

@Cottonwood__

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!