DecisionTreeCrlassifier
을 훈련시키는 코드다.from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X = iris.data[:, 2:] # 꽃잎의 길이와 너비
y = iris.target
tree_clf = DecisionTreeClassifier(max_depth = 2)
tree_clf.fit(X,y)
import os
from sklearn.tree import export_graphviz
export_graphviz(
tree_clf,
out_file = os.path.join("iris_tree.dot"), # image-path -> os.path.join
feature_names = iris.feature_names[2:],
class_names = iris.target_names,
rounded = True,
filled = True
)
from graphviz import Source
Source.from_file(os.path.join("iris_tree.dot"))
# sample 속성: 얼마나 많은 훈련 샘플이 적용되었는지 헤아린 것이다.
# 리프 노드의 gini 속성: 불순도를 측정한다. (깊이 1인 왼쪽 노드는 Iris-setosa훈련 샘플만 가지고 있으므로 순수 노드이고 gini점수가 0이다. 깊이 2의 왼쪽 노드는 1-(0/54)**2 - (49/50**2 - (..)))
tree_clf.predict_proba([[5,1.5]]) # [길이, 너비]
>>> array([[0. , 0.90740741, 0.09259259]])
tree_clf.predict([[5,1.5]])
>>> array([1])
import numpy as np
np.random.seed(42)
m = 200
X = np.random.rand(m, 1)
y = 4 * (X - 0.5) ** 2
y = y + np.random.randn(m, 1) / 10
from sklearn.tree import DecisionTreeRegressor
tree_reg = DecisionTreeRegressor(max_depth = 2, random_state = 42)
tree_reg.fit(X, y)
export_graphviz(
tree_reg,
out_file = os.path.join("regression_tree.dot"),
feature_names = ["x1"],
rounded = True,
filled = True
)
Source.from_file(os.path.join("regression_tree.dot"))
타깃 하나로만 이뤄진 리프 노드
를 순수 노드pure node
라고 한다.
새로운 데이터 포인트에 대한 예측은 주어진 데이터 포인트가 특성을 분할한 영역들 중 어디에 놓이는지를 확인하면 된다.
그래서 그 영역의 타깃값 중 다수(순수 노드라면 하나)인 것을 예측 결과로 한다. 루트 노드에서 시작해 테스트의 결과에 따라 왼쪽 또는 오른쪽으로 트리를 탐색해나가는 식으로 영역을 찾을 수 있다.
같은 방법으로 회귀 문제에도 트리를 사용할 수 있다. 예측을 하려면 각 노드의 테스트 결과에 따라 트리를 탐색해나가고 새로운 데이터 포인트에 해당되는 리프 노드
를 찾는다. 찾은 리프 노드
의 훈련 데이터 평균 값이 이 데이터 포인트의 출력이 된다.
일반적으로 트리 만들기를 모든 리프 노드가 순수 노드가 될 때까지 진행하면 모델이 매우 복잡해지고 훈련 데이터에 과대적합된다. ➡️ 즉, 정확도
가 100이 된다.➡️ 즉 훈련 세트의 모든 데이터 포인트는 정확한 클래스의 리프 노드에 있습니다.
위의 그림에서 오른쪽 그래프를 보면 과대적합된 것으로 볼 수 있다.
결정 경계가 클래스의 포인트들에서 멀리 떨어진 이상치 outlier 하나에 너무 민감하다.
사전 가지치기
사후 가지치기
scikit-learn
에서 결정 트리는 DecisionTreeRegressor
와 DecisionTreeClassifier
에 구현되어 있습니다. scikit-learn
은 사전 가지치기만 지원한다.
모든 리프 노드가 순수 노드이므로 훈련 세트의 정확도는 100%입니다.
테스트 세트의 정확도는 이전에 본 선형 모델에서의 정확도인 95%보다 조금 낮다.
훈련 세트의 정확도는 당연히 1이 되고, 테스트 세트의 정확도는 93퍼센트가 된다.
"일정 깊이에 도달하면 트리의 성장을 멈추게 하는 것"
Logistic Regression
SVM
Decision Tree
이때까지 배웠던 SVM
, Logistic Regression
, Decision Tree
은 분류문제에 쓰이는 알고리즘이었다.
이것들이 그런데 각각 다른 용도로 하나씩 쓰이는지 의문점을 갖게 되었다.
각각의 알고리즘은 따로 쓰일 수도 있겠지만, 역시 각자 장단점이 존재하기 때문에 서로 보완해주기 위해서 같이 혼합하여 쓰이는 경우가 많았다.
Bagging(자루넣기)
: 똑같은 일을 여러개 시키고 나서, 잘되는 점수만 뽑아간다.
Stacking(쌓기)
: 하나를 실행시켜서 나온 결과를 모아서 다른 곳에 또 넣어서 결과를 본다.
Boosting(밀어주기)
: 다른데서 정보를 살짝 받아서 진행한다.
앙상블된 실제 사례가 궁금해서 찾아보았다.
SVM
과 Decision Tree
를 이용한 혼합형 침입탐지 모델에 관한 논문을 찾게 되었다.
SVM
은 이산형 데이터를 이용하지 못하기에 Decision Tree
로 이를 보완하였다고 한다. 이를 통해 확연히 탐지율이 향상되었음을 확인할 수 있었다고 한다.
스터디에서 그런데 저 마지막 자료 화면에 "향후로는 ~~~ 연구가 필요하다." 파트에서 한 스터디원이 내가 미처 생각하지 못했던 점을 지적해주셨다.
이 논문이 나온 시기는 2007년으로 상당히 오래된 시점이었다. 그리고 뒤에 이어지는 논문을 보니 최근의 논문도 존재했으며 이것 역시 SVM
와 Decision Tree
를 앙상블하여 사용하였다.
라는 의문점이다.
이에 관해서는 다음 Chapter7에서 앙상블 방법을 다루고 있는데 그때 더 자세하게 정리하도록 하겠다!