콘텐츠로 이동

10.2 결정트리 분류기

결정트리의 구조

결정트리(decision tree)는 "특징 값이 기준보다 작거나 같은가"라는 질문을 반복해 자료를 분할하고, 마지막 분할 영역마다 하나의 범주를 배정하는 모델이다. 학습 과정에서는 각 단계에서 두 범주가 가장 잘 구분되는 특징과 기준값을 자동으로 선택한다. 학습 결과가 조건문 형태로 출력되므로 사람이 판정 근거를 해석할 수 있고, 외부 라이브러리 없이 if 문으로 변환할 수 있다. 이 성질은 11장에서 모델을 사이버파이에 탑재할 때 사용한다.

용어 의미
분기(split) 하나의 특징과 기준값으로 자료를 두 영역으로 분할하는 질문
깊이(depth) 뿌리에서 가장 아래 분기까지 질문이 이어지는 단계 수
잎(leaf) 더 이상 분할하지 않는 마지막 영역, 하나의 범주를 출력

모델 학습과 규칙 출력

깊이를 3으로 제한한 결정트리를 학습하고, export_text로 분기 규칙을 출력한다.

from sklearn.tree import DecisionTreeClassifier, export_text

clf = DecisionTreeClassifier(max_depth=3, random_state=0)
clf.fit(train[feats], train["target_rain"])
print(export_text(clf, feature_names=feats, decimals=1))

실행 결과

|--- precip_mm <= 2.4
|   |--- doy_cos <= -0.4
|   |   |--- doy_sin <= 0.1
|   |   |   |--- class: 0
|   |   |--- doy_sin >  0.1
|   |   |   |--- class: 0
|   |--- doy_cos >  -0.4
|   |   |--- sunshine_h <= 8.8
|   |   |   |--- class: 0
|   |   |--- sunshine_h >  8.8
|   |   |   |--- class: 0
|--- precip_mm >  2.4
|   |--- doy_cos <= 0.2
|   |   |--- precip_mm <= 20.4
|   |   |   |--- class: 1
|   |   |--- precip_mm >  20.4
|   |   |   |--- class: 1
|   |--- doy_cos >  0.2
|   |   |--- precip_mm <= 11.2
|   |   |   |--- class: 0
|   |   |--- precip_mm >  11.2
|   |   |   |--- class: 1

규칙의 해석

첫 분기는 오늘 강수량이 2.4 mm 이하인가를 판정한다. 학습 알고리즘이 7개 특징 중 오늘 강수량을 첫 기준으로 선택했으므로, 오늘의 강수 여부가 다음 날 강수 여부와 가장 밀접하다는 의미다.

경로 조건 예측
오늘 강수량 2.4 mm 이하 모든 하위 경로 0(무강수)
오늘 강수량 2.4 mm 초과, doy_cos 0.2 이하 3월 하순~10월 중순(9.2절) 1(강수)
오늘 강수량 2.4 mm 초과, doy_cos 0.2 초과 10월 중순~3월 하순, 오늘 강수량 11.2 mm 이하 0(무강수)
〃 10월 중순~3월 하순, 오늘 강수량 11.2 mm 초과 1(강수)

doy_cos가 0.2인 날은 연중 약 80일째(3월 하순)와 약 286일째(10월 중순)다. 정리하면 이 트리는 "오늘 비가 2.4 mm를 초과해 내렸고, 3월 하순~10월 중순이거나 강수량이 11.2 mm를 초과하면 내일도 비가 온다"고 판정한다. 왼쪽 가지의 잎 4개는 모두 0을 출력한다. 하위 분기가 두 범주의 비율을 변경하기는 하지만, 어느 잎에서도 강수일이 무강수일보다 많지 않으므로 같은 범주가 배정되었다. 따라서 오늘 강수량이 2.4 mm 이하인 날에 대해서는 이 트리가 다음 날 강수를 예측하지 못한다. 10.3절에서 이 결과가 재현율에 미치는 영향을 확인한다.

확인 문제

  1. max_depth=2로 다시 학습하고 출력된 규칙을 표로 정리하시오.
  2. 위 트리를 if·elif·else 문으로 작성한 함수 predict_rain(precip_mm, doy_cos)로 변환하시오. 오른쪽 가지만 구현하면 된다.