이번 포스팅에서는 머신러닝 모델 중에서 가장 많이 쓰이는 모델 중 하나인 랜덤포레스트와 그 기반이 되는 결정트리에 대해 알아봅니다.
Decision Tree(결정트리)
Decision Tree 원리 및 용어
- 데이터를 잘 분류할 수 있는 질문을 던져 가며 대상을 좁혀가는 '스무고개'와 비슷한 형식의 알고리즘.
- 분기해 나가는 구조가 Tree 구조와 같기 때문에 Decision Tree 라고 한다.
- 불순도 최대한 감소하는 방향으로 조건을 만들어 학습을 진행한다.
- 하위노드는 yes/no 두 개로 분기 된다.
- 머신러닝 모델들 중 몇안되는 White box 모델로 결과에 대한 해석이 가능하다.
- 과대적합(Overfitting)이 발생하기 쉽다.
- 앙상블기반 알고리즘인 랜덤 포레스트와 많은 부스팅(Boosting)기반 앙상블 모델들의 기반 알고리즘으로 사용된다.
순도(purity) / 불순도(impurity)
- 서로 다른 종류의 값들이 섞여 있는 비율
- 한 종류(class)의 값이 많을 수록 순도가 높고 불순도는 낮다.
Decision Tree(결정트리) 용어
- Root Node : 시작 node
- Decision Node (Intermediate Node): 중간 node
- Leaf Node(Terminal Node) : 마지막 단계의 노드로 최종결과를 가진다.
과대적합(Overfitting) 문제
- 모든 데이터셋이 모두 잘 분류 되어 불순도가 0이 될때 까지 분기해 나간다.
- Root에서 부터 하위 노드가 많이 만들어 질 수록 모델이 복잡해져 과대적합이 발생할 수 있다.
- 과대적합을 막기 위해서는 적당한 시점에 하위노드가 더이상 생성되지 않도록 해야 한다.
- 가지치기(Pruning)라고 한다.
Decision Tree 하이퍼파라미터
- 가지치기 관련 하이퍼파라미터
- max_depth : 최대 깊이
- max_leaf_nodes : 생성될 최대 Leaf Node 개수 제한
- min_samples_leaf: 가지를 칠 최소 sample 수. sample 수가 지정한 값보다 작으면 불순도와 상관없이 가지를 치지 않는다.
- criterion (크라이티어리언-판단기준)
- 불순도 계산 방식을 하이퍼파라미터
- gini (기본값)
- entropy
Feature(컬럼) 중요도 조회
- feature_importances_ 속성
- 모델을 만들때 각 Feature의 중요도를 반환
- input data 에서 중요한 feature를 찾기 위해 decision tree를 이용하기도 한다.
Decision Tree(결정트리) 모델링 예시
wine color 분류
- https://archive.ics.uci.edu/ml/datasets/Wine+Quality
- features
- 와인 화학성분들
- fixed acidity : 고정 산도
- volatile acidity : 휘발성 산도
- citric acid : 시트르산
- residual sugar : 잔류 당분
- chlorides : 염화물
- free sulfur dioxide : 자유 이산화황
- total sulfur dioxide : 총 이산화황
- density : 밀도
- pH : 수소 이온 농도
- sulphates : 황산염
- alcohol : 알콜
- quality: 와인 등급 (A>B>C)
- 와인 화학성분들
- target - color
- 0: white, 1: red
데이터 세팅 및 전처리
import pandas as pd
import numpy as np
wine = pd.read_csv('data/wine.csv')
wine['color'].value_counts()
# 0 4898
# 1 1599
wine['quality'].value_counts()
# B 2836
# C 2384
# A 1277
# quality 를 LabelEncoder를 이용해 숫자로 변경.
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
wine['quality'] = encoder.fit_transform(wine['quality'])
Decision Tree(결정트리) 모델링 및 성능평가
# 데이터셋과 타겟 분리
y = wine['color'] #output/target/label
X = wine.drop(columns='color') #input/feature
from sklearn.model_selection import train_test_split
#train/test set 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y)
from sklearn.tree import DecisionTreeClassifier
# 모델 생성
dt = DecisionTreeClassifier()
# 학습
dt.fit(X_train, y_train)
# ==>DecisionTreeClassifier(ccp_alpha=0.0, class_weight=None, criterion='gini',
# max_depth=None, max_features=None, max_leaf_nodes=None,
# min_impurity_decrease=0.0, min_impurity_split=None,
# min_samples_leaf=1, min_samples_split=2,
# min_weight_fraction_leaf=0.0, presort='deprecated',
# random_state=None, splitter='best')
# 예측, 검증
from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score, confusion_matrix
pred_train = dt.predict(X_train)
pred_test = dt.predict(X_test)
Decision Tree(결정트리) 모델링 시각화
from sklearn.tree import export_graphviz
from graphviz import Source
eg = export_graphviz(dt,
out_file=None,
feature_names = X.columns,
class_names = ['White','Red'],
rounded=True, filled=True)
graph = Source(eg)
graph
Decision Tree(결정트리) 중요 feature 조회
# 중요한 feature(컬럼)들 조회
dt.feature_importances_
# array([0.02757233, 0.0141966 , 0.00671037, 0.00773827, 0.66640735,
0.00553605, 0.21855338, 0.02588049, 0.01621922, 0.00813591,
0.00305004, 0. ])
f_i = pd.Series(dt.feature_importances_, index=X_train.columns)
f_i.sort_values(ascending=False)
import matplotlib.pyplot as plt
f_i.sort_values().plot(kind='barh', figsize=(10,6))
plt.show()
Decision Tree(결정트리) GridSerchCV 모델링
from sklearn.model_selection import GridSearchCV
param_grid = {
'max_depth':range(3,15),
'min_samples_leaf':range(5,51,5)
}
gs = GridSearchCV(DecisionTreeClassifier(),
param_grid = param_grid,
cv=5,
n_jobs=-1,
scoring=['accuracy','recall','precision', 'f1'],
refit='accuracy'
)
# GridSearch/Random Search 에서 평가지표를 여러개 선택한 경우 best param을 선택할때 사용할 평가지표를 알려줘야 한다.
# - refit='평가지표'
Feature(컬럼) 중요도 조회
Random Forest (랜덤포레스트)와 앙상블(Ensemble)
앙상블(Ensemble) 기법
- 하나의 모델만을 학습시켜 사용하지 않고 여러 모델을 학습시켜 결합하는 방식으로 문제를 해결하는 방식
- 개별로 학습한 여러 모델을 조합해 과적합을 막고 일반화 성능을 향상시킬 수 있다.
- 개별 모델의 성능이 확보되지 않을 때 성능향상에 도움될 수 있다.
앙상블의 종류
1. 투표방식
- 여러개의 추정기(Estimator)가 낸 결과들을 투표를 통해 최종 결과를 내는 방식
- 종류
- Bagging - 같은 유형의 알고리즘들을 조합하되 각각 학습하는 데이터를 다르게 한다.
- Voting - 서로 다른 종류의 알고리즘들을 결합한다.
2. 부스팅(Boosting)
- 약한 학습기(Weak Learner)들을 결합해서 보다 정확하고 강력한 학습기(Strong Learner)를 만든다.
- 각 약한 학습기들은 순서대로 일을 하며 뒤의 학습기들은 앞의 학습기가 찾지 못한 부분을 추가적으로 찾는다.
Random Forest (랜덤포레스트)
- Bagging 방식의 앙상블 모델이며 결정 Tree를 기반으로 한다.
- 다수의 결정트리를 사용해서 성능을 올린 앙상블 알고리즘의 하나
- 학습데이터를 샘플링해서 다수의 결정트리를 생성하고 이를 기반으로 다수결로 결과를 결정하는 방식
- 다수의 결정트리를 만드는데서 랜덤포레스트라고 부른다.
- 처리속도가 빠르며 분류 성능도 높은 모델로 알려져 있다.
- 랜덤포레스트의 절차
- 결정트리의 개수를 하이퍼파라미터로 받는다.
- 랜덤 포레스트를 구성하는 모든 결정트리가 서로 다르도록 만든다.
- 각 트리는 부트스트랩 샘플링(중복을 허용하면서 랜덤하게 샘플링하는 방식)으로 데이터셋을 준비한다. (총데이터의 수는 원래 데이터셋과 동일 하지만 일부는 누락되고 일부는 중복된다.)
- 각 트리는 전체 피처중 일부의 피처만 랜덤하게 가지게 된다.
- 각 트리별로 예측결과를 내고 분류의 경우 그 예측을 모아 다수결 투표로 클래스 결과를 낸다.
- 회귀의 경우는 예측 결과의 평균을 낸다.
- 주요 하이퍼파라미터
- n_estimators
- tree의 개수
- 시간과 메모리가 허용하는 범위에서 클수록 좋다.
- max_features
- 각 트리에서 선택할 feature의 개수
- 클수록 각 트리간의 feature 차이가 없어지고 작을 수록 차이가 많이 나게 된다.
- max_depth, min_samples_leaf, ..
- DecisionTreeClassifier의 하이퍼파라미터들
- 트리의 최대 깊이, 가지를 치기 위한 최소 샘플 수 등 결정 트리에서 과적합을 막기 위한 파라미터들을 랜덤 포레스트에 적용할 수 있다.
- n_estimators
Random Forest 모델링 예시 (1)
wine color 분류
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier(n_estimators=200, #결정트리 모델의 개수.
max_depth=3, #각 결정트리의 max_depth 하이퍼파라미터 지정.
max_features=5 #Train 데이터셋을 샘플링할때 컬럼(feature)의 개수.
)
rfc.fit(X_train, y_train)
#==> RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
criterion='gini', max_depth=3, max_features=5,
max_leaf_nodes=None, max_samples=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=200,
n_jobs=None, oob_score=False, random_state=None,
verbose=0, warm_start=False)
pred_train = rfc.predict(X_train)
pred_test = rfc.predict(X_test)
accuracy_score(y_train, pred_train), accuracy_score(y_test, pred_test)
(0.9883004926108374, 0.9821538461538462)
f1_score(y_train, pred_train), f1_score(y_test, pred_test)
(0.9760201935212451, 0.9633375474083439)
feature 중요도 확인
f_i = rfc.feature_importances_
f_i_s = pd.Series(f_i, index=X_train.columns).sort_values(ascending=False)
f_i_s
Random Forest 모델링 예시 (2)
TODO 위스콘신 유방암 데이터셋 분류
데이터셋 로드 및 train/test set 분리
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.ensemble import RandomForestClassifier
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data,cancer.target,test_size = 0.3, stratify=cancer.target)
모델(Random Forest) 생성 및 학습
from sklearn.model_selection import GridSearchCV
ran_for = RandomForestClassifier()
gr_ran = GridSearchCV(ran_for, param_grid = {'max_depth':range(1,10)},cv=5,n_jobs=-1)
gr_ran.fit(X_train,y_train)
#==> GridSearchCV(cv=5, error_score=nan,
estimator=RandomForestClassifier(bootstrap=True, ccp_alpha=0.0,
class_weight=None,
criterion='gini', max_depth=None,
max_features='auto',
max_leaf_nodes=None,
max_samples=None,
min_impurity_decrease=0.0,
min_impurity_split=None,
min_samples_leaf=1,
min_samples_split=2,
min_weight_fraction_leaf=0.0,
n_estimators=100, n_jobs=None,
oob_score=False,
random_state=None, verbose=0,
warm_start=False),
iid='deprecated', n_jobs=-1,
param_grid={'max_depth': range(1, 10)}, pre_dispatch='2*n_jobs',
refit=True, return_train_score=False, scoring=None, verbose=0)
pred_train = gr_ran.predict(X_train)
pred_test = gr_ran.predict(X_test)
분류 정확도 검증
from sklearn.metrics import accuracy_score
accuracy_score(y_train, pred_train), accuracy_score(y_test, pred_test)
(0.9974874371859297, 0.9181286549707602)
특성 중요도 (Feature importance) 조회 및 시각화
from sklearn.model_selection import GridSearchCV
ran_for = RandomForestClassifier(n_estimators=200, max_depth=3, max_features=5)
ran_for.fit(X_train,y_train)
pred_train = ran_for.predict(X_train)
pred_test = ran_for.predict(X_test)
accuracy_score(y_train, pred_train), accuracy_score(y_test, pred_test)'
import numpy as np
import pandas as pd
f_i = ran_for.feature_importances_
f_i_s = pd.Series(f_i, index=cancer.feature_names).sort_values(ascending=False)
f_i_s.sort_values().plot(kind='barh',figsize=(10,5))
728x90
반응형
'Data Analysis & ML > Machine Learning' 카테고리의 다른 글
[Machine Learning][머신러닝] 최적화 / 경사하강법 (0) | 2020.09.03 |
---|---|
[Machine Learning][머신러닝][앙상블] Voting (0) | 2020.09.02 |
[Machine Learning][머신러닝][지도학습] SVM(Support Vector Machine) (0) | 2020.09.01 |
[Machine Learning][머신러닝][지도학습] K-최근접 이웃(KNN) (0) | 2020.09.01 |
[Machine Learning][머신러닝] 과적합과 해결방법(그리드서치/파이프라인) (0) | 2020.08.31 |