이 단원에서는 YDF (Yggdrasil 결정 포레스트) 라이브러리를 사용하여 결정 트리를 학습하고 해석합니다.
이 단원은 🧭 YDF 시작하기 튜토리얼에서 가져온 내용입니다.
예비 과정
데이터 세트를 살펴보기 전에 다음을 실행합니다.
- 새 Colab 노트북을 만듭니다.
- 새 Colab 노트북에 다음 코드 줄을 배치하고 실행하여 YDF 라이브러리를 설치합니다.
!pip install ydf -U
- 다음 라이브러리를 가져옵니다.
import ydf import numpy as np import pandas as pd
Palmer Penguins 데이터 세트
이 Colab에서는 펭귄 3종의 크기 측정값이 포함된 Palmer Penguins 데이터 세트를 사용합니다.
- 턱끈
- Gentoo
- Adelie
이는 분류 문제입니다. 여기서 목표는 Palmer's Penguins 데이터 세트의 데이터를 기반으로 펭귄의 종을 예측하는 것입니다. 다음은 펭귄입니다.
그림 16. 세 가지 펭귄 종 이미지 제공: @allisonhorst
다음 코드는 pandas 함수를 호출하여 Palmer Penguins 데이터 세트를 메모리에 로드합니다.
path = "https://storage.googleapis.com/download.tensorflow.org/data/palmer_penguins/penguins.csv"
dataset = pd.read_csv(path)
label = "species"
# Display the first 3 examples.
dataset.head(3)
다음 표에는 Palmer Penguins 데이터 세트의 처음 3개 예시가 형식이 지정되어 있습니다.
표 3. Palmer Penguins의 처음 3개 예시
종 | 섬 | bill_length_mm | bill_depth_mm | flipper_length_mm | body_mass_g | sex | 년 | |
---|---|---|---|---|---|---|---|---|
0 | Adelie | Torgersen | 39.1 | 18.7 | 181.0 | 3750.0 | 남성 | 2007 |
1 | Adelie | Torgersen | 39.5 | 17.4 | 186.0 | 3800.0 | 여성 | 2007 |
2 | Adelie | Torgersen | 40.3 | 18.0 | 195.0 | 3250.0 | 여성 | 2007 |
전체 데이터 세트에는 숫자 (예: bill_depth_mm
), 범주형 (예: island
), 누락된 특성이 혼합되어 있습니다. 신경망과 달리 결정 트리는 이러한 모든 특성 유형을 기본적으로 지원하므로 원-핫 인코딩, 정규화 또는 추가 is_present 기능을 수행할 필요가 없습니다.
다음 코드 셀은 데이터 세트를 학습 세트와 테스트 세트로 분할합니다.
# Use the ~20% of the examples as the testing set
# and the remaining ~80% of the examples as the training set.
np.random.seed(1)
is_test = np.random.rand(len(dataset)) < 0.2
train_dataset = dataset[~is_test]
test_dataset = dataset[is_test]
print("Training examples: ", len(train_dataset))
# >> Training examples: 272
print("Testing examples: ", len(test_dataset))
# >> Testing examples: 72
기본 초매개변수를 사용하여 결정 트리 학습
하이퍼파라미터를 지정하지 않고도 CART (분류 및 회귀 트리) 학습 알고리즘 (학습자라고도 함)으로 첫 번째 결정 트리를 학습시킬 수 있습니다.
ydf.CartLearner
학습자가 적절한 기본 초매개변수 값을 제공하기 때문입니다. 이 유형의 모델이 작동하는 방식은 과정 후반부에서 자세히 알아봅니다.
model = ydf.CartLearner(label=label).train(train_dataset)
위의 호출에서는 입력 지형지물로 사용할 열을 지정하지 않았습니다. 따라서 학습 세트의 모든 열이 사용됩니다. 또한 호출에서 입력 특성의 시맨틱 (예: 숫자, 범주, 텍스트)을 지정하지 않았습니다. 따라서 지형지물 시맨틱이 자동으로 추론됩니다.
model.plot_tree()
를 호출하여 결과 결정 트리를 표시합니다.
model.plot_tree()
Colab에서는 마우스를 사용하여 각 노드의 클래스 분포와 같은 특정 요소에 관한 세부정보를 표시할 수 있습니다.
그림 17. 기본 초매개변수로 학습된 결정 트리입니다.
Colab에 따르면 루트 조건에는 243개의 예시가 포함되어 있습니다. 하지만 학습 데이터 세트에는 272개의 예시가 포함되어 있었음을 기억할 수 있습니다. 나머지 29개 예시는 유효성 검사 및 트리 프루닝을 위해 자동으로 예약되었습니다.
첫 번째 조건은 bill_depth_mm
의 값을 테스트합니다. 표 4와 5는 첫 번째 조건의 결과에 따라 다양한 종의 가능성을 보여줍니다.
표 4. bill_depth_mm ≥
42.3
인 경우 다른 종의 가능성
종 | 가능성 |
---|---|
아델리 (빨간색) | 8% |
Gentoo (파란색) | 58% |
턱끈 (녹색) | 36% |
표 5. bill_depth_mm < 42.3
인 경우 다른 종의 가능성
종 | 가능성 |
---|---|
아델리 (빨간색) | 97% |
Gentoo (파란색) | 2% |
턱끈 (녹색) | 0% |
bill_depth_mm
은 숫자 특성입니다. 따라서 숫자 특징을 사용한 이진 분류의 정확한 분할 알고리즘을 사용하여 42.3이라는 값이 발견되었습니다.
bill_depth_mm ≥ 42.3
가 True인 경우 flipper_length_mm ≥ 207.5
가 Gentoo와 Gentoos+Adelie를 거의 완벽하게 구분할 수 있는지 추가로 테스트합니다.
다음 코드는 모델의 학습 및 테스트 정확도를 제공합니다.
train_evaluation = model.evaluate(train_dataset)
print("train accuracy:", train_evaluation.accuracy)
# >> train accuracy: 0.9338
test_evaluation = model.evaluate(test_dataset)
print("test accuracy:", test_evaluation.accuracy)
# >> test accuracy: 0.9167
테스트 정확성이 학습 정확성보다 높은 경우는 드물지만 가능합니다. 이 경우 테스트 세트가 학습 세트와 다를 수 있습니다. 하지만 여기서는 트레인과 테스트가 무작위로 분할되었으므로 이 경우는 아닙니다. 더 가능성이 높은 설명은 테스트 데이터 세트가 매우 작아서 (예시 72개) 정확도 추정치에 노이즈가 있다는 것입니다.
실제로는 이렇게 작은 데이터 세트의 경우 교차 검증을 사용하는 것이 더 좋습니다. 교차 검증을 사용하면 더 정확한 평가 측정항목 값을 계산할 수 있기 때문입니다. 하지만 이 예에서는 편의상 학습 및 테스트를 계속 진행합니다.
모델 초매개변수 개선
이 모델은 기본 초매개변수 값으로 학습된 단일 결정 트리입니다. 더 나은 예측을 얻으려면 다음을 수행하세요.
랜덤 포레스트 또는 그래디언트 부스팅 트리 모델과 같이 더 강력한 학습기를 사용합니다. 이러한 학습 알고리즘은 다음 페이지에서 설명합니다.
관찰 및 직관을 사용하여 초매개변수를 최적화합니다. 모델 개선 가이드가 도움이 될 수 있습니다.
초매개변수 조정을 사용하여 가능한 많은 수의 초매개변수를 자동으로 테스트합니다.
아직 랜덤 포레스트 및 경사 부스트 트리 알고리즘을 보지 못했고, 자동 초매개변수 조정을 수행하기에는 예시 수가 너무 적으므로 모델을 수동으로 개선하겠습니다.
위에 표시된 결정 트리는 작으며 61개의 예가 포함된 리프에는 아델리 및 턱끈펭귄 라벨이 혼합되어 있습니다. 알고리즘이 이 리프를 더 이상 분할하지 않은 이유는 무엇인가요? 다음과 같이 두 가지 원인이 있습니다.
- 리프당 최소 샘플 수 (기본값:
min_examples=5
)에 도달했을 수 있습니다. - 오버피팅을 방지하기 위해 트리가 분할된 후 정리되었을 수 있습니다.
최소 예시 수를 1로 줄이고 결과를 확인합니다.
model = ydf.CartLearner(label=label, min_examples=1).train(train_dataset)
model.plot_tree()
그림 18. min_examples=1로 학습된 결정 트리입니다.
61개의 예가 포함된 리프 노드가 여러 번 더 분할되었습니다.
노드를 더 나누는 것이 유용한지 확인하기 위해 테스트 데이터 세트에서 이 새 모델의 품질을 평가합니다.
print(model.evaluate(test_dataset).accuracy)
# >> 0.97222
테스트 정확도가 0.9167에서 0.97222로 증가하면서 모델 품질이 향상되었습니다. 초매개변수를 변경한 것은 좋은 생각입니다.
결정 포레스트의 이전
초매개변수를 계속 개선하면 완벽한 정확성에 도달할 수 있습니다. 하지만 이 수동 프로세스 대신 랜덤 포레스트와 같이 더 강력한 모델을 학습시키고 더 잘 작동하는지 확인할 수 있습니다.
model = ydf.RandomForestLearner(label=label).train(train_dataset)
print("Test accuracy: ", model.evaluate(test_dataset).accuracy)
# >> Test accuracy: 0.986111
랜덤 포레스트의 정확성은 단순한 트리보다 우수합니다. 다음 페이지에서 그 이유를 알아봅니다.
사용 및 제한사항
앞서 언급한 바와 같이 단일 결정 트리는 랜덤 포레스트, 그래디언트 부스티드 트리, 신경망과 같은 최신 머신러닝 방법보다 품질이 낮은 경우가 많습니다. 하지만 다음과 같은 경우에는 결정 트리가 여전히 유용합니다.
- 더 복잡한 접근 방식을 평가하기 위한 간단하고 저렴한 기준으로
- 모델 품질과 해석 가능성 간에 절충이 이루어지는 경우
- 결정 포레스트 모델의 해석을 위한 대리 변수로, 이 과정에서는 나중에 살펴봅니다.