머신러닝 5일차

ParkJinYoung·2022년 10월 24일
0

Decision Tree (의사결정나무)


  • 모델 성능 평가 / 교차검증을 통해 일반화&신뢰도에 대한 확인,파악 (성능향상X)
# Label Encoding : 레이블을 숫자로 mapping 
# 특성이 많을 때는 사용하면 안된다.
# 레이블 인코딩 = 값의 크고 작음에 의미가 있을때 사용한다.
# 우선순위나 랭킹같은 데이터를 인코딩 해줄때 사용한다.(계급)

# 실습(서식지 데이터) => 예시
X['habitat'].unique()

# 딕셔너리를 활용해서 우선순위를 주자
hb_dict = {'u':0,'g':5,'m':1,'d':2,'p':4,'w':3,'l':6}

# 특정 대상에게 딕셔너리에 넣어준 숫자를 맵핑
# map : 값을 맵핑(같은 키값을 가진 데이터에 밸류를 매칭, 변경)

X['habitat'].map(hb_dict)
# 각 알파벳이 대응되는 숫자로 바뀐다. (컬럼이 증가하지 않음)

train,test 분리
# 자동으로 분리해주는 도구
X_train,X_test,y_train,y_test=tts(X_one_hot,y, test_size=0.3,random_state=7)
# ✔✔ 수치값 확인 ✔✔

print('훈련용 문제 : ',X_train.shape)
print('훈련용 답 : ',y_train.shape)
print('테스트 문제 : ',X_test.shape)
print('테스트 답 : ',y_test.shape)

# 모델 객체 생성
tree_model=DecisionTreeClassifier()
# Default값으로 끝까지 진행된다 => 과대적합의 위험이 존재함

# 모델 학습
tree_model.fit(X_train,y_train)

# 모델 정확도 평가
# 예측 생략 => 모델 자체에서 제공해주는 함수를 사용
tree_model.score(X_test,y_test)
# 정확도 1이 나온다면 과대적합을 의심해봐야한다.
# 새로운 데이터에 대한 결과 정확도가 낮아질 가능성이있다. 

하이퍼파라미터 조정하여 과대적합을 제어하자
# 조정한 객체 생성
tree_model2=DecisionTreeClassifier(max_depth=3)
# 모델학습
tree_model2.fit(X_train,y_train)
# 모델 정확도 확인
tree_model2.score(X_test,y_test)

# 우리가 보유한 데이터는 한정적이다 => 데이터가 많을수록 과적합제어가 쉬워진다.
# 데이터 수집은 너무 오랜시간이 필요해서 한정된 데이터에서 여러번 검증
# 교차 검증(cross validation)

교차검증 => 모델의 일반화를 확인하는 과정
이 모델의 일반화 성능이 어느정도인지 파악할때 사용한다
개념 : 일반성능 측정 방법중 모델데이터에 대해 모델이 얼마나 잘 맞히는지 평가,이는 한번에 하는 것보다 신뢰도가 높아진다.
방법 : (훈련 데이터내에서) 훈련세트와 테스트세트로 여러번 나누어서 평가
모델을 정의하고 학습전에 정확도가 얼마인지 확인가능

# 교차검증도구
from sklearn.model_selection import cross_val_score
# (적용할 모델명, 훈련문제, 훈련답, cv = 교차검증 횟수)
result = cross_val_score(tree_model,X_train,y_train,cv=5)
result
# 우리가 만든 tree_model 성능확인
# 과적합 확률이 적음을 알 수 있다.

# 교차검증의 정확도 평균
result.mean()

tree 모델 내부 시각화
외부라이브러리인 graphviz (트리 내부를 시각화 하기위한 라이브러리)
따로 설치해야함

# 외부 라이브러리 설치
!pip install graphviz
# tree모델 시각화(과적합제어 안한 모델)
from sklearn.tree import export_graphviz as eg

#(학습한 모델명, out_file=우리가만들파일이름.dot)
#dot 파일은 그래프를 불러오기 위한 텍스트 형식의 파일이다.
eg(tree_model, out_file='data/tree.dot' # 경로 / 파일이름.확장자
  , class_names=['독','식용'] # 정답데이터의 이름
  , feature_names=X_one_hot.columns # 원핫인코딩된 문제데이터들의 특성
  , impurity = True # 지니 불순도값 출력 여부
  , filled = True # 각 노드들이 구분될 수 있도록 색을 칠해주는 명령
  )

#학습되어있는 트리의 내부 모습을 보기위함
#학습된 모델의 정보가 들어있는 dot 파일을 생성한것!
# https://graphviz.org/download/ => graphviz-5.0.0 (64bit)

import os
os.environ['PATH']+=os.pathsep+'C:\\Program Files\\Graphviz\\bin\\'
# dot 파일을 가져와서 실제로 그래프로 표현
import graphviz

# tree.dot 파일을 불러오면서 한글로 인코딩 해주는 코드
with open('data/tree.dot',encoding='UTF-8') as f :
    dot_graph = f.read() # 변수에 파일을 담아줌

display(graphviz.Source(dot_graph)) # 그래프를 출력시켜주는 코드
# 그래프 해석
# 기준 <= 0.5 : 원핫 인코딩 이후에 0 또는 1을 구분해주는 조건값 (odor_n 판별 조건이 됐구나)
# gini : 지니 불순도 0,1에 가까울수록 불순도가 낮아진다 (0.5일때 가장 높다)
# samples : 데이터 개수
# value : 클래스별 개수
# class : 예측한 정답 값 - 분류했을때 투표형식으로 더 많은 정답값을 가진 label을 말해준다

# 과대적합을 제어한 tree_model2 시각화해보기
eg(tree_model2, out_file='data/tree2.dot' # 경로 / 파일이름.확장자
  , class_names=['독','식용'] # 정답데이터의 이름
  , feature_names=X_one_hot.columns # 원핫인코딩된 문제데이터들의 특성
  , impurity = True # 지니 불순도값 출력 여부
  , filled = True # 각 노드들이 구분될 수 있도록 색을 칠해주는 명령
  )
with open('data/tree2.dot',encoding='UTF-8') as f :
    dot_graph = f.read() # 변수에 파일을 담아줌

display(graphviz.Source(dot_graph))

모델 복잡도 곡선 그려보기
# 정확도를 담을 수 있는 리스트생성
train_list = []
test_list = []

for k in range(1,11,1):
    # 모델 생성 및 하이퍼 파라미터 조절
    tree_model3=DecisionTreeClassifier(max_depth=k)
    
    # 모델 학습
    tree_model3.fit(X_train, y_train)
    
    # 학습데이터의 정확도
    train_score = tree_model3.score(X_train,y_train)
    
    train_list.append(train_score)
    
    # 테스트 데이터의 정확도
    test_score = tree_model3.score(X_test,y_test)
    
    test_list.append(test_score)
    
plt.plot(train_list,label='train')
plt.plot(test_list,label='test')

plt.legend()
plt.show()

# max_depth가 깊어질수록 정확도가 올라가는 것을 확인
# 5 이상으로 깊어지는건 별 의미가 없다
# 더이상 정확도가 올라가지 않을 정도까지만 깊이를 조정

특성선택
지도학습 모델에서 데이터의 각 특성들의 중요를 확인해볼수가있다.
정답에 얼만큼 영향을 미치는 특성인지 수치로 확인가능하다.
각 특성들은 0~1 의 중요도를 가진다. ( 1 에 가까울수록 중요)
총 특성의 합은 1이다.
tree 모델의 특성 중요도가 높은 값부터 탑노드에 배치하여 분류해나간다.
의미없는 특성들은 0에 가깝다.

# tree모델의 특성중요도 확인
fi = tree_model.feature_importances_

pd.set_option('display.max_rows',None) # None(전체출력) : 내가 보고싶은 개수
# 이 순서는 columns 의 순서(총 117개)
# 특성중요도를 DataFrame화 해주기
fi_df=pd.DataFrame(fi, index=X_one_hot.columns, columns=['특성중요도'])

#정렬
fi_df.sort_values(by = '특성중요도',ascending=False) # 내림차순으로 정렬

# 특성이 117개나 있었는데 영향을 미치는 특성은 상위 5개 정도이다.
# 위에 있는 중요도가 높은 특성만 활용해도 된다.

## 정리
- tree 모델 내부 시각화 표를 보면 가장 중요도가 높은 특성인 odor_n 컬럼을 가장 먼저 고려해서 분류를 진행한다
- 중요도가 가장 높은 컬럼을 먼저 고려해야 효율적으로 분류가 가능하다
- 현재 데이터에서 odor_n 컬럼이 약 60% 이상의 중료도를 혼자 차지하고 있었기 때문에 모델이 학습하는데 용이했다. 그래서 100% 의 정확도가 쉽게 나온것이다.

타이타닉문제

## 머신러닝의 전체 과정
- 문제정의 (목표설정) : 주제선정
- 데이터 수집 (kaggle 데이터 불러오기)
- 데이터 전처리
- EDA (탐색적 데이터 분석)
- 모델 선택 및 하이퍼 파라미터 설정
- 모델 학습
- 모델 예측 및 평가

## 목표
- 타이타닉 데이터를 학습시켜 생존/사망자 예측하기
- 머신러닝의 전체적인 과정 이해
- kaggle 경진대회에서 높은 순위를 차지해본다

#도구 불러오기
import numpy as np
import seaborn as sns # 시각화 라이브러리
import matplotlib.pyplot as plt
import pandas as pd
#머신러닝 패키지
from sklearn.neighbors import KNeighborsClassifier as kn #KNN 분류모델
from sklearn.metrics import accuracy_score as acs 
from sklearn.tree import DecisionTreeClassifier 
from sklearn.model_selection import train_test_split as tts
from sklearn.model_selection import cross_val_score
from sklearn.tree import export_graphviz as eg
import graphviz
import os
os.environ['PATH']+=os.pathsep+'C:\\Program Files\\Graphviz\\bin\\'

# train, test 데이터 읽어오기('PassengerId' 컬럼 => 인덱스)
titanic_train=pd.read_csv("data/train.csv",index_col='PassengerId',encoding="utf-8")
titanic_test=pd.read_csv("data/test.csv",index_col='PassengerId',encoding="utf-8")

## 데이터 특성 확인
- PassengerId : 탑승자 번호 / Pclass : 티켓의 등급 / Name : 이름 / Sex : 성별 / Age : 나이
- Slisp : 형제, 자매 배우자 수 / Parch : 부모 자식의 수 / Ticket : 티켓번호 / Fare : 요금
- Cabin : 객실번호 / Embarked : 탑승한 항구 이름 3(C,Q,S) / Survived : 0(죽다), 1(살다)

# 데이터 크기 확인 (shape)
print('훈련용 데이터 : ', titanic_train.shape)
print('테스트용 데이터 : ', titanic_test.shape)
# train : 특성 10개 + 정답데이터 1개
# test : 특성 10개 + 정답데이터 X0

# 데이터 확인 : 이상치 결측치
titanic_train.info()
titanic_test.info()

profile
꾸준히

0개의 댓글