[핸즈온 머신러닝] 6강 결정트리 ( Decision tree)

2018. 7. 25. 17:12Python-이론/python-인공지능2

결정 트리



결정트리는 분류, 회귀, 다중 출력도 할 수 있는 만능 머신러닝 알고리즘이다. 그리고 결정트리는 자주 이용하는 RandomForest의 기본 구성요소 중 하나이다. 

6.1 결정 트리 학습과 시각화 

붓꽃 데이터 훈련하기 

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)


처음으로 판단 해주는 것은 꽃잎 길이 두번째로 판단하는 것은 꽃잎 너비를 통해서 판단 해줍니다. 
각 데이터 세트들은 50개의 데이터가 존재하는 것을 알 수 있다. 깊이가 2인 곳에서는 5개와 1개씩 잘못 판단 되는 것을 볼 수 있다. 
보통 위와 같은 코드로 훈련 시켜주면 사진과 같은 트리구조가 만들어진다. 


6.2 예측하기 


위의 사진에서 첫 시작하는 점을 루트 노드라고 합니다. 루트노드는 꽃잎 길이를 기준으로 참이라면 왼쪽 리프 노드(자식 노드를 갖고 있지 않는 노드)로 이동하고 거짓이면 오른쪽 자식노드로 이동합니다. 


각 노드의 samples속성은 얼마나 많은 훈련샘플이 적용되었는지 헤아린 것 입니다. 총 150개의 데이터들중 클래스별로 50개씩 나누어 주어서 훈련시켰다. 그러나 오른쪽 자식노드의 리프들은 정확히 구분이 안된 것을 알 수 있다. 


gini 속성은 각 노드별로 불순도를 나타내는 값이다. 만약에 한 노드의 데이터들이 같은 클래스로 분류되고 있다면 순수하다고 볼 수 있습니다(gini=0). 

1 - 각 클래스별로 0/54의 제곱 - 49/54의 제곱 - 5/54의 제곱으로 표현 할 수 있다. 결국 각 클래스별로 데이터수아 샘플수의 비율의 제곱 빼기로 표현 할 수 있습니다. 


사이킷 런은 이진 트리를 만드는데 CART알고리즘을 사용합니다. 이 알고리즘은 리프 노드외에 모든 노드들은 두개의 자식노드를 가지게 만드는 특징이 있습니다. 


추가 상식?


화이트 박스와 블랙박스 


결정트리는 위에서 알아본 바와 같이 매우 직관적이고 결정방식을 이해하기 쉬웠습니다. 이를 화이트박스 모델이라고 합니다. 

반대로 랜덤 포레스트나 신경망은 블랙박스 모델이라고 합니다. 이 알고리즘들은 성능이 뛰어나고 예측을 만드는 과정을 쉽게 확인할 수 있습니다. 하지만 화이트 박스 모델과 같이 쉽게 예측을 하는 과정을 설명하기 어렵습니다.  


x 선은 꽃잎 길이이고 y선은 꽃잎 넓이이다. 그리고 옵션으로 maxdepth를 2로 쓴다면 꽃잎을 5로 한번 더 분류한다. 



6.3 클래스 확률 추정 


결정 트리는 한개의 데이터가를 이용하여 특정 클래스 a에 속할 확률을 추정할 수 도 있다. 이 샘플에 대한 리프노드를 찾기 위해 트리를 탐색하게 되고 그 노드에 있는 훈련샘플의 비율을 반환하게 됩니다. 


확률 예측하기

tree_clf.predict_proba([[5, 1.5]])
array([[0.        , 0.90740741, 0.09259259]])


가장 높은 확률의 인덱스 값 반환하기 

tree_clf.predict([[5, 1.5]])
array([1])



6.4 CART 훈련 알고리즘 


사이킷 런은 결정트리를 훈련시키기 위해 CART알고리즘을 사용합니다. 이알고리즘 일단 데이터에 기준하여 나누어줄 기준 값을 구합니다(꽃잎 길이    <= 2.45) 이 기준은 우리가 정하는 것이 아니라 알고리즘이 알아서 정해줍니다.  알고리즘은 데이터 구분 기준을 가장 단순하고 순수하게 나눌 수 있는 점을 바탕으로 정합니다. (불순률이 낮으면서 정확히 구분할 수 있는 기준) 이 기준으로 두개로 나누고 또 서브셋들을 두개로 나누고를 반복해서 나눈게 됩니다. 이 과정은 max depth라는 옵션으로 멈추게하거나 불순도를 줄이는 분할을 찾을 수 없을 때 멈추게 됩니다. max depth뿐만 아니라 다른 옵션을 사용해서 멈추게 할 수 도 있습니다. 


6.5 지니 불순도 또는 엔트로피


기본적으로 지니 불순도가 사용되지만 criterion 매개변수를 entropy로 지정해주면 entropy 불순도를 사용할 수 있습니다. 

엔트로피는 분자의 무질서함을 측정하는 것으로 원래 열역학의 개념입니다. 정확히 잘 예측했다면 entropy는 0이 됩니다. 즉 어떤 세트가 한 클래스의 샘플만 담고 있다면 엔트로피가 0이 됩니다. 


지니와 엔트로피 중 어느 것을 사용해야 한다 물어본다면 실제로는 큰차이가 없습니다. 일반적으로는 지니가 속도가 더 빠릅니다. 하지만 지니는 일반적으로 한쪽 가지로 고립시키는 경향이 있는 반면에 엔트로피는 조금 더 균형 잡힌 트리를 만듭니다. 


6.6 규제 매개변수 


결정트리는 일반적으로 데이터에 대한 제약사항이 거의 없습니다. 그러나 제한을 두지 않으면 훈련데이터에 너무 적응하게되서 과대적합 현상이 일어나기 쉽습니다. 그래서 훈련을 시켜줄 때 제약을 걸어주는 편이 좋습니다.  예를 들어 위에서와 같이


max depth: 최대 깊이 설정 

min_samples_split: 분할되기 위해 노드가 가져야하는 최소샘플 수 

min_samples_leaf: 리프 노드가 가지고있어야 하는 최소 샘플 수 

min_weight_fraction_leaf: min_samples_leaf와 비슷하지만 가중치가 부여된 전체 샘플 수에서의 비율 

max_leaf_nodes: 리프 노드의 최대수 

max_features: 각 노드에서 분할에 사용할 특성의 최대 수 


등의 제약을 걸 수 있는 옵션들이 있다. 


No restrictions는 규제가 없는 것이고 오른쪽은 리프노드의 최소 샘플수를 4로 제한하여 과적합을 피한 모습을 볼 수 있다. 왼쪽의 그래프는 특별한 데이터에서는 특이값을 보여주고 있다. 



6.7 회귀 


결정 트리 문제는 회귀문제에도 사용할 수 있습니다. 사이킷런의 DecisionTreeREgressor를 사용해 노이즈가 섞인 회귀트리를 만들어 보겠습니다. 


from sklearn.tree import DecisionTreeRegressor

tree_reg = DecisionTreeRegressor(max_depth=2)
tree_reg.fit(X,Y)


아래와 같이 트리형태로 만들어진다. 분류와 달리 클래스로 나오는 것이 아니라 숫자로 결과가 나오게 된다. 그리고 분류에서는 불순률을 줄이기 위해 파라미터등을 통해서 제약을 줬는데 회귀에서는 mse를 최소로 하기위해서 훈련을 진행하는 점만 빼면 분류와 비슷하게 작동 하는 것 같다. 

 

왼쪽과 달리 오른쪽 그래프가 depth를 더 늘려주어서 더 구체적인 모델임을 확인 할 수 있다. 


규제를 추가한 모델 




규제가 없는 왼쪽의 모델은 과대적합을 만들고 있다. 오른쪽과 같이 규제를 진행해주면 조금 더 그럴싸한 모델이 만들어집니다.



6.8 불안정성 


지금까지 결정트리는 이해하고 해석하기 쉬우며 편하고 여러용도로 사용할 수 있고 성능도 뛰어나다는 것을 알았습니다. 하지만 몇가지 제약상황이 있습니다. 결정트리는 계단모양의 결정경계를 만듭니다. 그래서 훈련세트의 회전에 민감합니다. 데이터가 조금만 회전하게 되도 일반화가 잘못될 떄도 있습니다. 



위의 그래프는 데이터들을 45도 정도 회전한 그래프인데 조금 더 부정확한 모델을 오른쪽과 같이 만들고 있다. 이러한 예시를 봐서 결정트리는  데이터의 회전에 민감함을 볼 수 있다. 


그리고 또다른 문제는 훈련세트가 조금만 변화에도 매우 민감하다는 것 입니다. 

예를 들어서 데이터들 중 하나의 라벨을 없애서 테스트 해보면 이전의 모델 모습과는 전혀 다르게 생겼다. 




이러한 문제점들은 랜덤 포레스트에서 많은 트리에서 만든 예측을 평균하고 이런 불안정성을 극복합니다.