Decision Tree : 결정트리, 의사결정나무, 결정나무
- KNN : 주변에 있는 이웃들을 검색하는 알고리즘
- 질문을 순차적으로 나열해서 데이터를 구분하는 알고리즘
- 가장 먼저 던지는 질문 : Root Node
=> 가장 중요한 질문 : 가지고 있는 데이터를 가장 잘 구분할 수 있는 질문
- 가장 마지막에 던지는 질문 : Leaf Node
=> 더 이상 질문이 나열되지 않는 상태, 상대적으로 덜 중요한 질문
- 각 질문의 중요도를 구분하기 위해 사용하는 지표 : 지니불순도, 엔트로피
==> 각 데이터가 얼마나 섞여있는지를 판단
==> 많이 섞여있을수록 : 불순도가 높음
==> 조금 섞여있을수록 : 불순도가 낮음
- 불순도가 가장 낮은 것이 가장 중요한 질문 : Decision Tree 알고리즘
### 문제정의
- 버섯의 특징(22개)를 활용해서 독성/식용 버섯을 분류
### 데이터 수집
import pandas as pd
data = pd.read_csv('./data/mushroom.csv')
data.head()
# 안보이는 열 숨기기 : pd.set_option('display.max_columns', None)
# 안보이는 행 숨기기 : pd.set_option('display.max_rows', None)
# 데이터의 크기 확인
data.shape
### 데이터 전처리
1. 결측치
2. 이상치
# 결측치
data.info()
# 결측치가 없음 => 가지고 있는 데이터를 그냥 활용
# 이상치
# describe() : 숫자인 컬럼에서만 확인 가능
data.describe()
# 문자열로 이루어진 컬럼에서 describe()로 확인하면
# 수치적인 계산은 할 수 없고, 값이 몇 개(unique)로 구성되어 있는지 빈도(freq)정도만 확인할 수 있음.
# 어떤 데이터가 가장 많은지 정도(top)
### 탐색적 데이터 분석
- 일단 생략 : 데이터가 수치형이 아닌 문자열 데이터로 탐색적 데이터 분석을 진행하기가 어려움
### 모델 생성 및 하이퍼 파라미터 튜닝
#### 모델 불러오기
# Decision Tree 모델 불러오기
from sklearn.tree import DecisionTreeClassifier
tree_model = DecisionTreeClassifier()
#### 데이터 나누기
##### 문제와 정답 데이터로 나누기
X = data.iloc[:, 1:]
display(X)
y = data.iloc[:, 0]
display(y)
##### 문제를 숫자로 만들기
X1 = X.copy() # 데이터를 복사, X가 가지고 있는 주소 != X1이 가지고 있는 주소
# X의 값이 바뀌어도 X1에는 반영되지 않는다.
# 데이터를 가지고 와서 한 번 바꿔볼 때 사용
# copy()를 사용하는 이유 : 기존에 가지고 있는 데이터의 원본이 훼손되는 것을 방지
# 테스트 용도로 사용해 보고자 할 때 사용
# X1 = X 대입 => 같은 주소로 같은 데이터, X의 값이 바뀌면 X1의 값도 바뀌게 된다.
X1
###### Label 인코딩
- 하나의 값에 하나의 숫자를 대입
- 많이 사용되는 방법은 아님
- 왜? 값을 변경함에 있어서 사용자의 개입이 들어감
- 원래 문자가 가지고 있던 의미는 사라지고 사용자가 임의대로 값을 변경
- => 따라서 대게 사용 X
X1['cap-shape'].unique()
# cap-shape은 총 6개의 값을 가지고 있는데, 라벨인코딩을 수행하게 되면,
# 순서대로 1, 2, 3, 4, 5, 6으로 숫자값으로 변경
# 'x' : 1, 'b' : 2, 's' : 3, 'f' : 4, 'k' : 5, 'c' : 6
# 인덱스 개념으로 코드에 반영하려면 : 0 ~ 5까지의 숫자값
# map 함수 : 라벨인코딩을 진행해주는 함수
# map()를 사용하기 위해서는 딕셔너리 형태로 값을 저장해줘야 함
trans = {'x' : 0, 'b' : 1, 's' : 2, 'f' : 3, 'k' : 4, 'c' : 5}
# key값을 value 값으로 변경
X1['cap-shape'] = X1['cap-shape'].map(trans)
# map()함수를 쓸 때 주의할 점 : 가지고 있는 대상을 전부 다 바꿔줘야 함.
X1['cap-shape'].value_counts()
# 가지고 있던 문자가 숫자로 바뀌었고 숫자들의 빈도수를 확인
###### One hot 인코딩
- 문자를 숫자로 변경하는 방법
- 컬럼이 가지고 있는 데이터만큼 컬럼을 생성 => 데이터가 늘어난 효과를 얻음
- 0과 1로 데이터를 표시
- 일반적으로 더 많이 사용함
Label 인코딩 vs One hot 인코딩
- Label 인코딩 : 데이터의 의미가 사라짐
- One hot 인코딩 :
- 장점 1. 기존에 가지고 있는 데이터의 의미 유지
- 장점 2. 데이터가 늘어나는 효과(가짓수가 많아짐)
![image.png](attachment:image.png)
# pd.get_dummies(대상) : One hot 인코딩을 진행해주는 함수
X2 = X.copy()
X_onehot = pd.get_dummies(X2)
X_onehot.head()
##### 훈련(train)과 평가(test)데이터 나누기
# 수치형 데이터가 아니기 때문에 데이터형식을 바꿔주는 작업이 필요!
# 문제 데이터 : X_onehot
# 정답 데이터 : y
# 문제와 정답데이터를 train과 test로 분리해주는 함수 : train_test_split
# 문제와 정답데이터를 훈련용과 평가용 데이터로 나누기
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_onehot, y, test_size=0.3)
X_train.shape, X_test.shape, y_train.shape, y_test.shape
### 학습
tree_model.fit(X_train, y_train)
### 평가
tree_model.score(X_train, y_train)
# 1.0 이라는 값은 보통 '과대적합' => 사전 가지치기를 해주지 않았기 때문에
tree_model.score(X_test, y_test)
# train도 test도 1.0이다.
# 1. 뭔가 잘못됐다(99%)
# 2. 학습이 잘 됐다(1%) => 데이터가 구분하기 좋은 데이터로만 구성이 되어있어서 학습이 잘됐다.
알고리즘 시각화
https://graphviz.org/download/
system Path는 아래로 설정해주기
설치완료되었는지 확인해보기
시스템환경변수 들어가기
아래 화면에 ~ bin이 존재한다면 설치완료된 상황
### 알고리즘 시각화
# graphviz가 설치가 다 됐다
!pip install graphviz
# 1. 알고리즘 표현하기
# tree가 가지고 있는 알고리즘을 밖으로 내보낸다는 의미 => export
from sklearn.tree import export_graphviz
export_graphviz(tree_model, # 알고리즘을 내보낼 모델
out_file='tree.dot', # tree.dot 형태로 알고리즘을 내보내기
class_names=['p', 'e'], # 정답을 어떻게 표시할 것인지 p = 독성, 0 = 식용
feature_names=X_onehot.columns, # 원래는 특성의 번호를 명시
# 특성의 이름을 지정해주면서 지정한 특성의 이름을 표시
impurity=True, # 지니불순도 / 엔트로피의 값을 표시할 것인지 설정
filled=True) # 클래스(정답)별로 색의 변화를 줄 것인지 설정
# 연한색상 - 분류가 잘 안된 것이지만 같은 계열의 색상으로 표시
# 2. 환경변수 설정
# graphviz를 파이썬에서 사용하기 위해 폴더의 경로를 지정
import os
os.environ['PATH'] += os.pathsep+'C:/Program Files/Graphviz/bin'
# 3. 알고리즘 그리기
# 1단계에서 글로 표현된 알고리즘을 그림으로 표현
import graphviz
with open('tree.dot', encoding='UTF8') as f:
dot_graph = f.read()
display(graphviz.Source(dot_graph)) # dot_graph에 있는 내용을 그림으로 출력
# 특성, 불순도 => 앞으로 질문할 특성
# 샘플수, 정답값(p, e), 예측클래스 => 현재 데이터의 정보
# leaf 노드들을 확인해보면 더이상 질문할 특성이 없고 4개의 요소만 존재
# 4. 3단계에서 그린 알고리즘 그림을 파일형태(png, jpg...)로 저장
# 정상적으로 실행이 된다면 0이 출력
from subprocess import check_call
check_call(['dot', '-Tpng', 'tree.dot', '-o', 'tree.png'])
### 교차검증
- 훈련과 평가를 여러 번 진행하면서 검증의 효과를 얻기 위한 방법
- 전체 데이터가 축소되지 않기 때문에 적은 데이터에서 효과를 얻을 수 있음.
- 앞으로는 7.평가단계에서 교차검증을 수행.
- score 대신에 cross_val_score(tree_model, X_onehot, y, cv=5).mean()으로 확인
# 교차검증 라이브러리 불러오기
from sklearn.model_selection import cross_val_score
cross_val_score(tree_model, X_onehot, y, cv=5)
# cross_val_score(사용할 모델, 문제데이터, 정답데이터, 데이터분할 수(cv))
# 검증을 확인할 필요가 있음
cross_val_score(tree_model, X_onehot, y, cv=5).mean()
# 기존의 완벽한 1이 아닌 교차검증을 해보니 0.95 정도가 나왔다.
교차검증
1. 기존의 검증방법은 고정되어있는 훈련세트로 학습을 하고
고정되어있는 테스트 세트로 검증
2. 성능이 좋지않을 때 하이퍼 파라미터 튜닝을 하고 다시 학습 후 검증 단계를 반복
=> 모델의 성능을 향상시키기 위해서 1, 2의 과정에서 나타나는 문제
=> 검증하려고 남겨둔 테스트 세트에도 과대적합이 발생
훈련데이터 - 검증데이터 - 평가데이터
훈련 : 데이터를 학습
검증 : 모델이 잘 만들어졌는지를 확인
평가 : 모델이 고정되어있는 데이터에 맞게 학습이 된 건지를 판단하기 위해서
가장 마지막에 한 번만 사용
데이터 분할
전체데이터 : 학습(5), 검증(3), 평가(2) 비율로 사용
검증데이터 필요성
- 기존의 방식은 test가 여러 번 사용되기 때문에
모델의 입장에서는 test는 새로운 데이터가 아님
=> 테스트 세트에 과대적합
- 검증데이터 세트를 만들어서(기존의 테스트 역할)
검증데이터 세트에서 좋은 score가 나왔다면
마지막으로 test에서 확인
=> 모델이 잘 만들어졌는지를 제대로 확인하는 과정
단점) 데이터가 적을 경우 학습이 제대로 안됨(과소적합)
교차검증 : 전체 데이터를 train과 test로만 나눔
- 학습할 때마다 다른 데이터를 사용
- 검증할 때마다 매 단계에서 다른 데이터를 사용
- cross_val_score().mean()
- 앞으로는 7. 평가단계에서 score() 대신 cross_val_score().mean() 사용하여 모델 평가
### 특성 선택
- 데이터가 엄청 많아지게 되면 데이터를 줄여야 함
- 1. 학습량이 늘어나서 시간이 많이 소요됨
- 2. 쓸데없는 데이터가 발생(도움이 안되는 데이터) => 불필요한 계산 시간이 소요
- 쓸모있는 데이터만 남기자
#### Decision Tree 모델에서의 특성 선택
tree_model
# 사용한 특성의 중요도 확인하기
# 전체 117개의 중요도 총합이 1
# 0 ~ 1 사이의 값으로 표시
# 1에 가까울수록 중요한 특성
fi = tree_model.feature_importances_
# 특성의 중요도를 확인하기 위해서 데이터프레임 형태로 변환
df = pd.DataFrame(fi, index=X_onehot.columns)
# 가장 많이 사용된 특성들만 확인
# 컬럼명을 따로 명시하지 않아서 생성된 컬럼명 0을 기준으로 내림차순 정렬
df.sort_values(by=0, ascending=False)
# 중요도가 0인 것을 제외하고 확인
# 불리언 인덱싱
df[df[0] != 0]
# 실제 버섯의 독성/식용 분류에 사용된 특성은 11개
'Computer Engineering > 머신러닝' 카테고리의 다른 글
타이타닉 데이터 실습_앙상블 (0) | 2023.06.15 |
---|---|
타이타닉 데이터 분류 (0) | 2023.06.13 |
KNN-iris 분류 실습 (2) | 2023.06.07 |
머신러닝 학습 7단계 (0) | 2023.06.05 |
머신러닝 기초_AND 연산 (0) | 2023.06.02 |
댓글