6장 결정트리

주요 내용

참고: 핵심 설명과 코드는 🔑로 표시되었으며 굳이 알아둘 필요가 없는 코드는 ✋로 표시되었다.

기본 설정

6.1 결정트리 학습과 시각화 (p. 229)

DecisionTreeClassifier 클래스는 결정트리 알고리즘을 활용한 분류 모델을 지원한다. 아래 코드는 붓꽃 데이터의 꽃잎 길이와 꽃잎 너비 특성만을 이용한 결정트리 모델의 훈련방법을 보여준다.

주의사항: 아래 코드는 파이썬 3.8을 사용하는 경우 필요한 모듈을 설치할 수 없기에 실행하지 말아야 한다. 이어지는 코드의 실행과는 무관한 그래프 지원 보조코드이다. 하만 다행이도 파썬 3.7 버전을 사용하는 구글 코랩에서는 잘 실행된다.

아래 코드는 graphviz 모듈의 기능을 이용하여 학습된 결정트리 분류모델의 훈련결과를 보여준다. 각각의 노드(node)에서 훈련과정에 사용된 값과 속성을 확인할 수 있다.

6.2 예측하기 (p. 231)

아래 코드는 결정트리 분류 모델의 클래스 예측결과를 그래프로 그린다.

아래 코드는 가지분할을 최대 3번까지 허용해서 얻어진 모델의 훈련샘플들에 대한 예측결과를 보여준다.

학습된 결정트리의 모양은 다음과 같다.

주의사항: 아래 코드는 파이썬 3.8을 사용하는 경우 필요한 모듈을 설치할 수 없기에 실행하지 말아야 한다. 이어지는 코드의 실행과는 무관한 그래프 지원 보조코드이다.

화이트박스 vs. 블랙박스

결정트리 모델처럼 훈련과 예측 과정은 명료하게 추적할 수 있는 모델을 화이트박스(white box) 모델이라 부른다. 반면에 앞으로 다룰 예정인 랜덤 포레스트, 신경망 등의 모델은 블랙박스(black box) 모델이라 부른다. 이유는 그런 모델들의 훈련과 예측 과정을 정확히 설명할 수 있기 때문이다.

6.3 클래스 확률 추정 (p. 234)

입력 샘플의 클래스 확률은 샘플이 속한 리프 노드(leaf node)의 클래스 비율을 사용하며, 가장 높은 비율의 클래스를 예측값으로 사용한다. 따라서 노드에 속한 모든 샘플의 클래스 확률은 동일하다.

아래 코드는 꽃잎 길이와 너비가 각각 5cm, 1.5cm인 붗꽃의 품종별 확률과 예측값을 보여준다.

6.7 규제 매개변수 (p. 237)

결정트리 모델의 규제는 기본적으로 분할을 제한하는 다양한 방식으로 이루어진다. 아래 코드는 min_samples_leaf=4 규제를 사용하는 모델(아래 그림 오른편)과 어느 규제도 사용하지 않은 모델(아래 그림 왼편)의 차이를 보여준다. 사용되는 훈련세트는 moons 데이터셋이다.

6.8 회귀 (p. 239)

결정트리 회귀모델 알고리즘은 분류모델과 거의 동일한 알고리즘을 사용한다. 아래 코드는 2차 다항식을 이용하여 생성된 훈련 세트에 대한 결정트리 회귀모델 훈련을 보여준다.

아래 코드는 max_depth를 2 또는 3으로 지정하고 결정트리 회귀모델을 훈련시킨 결과를 보여준다.

아래 함수는 훈련세트와 노드별 예측값(빨강 직선)을 그린다.

왼편 그래프에 해당하는 결정트리 회귀모델은 다음과 같다.

회귀모델 규제

결정트리 회귀모델의 규제는 CART 알고리즘이 노드 분할에 사용하는 기준(criterion) 하이퍼파라미터에 사용되는 값을 제외하고 분류모델의 경우와 완전히 동일하다.

아래 코드는 min_samples_leaf=10 규제를 사용하는 회귀모델(아래 그림 오른편)과 어느 규제도 사용하지 않은 회귀모델(아래 그림 왼편)의 차이를 보여준다.

6.9 불안정성 (p. 241)

결정트리 모델의 훈련과 사용은 매우 쉽고, 성능도 강력하다. 하지만 x, y 등의 축(axis)에 수직인 결정경계만 사용하기 때문에 회전, 샘플 삭제/추가 등 훈련세트의 작은 변화에 매우 민감하다.

회전 민감도 예제 1

아래 코드는 결정트리 모델의 회전 민감도를 보여준다. 두 개의 특성을 가지며, 임의로 생성된 100개의 훈련 샘플을 시계방향으로 45도 회전시킨 후 훈련시킨 모델의 결정경계가 직선에서 계단식으로 변화되는 것을 볼 수 있다. 결국 일반화 성능이 보다 약한 모델이 생성되었다.

회전 민감도 예제 2

아래 코드는 붗꽃 데이터를 시계방향으로 20도 회전한 후에 훈련시키면 분류 모델의 결정경계가 이전과 많이 다름을 잘 보여준다.

샘플 민감도 예제

아래 코드는 훈련세트에 포함된 버시컬러 품종 중에서 가장 넓은 꽃잎을 가진 샘플을 삭제한 후에 훈련시킨 결정트리 분류모델의 결정경계를 보여준다. 이전과 많이 다름에 주의하라.

결정경계 기준값으로 꽃잎의 길이는 전혀 사용되지 않는다.

연습문제 해답

1. to 6.

책 부록 A 참조.

7.

Exercise: train and fine-tune a Decision Tree for the moons dataset.

a. Generate a moons dataset using make_moons(n_samples=10000, noise=0.4).

Adding random_state=42 to make this notebook's output constant:

b. Split it into a training set and a test set using train_test_split().

c. Use grid search with cross-validation (with the help of the GridSearchCV class) to find good hyperparameter values for a DecisionTreeClassifier. Hint: try various values for max_leaf_nodes.

d. Train it on the full training set using these hyperparameters, and measure your model's performance on the test set. You should get roughly 85% to 87% accuracy.

By default, GridSearchCV trains the best model found on the whole training set (you can change this by setting refit=False), so we don't need to do it again. We can simply evaluate the model's accuracy:

8.

Exercise: Grow a forest.

a. Continuing the previous exercise, generate 1,000 subsets of the training set, each containing 100 instances selected randomly. Hint: you can use Scikit-Learn's ShuffleSplit class for this.

b. Train one Decision Tree on each subset, using the best hyperparameter values found above. Evaluate these 1,000 Decision Trees on the test set. Since they were trained on smaller sets, these Decision Trees will likely perform worse than the first Decision Tree, achieving only about 80% accuracy.

c. Now comes the magic. For each test set instance, generate the predictions of the 1,000 Decision Trees, and keep only the most frequent prediction (you can use SciPy's mode() function for this). This gives you majority-vote predictions over the test set.

d. Evaluate these predictions on the test set: you should obtain a slightly higher accuracy than your first model (about 0.5 to 1.5% higher). Congratulations, you have trained a Random Forest classifier!