머신러닝 4: 혼공머신 5장
5장: 트리 알고리즘
결정 트리
결정 트리 | 로지스틱 회귀 |
---|---|
이유를 설명하기 쉽다 | 결과를 설명하기 어렵다 |
- 사이킷런의 DecisionTreeClassifier 클래스를 사용하여 결정 트리 모델을 수립할 수 있다.
1
2
3
4
5
6
7
from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(random_state=42)
dt.fit(train_scaled, train_target)
print(dt.score(train_scaled, train_target))
print(dt.score(test_scaled, test_target))
plot_tree() 함수를 이용하여 결정 트리를 이해하기 쉬운 트리 그림으로 볼 수 있다.
1 2 3 4 5 6
import matplotlib.pyplot as plt from sklearn.tree import plot_tree plt.figure(figsize=(10,7)) plot_tree(dt) plt.show()
- 위 그림에서 맨 위의 노드를 루트 노드라고 부르고 맨 아래 끝에 달린 노드를 리프 노드라고 부른다.
- 노드란: 훈련 데이터의 특성에 대한 테스트를 표현한다.
- 가지(branch)는 테스트의 결과(True/False)를 나타내며 일반적으로 하나의 노드는 2개의 가지를 가진다.
- 매개변수:
- max_depth: 루트 노드를 제외하고 몇 개의 노드를 더 확장하여 그린다
- filled: 클래스에 맞게 노드의 색을 칠할 수 있다
feature_names: 특성의 이름을 전달한다
1 2 3
plt.figure(figsize=(10,7)) plot_tree(dt, max_depth=1, filled=True, feature_names=['alcohol', 'sugar', 'pH']) plt.show()
결정 트리 그림을 읽는 방법:
- 위 그림에서 맨 위의 노드를 루트 노드라고 부르고 맨 아래 끝에 달린 노드를 리프 노드라고 부른다.
- criterion 매개변수: 노드에서 데이터를 분할할 기준을 정하는 것
- 지니 불순도
- 기본적으로 criterion 매개변수가 ‘gini’로 지정한다 \(\text{지니 불순도} = 1 - (\text{음서 클래스 비율}^2 + \text{양성 클래스 비율}^2)\)
- 정보 이득(information gain)이란: 결정 트리 모델은 부모 노드 (parent node)와 자식 노드(child node)의 불순도 차이가 가능한 크도록 트리를 성장시킨다. \(\text{부모의 불손도} - \frac{\text{왼쪽 노드 샘플 수}}{\text{부모의 샘플 수}} \times \text{왼쪽 노드 불순도} - \frac{\text{오른쪽 노드 샘플 수}}{\text{부모의 샘플 수}} \times \text{오른쪽 노드 불순도}\)
- 엔트로피 불순도
criteron = 'entropy'
로 지정한다- 지니 불순도와 달라 제곱을 사용하는 대신에 밑이 2인 로그를 사용하여 곱한다. \(-\text{음성 클래스 비율} \times \log_2{(\text{음성 클래스 비율})} - \text{양성 클래스 비율} \times \log_2{(\text{양성 클래스 비율})}\)
가지치기
- 과대적합을 피하기 위한 과정
- DecisionTreeClassifier 클래스에 있는 max_depth 매개변수를 이용하여 최대 깊이를 지정할 수 있다.
1
dt = DecisionTreeClassifier(max_depth=3, random_state=42)
특성 중요도
- 결정 트리에 사용된 특성이 불순도를 감소하는데 기여한 정도를 나타내는 값이다
- feature_imporances_ 속성을 이용하여 특성 중요도를 볼 수 있다.
1
dt.feature_importances_
교차 검증과 그리드 서치
검증 세트
테스트 세트를 사용하지 않고 모델이 과대적합인지 과소적합인지 측정하기를 위하여 훈련 세트를 또 나눈다.
- 훈련 세트에서 모델을 훈련하고 검증 세트로 모델을 평가한다
- 이런 식으로 테스트하고 싶은 매개변수를 바꿔가며 가장 좋은 모델을 고른다
- 이 매개변수를 이용하여 훈련세트 와 검증 세트를 합쳐 전체 훈련 데이터에서 모델을 다시 훈련하고 마지막에 테스트 세트에서 최종 점수를 평가한다
- 이런 식으로 테스트하고 싶은 매개변수를 바꿔가며 가장 좋은 모델을 고른다
- 이전처럼 train_test_split() 함수를 이용하여 전체 데이터를 훈련 세트와 테스트 세트로 나누고 그 함수를 이용하여 훈련 세트를 또 훈련 세트와 검증 세트로 나눈다.
1
2
3
train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42)
sub_input, val_input, sub_target, val_target = train_test_split(train_input, train_target, test_size=0.2, random_state=42)
교차 검증
검증 세트를 만드느라 후련 세트가 줄었는 탓에 어누 조금 떼어 놓으면 불안정할 수도 있으므로 교차 검증(cross validation을 이용하여 안정적인 검증 점수를 얻을 수 있도 훈련에 더 많은 데이터를 사용할 수 있다.
- 훈련 세트를 k 부분으로 나눠서 교차 검증을 수행하는 것을 k-폴드 교차 검증(k-fold cross validation)이라고 한다
- 보통 5-폴드 교차 검증이나 10-폴드 교차 검증을 많이 사용한다.
- 사이킷런에 있는 cross_validate() 함수를 이용하여 교차 검증을 수행할 수 있다
1
2
from sklearn.model_selection import cross_validate
scores = cross_validate(dt, train_input, train_target)
- 이 함수는 fit_time, score_time, test_score 키를 가진 딕셔너리를 반환한다
- fit_time: 모델을 훈련하는 시간
- score_time: 검증하는 시간
- test_score: 교차 검증의 최종 점수
- 기본적으로 5-폴드 검증을 수행하는데 cv 매개변수를 이용하 폴드 수를 바꿀 수도 있다
- cross_validate()는 훈련 세트를 섞어 폴드를 나누지 않은데 먼저 train_test_split() 함수로 전체 데이터를 섞어 훈련 세트를 준비했으니 따로 섞을 필요가 없다
- 교차 검증을 수행할 때 훈련 세트를 섞으려면 분할기(splitter)를 지정해야 된다
- 기본적으로 회귀 모델일 경우 KFold 분할기를 사용하고 분류 모델일 경우 타깃 클래스를 골고루 나누기 위하여 StratifiedKFold를 사용한다
1 2
from sklearn.model_selection import StratifiedKFold scores = cross_validate(dt, train_input, train_target, cv=StratifiedKFold())
- 만약 훈련 세트를 섞은 후 10-폴드 교차 수행하려면 (KFold도 동일한 방식으로 사용한다):
1
2
splitter = StratifiedKFold(n_splits=10, shuffle=True, random_state=42) # n_splits 매개변수는 k 값을 지정
scores = cross_validate(dt, train_input, train_target, cv=splitter)
하이퍼파라미터 튜닝
- 검증 세트의 점수나 교차 검증을 통해서 매개변수를 조금씩 바꾼다
- 그리드 서치를 이용하여 어떤 모델에 대한 매개변수들의 최적값을 찾을 수 있다
- 사이킷런에 GridSearchCV 클래스를 이용할 수 있다
1
2
3
4
from sklearn.model_selection import GridSearchCV
params = {'min_impurity_decrease': [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]} # 0.0001qnxj 0.0005 0.0001씩 증가하는 5대의 값을 시도
gs = GridSearchCV(DecisionTreeClassier(random_state=42), params, n_jobs=-1)
- best_params_ 속성을 이용하여 최적의 매개변수를 알아볼 수 있다
랜덤 서치
- 또 너무 많은 매개변수 조건이 있으면 그리드 서티 수행 시간이 오래 걸릴 수 있으므로 이 경우에는 랜덤 서치를 사용하면 좋다
- 매개변수 값의 목록을 전달하는 것이 아니라 매개변수를 샘플링할 수 있는 확률 분포 객체를 전달한다
1
2
3
4
5
6
7
from scipy.stats import uniform, randint # uniform은 실숫값을 뽑고 randint는 정숫값을 뽑는다
# 0에서 10 사이의 범위를 갖는 randint 객체를 만들고 10개의숫자를 샘플링한다
rgen = randint(0, 10)
rgen.rvs(10)
# uniform 생성 방법 똑같다
트리 앙상블
정형 데이터와 비정형 데이터
- 정형 데이터(structured data)이란: 어떤 구조로 되어 있다
- CSV, 데이터베이스, 엑셀
- 비정형 데이터(unstructured data): 데이터베이스나 엑셀로 표현하기 어렵다
- 책의 글, 텍스트 데이터, 기지털카메라로 찍은 사진, 등
- 신경망 알고리즘을 이용하여 학습
- 앙상블 학습: 정형 데이터를 다루는 데 가장 뛰어난 성과를 내는 알고리즘
랜덤 포레스트
- 결정 트리를 랜덤하게 만들어 결정 트리의 숲을 만든다
부트스트랩 샘플: n 개 샘플에서 k 개씩 샘플을 뽑는다
- 사이킷런에 있는 RandomForestClassifier 클래스를 이용하여 랜덤 포레스트를 수행할 수 있다
1
2
from sklearn.ensemle import RandomForestClassifier
rf = RandomForestClassifier(n_jobs=-1, random_state=42)
- oob_score 매개변수를 이용하여 자체적으로 모델을 평가하는 점수를 얻을 수 있다
1
2
3
rf = RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)
rf.fit(train_input, train_target)
print(rf.oob_score_)
엑스트라 트리
- 랜덤 포레스트와 매우 비숫하게 동작하는데 랜덤포레스트와 달라 부트스트랩 샘플을 사용하지 않는다
1
2
from sklearn.ensemble import ExtraTreesClassifier
et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
그레이디언트 부스팅
- 깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블 하는 방법이다
- 과대적합에 강하고 일반적으로 높은 일반화 성능을 기대할 수 있다
1
2
from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(random_state=42)
- 학습률을 증가시키고 트리의 개수를 늘리면 조금 더 성능이 향상될 수 있다
1
gb = GradientBoostingClassifier(n_estimators=500, learning_rate=0.2, random_state=42)
히스토그램 기반 그레이디언트 부스팅
- 그레이디언트 부스팅의 속도를 개선한 것이며 안정적인 결과와 높은 성능으로 매우 인기가 높다
1
2
3
from sklearn.experimental import enable_hist_gradient_boosing
from sklearn.ensemble import HistGradientBoostingClassifier
hbg = HistGradientBoostingClassifier(random_state=42)
- 사이킷런 말고 히스토그램 기반 그레이디언트 부스팅 알고리즘을 구현한 대표적인 라이브러리는 XGBoost이다.
1
2
from xgboost import XGBClassifier
xgb = XGBClassifier(tree_method='hist', random_state=42)
This post is licensed under CC BY 4.0 by the author.