훈련 데이터 세트를 하나의 특성 k와 그에 해당하는 임계값 t를 기준으로 두개의 subset으로 나눈다. CART함수의 비용함수는 두개의 subset의 불순도의 가중평균으로 모든 가능한 (k, t)들중 이 비용함수를 최소화할 수 있는 (k, t)를 찾으면 된다.
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
iris=load_iris()
iris.feature_names
['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']
iris.target_names
array(['setosa', 'versicolor', 'virginica'], dtype='<U10')
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=1)
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
model1 = DecisionTreeClassifier(criterion="entropy", max_depth=None, )
model1.fit(x_train, y_train)
DecisionTreeClassifier(criterion='entropy')
plt.figure(figsize=(12, 12))
plot_tree(decision_tree=model1, feature_names=iris.feature_names, class_names=iris.target_names, filled=True)
plt.show()
아래는 randomstate=2인 train data와 test data를 같은 비율이지만 다르게 나눈 동일한코드이다.
아래의 도식화된 그림을 보면 학습데이터에 변동이 최종결과에 큰 영향을 주는것을 알 수 있다.
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=2)
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
model2 = DecisionTreeClassifier(criterion="entropy", max_depth=None) #깊이를 제안하는 파라미터 : max_depth
model2.fit(x_train, y_train)
plt.figure(figsize=(12, 12))
plot_tree(decision_tree=model2, feature_names=iris.feature_names, class_names=iris.target_names, filled=True)
plt.show()
Decision Tree Clasifier의 max_depth의 조정으로 1 ~ max일때까지 test error를 통해 test error가 가장적은 노드를 기준으로 Prunning을 진행하였다.
max_depths = [depth+1 for depth in range(int(model1.get_depth()))]
max_depths
[1, 2, 3, 4, 5]
train_error = []
test_error = []
for depth in max_depths:
model = DecisionTreeClassifier(max_depth=depth)
model.fit(x_train, y_train)
target_train_predict = model.predict(x_train)
target_test_predict = model.predict(x_test)
acc_train = accuracy_score(y_train, target_train_predict)
acc_test = accuracy_score(y_test, target_test_predict)
train_error.append(1-acc_train)
test_error.append(1-acc_test)
plt.plot(max_depths, train_error, color="red")
plt.plot(max_depths, test_error, color="blue")
plt.show()
{: width="60%" height="60%"}
위의 graph를 통해 파란색 test error을 보면 depth가 3일때 Prunning을 해야하는것을 알 수 있다.
model_f = DecisionTreeClassifier(criterion="entropy", max_depth=3)
model_f.fit(x_train, y_train)
DecisionTreeClassifier(criterion='entropy', max_depth=3)
plt.figure(figsize=(12, 12))
plot_tree(decision_tree=model_f, feature_names=iris.feature_names, class_names=iris.target_names, filled=True)
plt.show()
위의 Decision Tree가 Pruning을 끝낸 최종 결과이다.
import numpy as np
new_data = np.array([[0.23, -0.87, 0.13, 0.9]])
print(model_f.predict_proba(new_data))
print(model_f.predict(new_data))
[[0. 0.25 0.75]]
[2]