이 단원에서는 YDF (Yggdrasil 결정 포레스트) 라이브러리를 사용하여 결정 트리를 학습하고 해석합니다.
이 단원은 🧭 YDF 시작하기 튜토리얼에서 영감을 받았습니다.
예비 과정
데이터 세트를 살펴보기 전에 다음을 수행하세요.
- 새 Colab 노트북을 만듭니다.
- 새 Colab 노트북에 다음 코드 줄을 배치하고 실행하여 YDF 라이브러리를 설치합니다.
!pip install ydf -U
- 다음 라이브러리를 가져옵니다.
import ydf import numpy as np import pandas as pd
Palmer Penguins 데이터 세트
이 Colab에서는 세 가지 펭귄 종의 크기 측정값이 포함된 Palmer Penguins 데이터 세트를 사용합니다.
- 턱끈
- Gentoo
- 아델리
이는 분류 문제입니다. 목표는 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 | 아델리 | Torgersen | 39.1 | 18.7 | 181.0 | 3750.0 | 남성 | 2007 |
1 | 아델리 | Torgersen | 39.5 | 17.4 | 186.0 | 3800.0 | 여성 | 2007 |
2 | 아델리 | 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와 Gentoo+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
랜덤 포레스트의 정확도가 단순 트리보다 높습니다. 다음 페이지에서 그 이유를 알아봅니다.
사용 및 제한사항
앞서 언급한 것처럼 단일 의사결정 트리는 랜덤 포레스트, 그레이디언트 부스티드 트리, 신경망과 같은 최신 머신러닝 방법보다 품질이 낮은 경우가 많습니다. 하지만 다음과 같은 경우에는 결정 트리가 여전히 유용합니다.
- 더 복잡한 접근 방식을 평가하기 위한 간단하고 저렴한 기준선
- 모델 품질과 해석 가능성 사이에 상충 관계가 있는 경우
- 이 과정에서 나중에 살펴볼 결정 포레스트 모델의 해석을 대신합니다.