
결정 트리 decision tree 는 랜덤 포레스트의 기본 구성 요소이고, 분류/ 회귀 / 다중 출력 작업까지 가능한 다목적 알고리즘이다.
따라서, 이번 장에서는 결정 트리의 훈련 , 시각화, 예측 방법, 규제, 제약 사항 등을 다루고자 한다.
결정 트리 모델 DecisionTreeClassifier 훈련
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
iris = load_iris(as_frame=True)
X_iris = iris.data[["petal length (cm)", "petal width (cm)"]].values
y_iris= iris.target
tree_clf = DecisionTreeClassifier(max_depth=2, random_state=42)
tre_clf.fit(X_iris, y_iris)
sklearn은 이진 트리만 만드는 CART 알고리즘을 사용함. 따라서, 분할 노드는 항상 두개의 자식 노드를 가짐max_depth 조절을 통해 더 깊은 트리를 만들 수 있음결정 트리 시각화
1) export_graphviz() 를 통해 그래프 정의를 .dot 파일로 추출
from sklearn.tree import export_graphviz
export_graphviz(
tree_clf,
out_file="iris_tree.dot",
feature_names=["꽃잎 길이 (cm)", "꽃잎 너비 (cm)"],
class_names=iris.target_names,
rounded=True, # 박스의 모서리 둥글게 여부
filled=True, # 노드의 색칠 여부
)
2) graphviz.Source.from_file() 통해 시각화
graphviz 는 오픈소스 그래프 시각화 소프트웨어 패키지로 .dot 파일을 pdf나 png 등과 같은 다양한 형식으로 변환하는 도구가 포함되어 있음
from graphviz import Source
Source.from_file("iris_tree.dot")

>>> tree_clf.predict_proba[,15]]).round(3)
array([[0. , 0.907, 0.093]])
>>> tree_clf.predict([[5,1.5]])
array[1]
predict_proba : 각 클래스의 속할 확률을 리스트로 returnpredict : 확률이 가장 높은 클래스를 return루트 노드에서 이진 ( True / False )로 구분하기 위해서는 1. 특성 k 와 2. 특성 k의 임계값을 설정해야함
가장 적합한 k와 임계값을 찾기 위한 CART 비용 함수

최대 깊이가 되거나, 불순도를 줄이는 조합을 찾을 수 없을 때 이 과정을 멈추게 됨
CART는 현재 단계에서 즉시 가장 좋은 분할만 선택하기 때문에 탐욕 알고리즘임
DecisionTreeClassifier 클래스는 기본적으로 지니 불순도 사용결정 트리는 훈련 데이터에 대한 제약사항( ex. 데이터가 선형 )이 거의 없기 때문에 과대적합되기 쉬움
결정트리는 훈련 전 파라미터 수가 결정되지 않으므로 비파라미터 모델 nonparametric model
과대 적합을 피하기 위해 결정 트리의 자유도를 제한 !
scikit_learn에서는 max_depth 로 자유도를 제한
max_depth 를 줄이면 모델을 규제하고 과대적합의 위험을 감소시킴 max_features : 각 노드에서 분할에 사용할 특성의 최대 수
max_leaf_nodes : 리프 노드의 최대 수
min_samples_split : 분할되기 위해 노드가 가져야 하는 최소 샘플 수
min_samples_leaf : 리프 노드가 생성되기 위해 가지고 있어야할 최소 샘플 수
min_weight_fraction_leaf : 기능은 min_samples_leaf와 같지만, 가중치가 부여된 샘플 수에서의 비율을 고려
예시
from sklearn.datasets import make_moons
X_moons, y_moons = make_moons(n_samples=150, noise=0.2, random_state=42)
tree_clf1 = DecisionTreeClassifier(random_state=42)
tree_clf2 = DecisionTreeClassifier(min_samples_leaf=5, random_stat=42)
tree_clf1.fit(X_moons, y_moons)
tree_clf2.fit(X_moons, y_moons)

X_moons_test, y_moons_test = make_moons(n_sampes=1000, noise=0.2, random_state=43)
....
...
>>> tree_clf1.score(X_moons_test, y_moons_test)
0.898
>>> tree_clf2.score(X_moons_test, y_moons_test)
0.92
DecisionTreeRegressorimport numpy as np
from sklearn.tree import DecisionTreeRegressor
np.random.seed(42)
X_quad = np.random.rand(200, 1) - 0.5 # 랜덤한 하나의 입력 특성
y_quad = X_quad ** 2 +0.025 * np.random.randn(200,1)
tree_reg = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg.fit(X_quad, y_quad)



결정 트리는 계단 모양의 결정 경계를 생성하므로, 데이터의 방향에 민감
더 좋은 일반화를 위해서 PCA(주성분분석) 변환을 적용
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
pca_pipeline = make_pipeline(StandardScaler(), PCA())
X_iris_rotated = pca_pipeline.fit_transform(X_iris)
tree_clf_pca = DecisionTreeClassifier(max_depth=2, random_state=42)
tree_clf_pca.fit(X_iris_rotated, y_iris)

random_state 매개변수 설정하지 않는 한 매우 다른 모델이 생성될 수도 있음