멀리 보는 연습

머신러닝_버섯 데이터 분류 실습(Decision Tree) 본문

빅데이터 분석 서비스/머신러닝

머신러닝_버섯 데이터 분류 실습(Decision Tree)

푸실리 2021. 9. 4. 23:20

4번째 실습 버섯 데이터 분류. Decision Tree 알고리즘을 활용하여 진행하였고, 처음 접하는 알고리즘이다보니 트리의 최대 깊이, 노드의 최대 개수, 가지치기, 데이터 포인트 최소 개수 등 헷갈리는 개념이 많았다. 그래도 자주 접하다 보면 익숙해질 것이므로 크게 상심하지 말자! 

 

Decision Tree(결정트리)란? 

  • Tree를 만들기 위해 예/아니오 질문을 반복하며 학습
  • 다양한 앙상블 모델이 존재
  • 분류와 회귀에 모두 사용가능
  • 타깃 값이 한개인 리프 노드를 순수노드라고 한다.
  • 모든 노드가 순수 노드가 될때 까지 학습하면 복잡해지고 과대적합이 된다.
  • 새로운 데이터 포인트가 들어오면 해당하는 노드를 찾아 분류라면 더 많은 클래스를 선택하고, 회귀라면 평균을 구한다.

Decision Tree(결정트리) 과대적합 제어

  • 사전 가지치기(pre-pruning) : 노드 생성을 미리 중단하는 방법
  • 사후 가지치기(pruning) : 트리를 만든후에 크기가 작은 노드를 삭제하는 방법
  • 트리의 최대깉이나 리프 노드의 최대 개수를 제어
  • 노드가 분할 하기 위한 데이터 포인트의 최소 개수를 지정

주요 매개변수(Hyperparameter)

  • DecisionTreeClassifier(max_depth, max_leaf_nodes, min_sample_leaf)
  • 트리의 최대 깊이 : max_depth (깊이가 깊을수록 모델의 복잡도가 올라간다.)
  • 리프 노드의 최대 개수 : max_leaf_nodes
  • 리프 노드를 구성하는 최소 샘플의 개수 : min_sample_leaf

장점

  • 만들어진 모델을 쉽게 시각화할 수 있어 이해하기 쉽다.
  • 각 특성이 개별 처리되기 때문에 데이터 스케일에 영향을 받지 않아 특성의 정규화나 표준화가 필요없다.
  • 트리 구성시 각 특성의 중요도를 계산하기 때문에 특성 선택에 활용될 수 있다.

단점

  • 훈련데이터 범위 밖의 포인트는 예측할 수 없다. (ex 시계열 데이터)
  • 가지치기를 사용함에도 불구하고 과대적합되는 경향이 있어 일반화 성능이 좋지 않다.

 

1. 목표

- 버섯의 특징을 활용하여 독/식용 버섯을 분류
- Decision tree 시각화 & 과대적합 제어
- 특성선택(Feature selection) 

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier  # DecisionTree 활용하기
pd.set_option('display.max_rows', 1000)
pd.set_option('display.max_columns', 1000)

 

2. 데이터 가져오기

mushroom.csv
0.36MB

data = pd.read_csv('data/mushroom.csv', encoding='utf-8')
data.head(10)

data.shape

(8124, 23)

data.info()

data.isnull().sum()

이 버섯 데이터는 말이 안되는 데이터다. 어떻게 결측치가 0이야? 말이 안돼.. 

 

3. 전처리

# 문제와 답 나누기
X=data.iloc[ : , 1:]
y=data.iloc[ : , 0]
data.describe()  # unique는 범주  freq : 최빈값

 

원 핫 인코딩  
- 컴퓨터는 숫자로 계산, 하지만 자료가 범주형(이산형) 특성이기 때문에 인코딩 필요
- 인코딩에는 Label 인코딩과 One-hot 인코딩 방식이 있음
- Label은 정답 데이터를 숫자로 변환, One-hot은 0 or 1로만 인코딩(컬럼 갯수 증가)

 

라벨 인코딩의 단점
- 컴퓨터가 서열이나 순위 패턴으로 오역 학습할 가능성이 있음.

 

원핫 인코딩의 단점
- 컬럼이 늘어나서 과대적합이 일어날 가능성이 있다.

 

# 원 핫 인코딩
X_one_hot = pd.get_dummies(X)

라벨 인코딩(컬럼 하나하나 해줘야함)

X['habitat'].unique()

array(['u', 'g', 'm', 'd', 'p', 'w', 'l'], dtype=object)

 

habitat_dic= {
    'u' : 1,
    'g' : 2,
    'm' : 3,
    'd' : 4,
    'p' : 5,
    'w' : 6,
    'l' : 7
}

# habitat_dic 값과 실제 값을 매칭
X['habitat'].map(habitat_dic)

y_dic = {
    'p' : 0,
    'e' : 1  
}

y_label= y.map(y_dic)
X_train, X_test, y_train, y_test = train_test_split(X_one_hot, y_label, test_size =0.3, random_state=1)
# 변수 선언                                                             # test 비율     # 랜덤 숫자는 아무거나

 

모델링

tree_model = DecisionTreeClassifier()  # 결정트리 객체
tree_model.fit(X_train, y_train) # 훈련데이터 학습

DecisionTreeClassifier()

 

# 스코어 나타내기
tree_model.score(X_test,y_test)

1.0

 

삐옹삐옹 과대적합 발생!

 

 

시각화 패키지 설치

!pip install graphviz
from sklearn.tree import export_graphviz
export_graphviz(tree_model, out_file="tree.dot",
                class_names=["독성", "식용"],
                feature_names= X_one_hot.columns,
                impurity = False,
                filled=True)
import graphviz
with open("tree.dot", encoding = "UTF8") as f:
    dot_graph = f.read()
    display(graphviz.Source(dot_graph))

위 이미지가 보이지 않는다면, 아래 링크에 graphviz 설치 순서를 따라서 graphviz를 설치해야 합니다.

 

Decision Tree2 실습( Mushroom 데이터)

0. 필요한 기능 import 1. 데이터 불러오기 2. 전체 행/여려 수 확인 3. 결측치 확인 - 결측치는 없다. 4. 문제/답 나누기 - loc 사용하여 컬럼명으로 문제와 답 나눠줌 - 전체 23개 컬럼 중 22개가 문제로

winter-time.tistory.com

 

 

 

과대적합제어

# max_depth, max_leaf_nodes, min_samples_leaf(리프노드가 되기 위한 최소 샘플 데이터 수)
# max_features : 최적의 분할을 위해 고려할 최대 특성 개수
# min_samples_split : 노드를 분할하기 위한 최소한의 샘플 데이터 수 ex) default=2
# 작게 설정할수록 분할 노드가 많아져 과대적합 가능성 증가
tree_model2 = DecisionTreeClassifier(max_depth = 3,
                                     max_leaf_nodes=4,
                                     min_samples_leaf=4)
tree_model2.fit(X_train, y_train)

DecisionTreeClassifier(max_depth=3, max_leaf_nodes=4, min_samples_leaf=4)

 

export_graphviz(tree_model2, out_file="tree2.dot",
                class_names=["독성", "식용"],
                feature_names= X_one_hot.columns,
                impurity = False,
                filled=True)
with open("tree2.dot", encoding = "UTF8") as f:
    dot_graph = f.read()
    display(graphviz.Source(dot_graph))

 

 

 

특성 선택

- tree 모델의 특성중요도

 

fe = tree_model.feature_importances_ # 특성 중요도 수치 
fe

뭔지는 몰라도 보기 어려우니까 DataFrame 형태로 바꿔주자!

X_one_hot.columns

X_one_hot.columns를 인덱스로 하는 데이터프레임을 만들자

im_df = pd.DataFrame(fe, index=X_one_hot.columns)

0.00000이 나온 컬럼은 트리 구조에서 크게 쓸모가 없다. 그래서 날려도 상관 없다고 한다.

 

 

 실습을 하면 따라가기 바쁜데 이렇게 복습을 하니까 굉장히 유익한 것 같다. 따라가기 바쁜 이유 중에 하나는 온라인 수업으로 진행하기 때문이다. 현재 하프하프 등원(수강생의 50%만 등원)을 진행하고 있다. 그래서 줌으로 수업을 듣는 날이 많다보니, 놓치면 답이 없다. 하하 그래도 처음보다는 많이 능숙해져서 수월하게 따라가긴 하지만.. 오프라인 수업의 장점은 아무래도 선생님과 같은 공간에 있다보니 소통이 원활하다는 점이고, 온라인 수업의 장점은 집에 듀얼 모니터가 있어서 실습하기 편하다는 점..? 온라인 수업을 계속 하다보니 또 거기에 적응해서 온라인이 집중이 더 잘되는 것 같기도 하고...

 

Comments