본문으로 바로가기

타이타닉 생존자 예측이라는 주재를 가지고 신경망으로 분류를 했던 적이 있습니다. 당시엔 Keras를 사용했는데요. 이번에는 결정트리 Decision Tree 기법을 이용하려고 합니다. 그리고 사이킷런 Scikit Learn을 이용할 거구요^^ 먼저 데이터는 이전에 했던 [Keras] 타이타닉 생존자 예측에서 사용한 엑셀로된 데이터 입니다.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

raw_data = pd.read_excel('titanic.xls')
raw_data.info()

필요한 모듈과 데이터를 읽었습니다.

데이터가 1300개 정도로 보이지만, 중요 데이터인 age가 null이 있어서 살짝 손을 봐줘야 합니다.

tmp = []
for each in raw_data['sex']:
    if each == 'female':
        tmp.append(1)
    elif each == 'male':
        tmp.append(0)
    else:
        tmp.append(np.nan)

raw_data['sex'] = tmp

raw_data['survived'] = raw_data['survived'].astype('int')
raw_data['pclass'] = raw_data['pclass'].astype('float')
raw_data['sex'] = raw_data['sex'].astype('float')
raw_data['sibsp'] = raw_data['sibsp'].astype('float')
raw_data['parch'] = raw_data['parch'].astype('float')
raw_data['fare'] = raw_data['fare'].astype('float')

raw_data = raw_data[raw_data['age'].notnull()]
raw_data = raw_data[raw_data['sibsp'].notnull()]
raw_data = raw_data[raw_data['parch'].notnull()]
raw_data = raw_data[raw_data['fare'].notnull()]

raw_data.info()

이렇게 필요한 데이터들은 숫자로 변경하고, NaN이 아닌 데이터들만 가져오는 겁니다. 저기처럼 다 notnull() 처리할 필요 없이 사실 age 컬럼에만 해주면 되는데.. 어쩌다 저렇게 네 줄짜리가 되었는지.ㅠㅠ. 아마 코드 돌려막기와 확인하기 귀차니즘 때문이겠죠~

그리고 나면 저렇게 데이터가 만들어 집니다. 흠.. 그러고 보니... age의 데이터보다 하나가 더 적네요... 그렇다면 나머지 어딘가에도 null이 있었다는 거군요^^

데이터 head()를 보면 저렇습니다.~

train_pre = raw_data[['pclass','sex','age','sibsp','parch','fare']]
train_pre.head()

필요한 컬럼만 다시 가져옵니다. 변수 이름 작업법이라는 교육이 있으면 꼭 들어야겠습니다. ㅠㅠ.

이제... 이렇게 만들고 난 후~

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(train_pre, raw_data[['survived']], test_size=0.1, random_state=13)

흠 훈련용 데이터와 테스트용 데이터로 나눕니다. sklearn에서 제공하는 train_test_split을 사용했고, 세상에서 가장 완벽한 숫자인 13[각주:1]을 random_state로 결정했습니다.

X_train = X_train.reset_index()
X_train = X_train.drop(['index'], axis=1)

X_test = X_test.reset_index()
X_test = X_test.drop(['index'], axis=1)

y_train = y_train.reset_index()
y_train = y_train.drop(['index'], axis=1)

y_test = y_test.reset_index()
y_test = y_test.drop(['index'], axis=1)

그리고 가장 마음에 안 드는 코드인 인덱스를 좀 정리하는 곳입니다. 생각해보니... 데이터를 나누기 전에 저걸하고, 나누면 저렇게 네 번 복사한듯 한 무식함은 없을텐데.ㅠㅠ. 뭐 아무튼 그러합니다.

from sklearn.tree import DecisionTreeClassifier
tree_clf = DecisionTreeClassifier(max_depth=3, random_state=13)
tree_clf.fit(X_train, y_train)
print('Score: {}'.format(tree_clf.score(X_train, y_train)))

이제.. 드디어 결정트리 DecisionTreeClassifier 분류기를 사용합니다. depth는 3단계 정도로 보고... random_state는 가장 완벽하다는 그 숫자 13을 사용합니다.^^. 아무튼~ 훈련 성과를 볼까요?

80%가 넘네요... 그냥 만족할렵니다.^^. 

from sklearn.tree import export_graphviz

export_graphviz(
        tree_clf,
        out_file="titanic.dot",
        feature_names=['pclass', 'sex', 'age', 'sibsp', 'parch', 'fare'],
        class_names=['Unsurvived','Survived'],
        rounded=True,
        filled=True
    )

import graphviz
with open("titanic.dot") as f:
    dot_graph = f.read()
dot = graphviz.Source(dot_graph)
dot.format = 'png'
dot.render(filename='titanic_tree', directory='images/decision_trees', cleanup=True)
dot

이제 sklearn에서 Decision Tree를 사용할때의 가장 큰 장점인... 트리 구조를 보겠습니다.

와우~ 제일 상층부에서... 성별이 여성이면 오른쪽으로 ... 선실 등급이 1 혹은 2등급이면 그 밑으로 두개가 있지만, 뭐 둘다 살아남는군요... ㅎㅎ^^ 여하튼... 결정트리와 같은 알고리즘의 장점은 역시 저렇게 결정되는 과정[각주:2]을 쉽게 눈으로 확인할 수 있다는 거죠.

from sklearn.metrics import accuracy_score

y_pred = tree_clf.predict(X_test)
print("Test Accuracy is ", accuracy_score(y_test, y_pred)*100)

이제 테스트 데이터 셋에 적용해볼까요?

84.76%군요... max_depth를 높이면 과적합 위험성이 있죠.. 이 정도 선에서 마무리하는 것고 좋겠습니다. 사실.. recall이나 precision도 확인해야겠지만... 오늘은 여기까지^^

# pclass, sex, age, sibsp, parch, fare
dicaprio = [3., 0., 19., 0., 0., 5.]
winslet = [1., 1., 17., 1., 2., 100.]

def isSurvived(name, person):
    isSurvive = 'not survived' if tree_clf.predict([person])[0] == 0 else 'survived'
    print(name, ' is ', isSurvive, 
          ' --> ', max(tree_clf.predict_proba([person])[0]))
    
isSurvived('Dicaprio', dicaprio)
isSurvived('Winslet', winslet)

아... 디카프리오나 윈슬릿의 데이터를 넣어봐야죠~ 

흠... 디카프리오 형님 생존하지 못할 확율이 87.5%, 윈슬릿의 생존확률이 97.58%가 나오는군요... 뭐 아무튼.. Toy 프로젝트니까요...^^

  1. 양웬리의 13함대 : https://namu.wiki/w/%EC%96%91%20%EC%9B%AC%EB%A6%AC%20%ED%95%A8%EB%8C%80 [본문으로]
  2. 화이트박스모델이라고 한다. 반대로 예측되는 과정이나 그 결과를 설명할 수 없는 신경망과 같은 알고리즘을 블랙박스모델이라고 한다. [본문으로]

댓글을 달아 주세요

  1. BlogIcon 공수래공수거 2018.07.02 09:20 신고

    결정트리라는 용어는 들어 본것 같습니다
    7월 가분좋은 시작하시기 바랍니다

  2. BlogIcon 휴식같은 친구 2018.07.02 12:02 신고

    어려워보이네요..ㅎㅎ
    잘 보고 갑니다. 즐겁게 한 주 시작하세요~^^

  3. BlogIcon 북두협객 2018.07.02 12:55 신고

    프로그래밍 세계는 정말이지 대단하네요~

  4. BlogIcon 스티마 2018.07.02 21:10 신고

    지난번에 보여주셨던 분석과정을 눈으로 볼 수 있게 하는 건가 봅니다!

  5. BlogIcon 핑구야 날자 2018.07.03 06:49 신고

    결정 트리를 응용하면 말하는 것들을 알 수 있을 수도 있겠네요

  6. BlogIcon Deborah 2018.07.03 11:32 신고

    아주 전문성이 뛰어난 글 잘 봤네요. 이렇게 프로그래밍이로 할 수있는 영역이 무한대인것 같군요.
    활용도가 높은 글이네요

  7. BlogIcon 멜로요우 2018.07.03 12:57 신고

    사실 봐도 잘모르겠지만 전공하는분들에게는 대단 하신거같아요~~ ㅋㅋ

  8. BlogIcon kangdante 2018.07.03 13:20 신고

    흥미로워 보이기도 합니다
    잘 보고 갑니다.. ^^

  9. BlogIcon Bliss :) 2018.07.04 07:52 신고

    오아~ 결정트리로도 생존 예측이 가능하군요!!! 저번에 타이타닉 글도 엄청 흥미로웠어요! 실제 사건을 새로운 각도로 바라보니 신선하더라구요. 오늘도 감탄하고 갑니다. 활기찬 하루 보내시길요^^