상세 컨텐츠

본문 제목

[머신러닝 커닝 페이퍼] 분류를 위한 결정트리의 모든 것 2편

프로그래밍/Data&ML

by 척척석사 민준 2022. 12. 15. 00:15

본문

728x90

2022.12.01 - [자연과학도를 위한 프로그래밍 (Python+MATLAB)/머신러닝과 데이터분석 (Python)] - [머신러닝 커닝 페이퍼] 분류를 위한 결정트리모델의 모든 것 1편

 

[머신러닝 커닝 페이퍼] 분류를 위한 결정트리모델의 모든 것 1편

from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 학습데이터와 테스트데이터 나눠준다 X_train, X_test, y_train, y_test = train_test_split(data, l

super-master.tistory.com

 

1편의 내용을 요약하자면 결정트리 모델의 장점은 설명가능하다는 점이고 시각화를 통해 알고리즘이 어떻게 흘러가는지를 알 수 있다는 점이었다.

단점은 과대적합이 되기 쉽다는 점이었다.

 

과대적합을 막기 위해 사전 가지치기와 사후가지치기를 할 수 있는데 이를 자세히 알아보자

 

사전가지치기는 두개면 충분하다.

# max_depth와 min_samples_split만 적절히 설정해도 사전가지치기효과로 성능이 좋아진다
dt_clf = DecisionTreeClassifier(random_state=0, max_depth = 3 ,min_samples_split=4)
dt_clf.fit(X_train, y_train)
dt_pred = dt_clf.predict(X_test)

 

- max_depth : 트리의 최대 깊이를 규정해준다.

가지를 어디까지 뻗을꺼야? 이런 질문이 될 수 있다. 데이터의 관점에서 볼 때 데이터의 불순도를 어디까지 봐줄껀지 정해준다.(CART 알고리즘은 데이터의 불순도를 기준으로 분류를 한다)

 

max_depth를 적용하기 전(좌)과 후(우)
max_depth를 적용하기 전(좌)과 후(우)

- min_samples_split : 노드 분할을 위한 최소한의 데이터 수

작을수록 과적합이 된다. (1이면 오차 데이터 하나만으로도 가지가 생기게 된다. 기본값은 2)

학습데이터 크기에 따라 달라질 수도 있는데, 학습데이터 자체가 너무 작으면 어쩔 수 없지만, 어느정도 데이터양이 보장이 된다면 min_samples_split는 클 수록 과적합을 막고 이상치에 의한 과적합을 방지할 수 있다.

정수와 실수를 지원하는데 min_sample_split이 실수일 경우는(ex. min_sample_spilit = 0.01) min_sample_split * 전체 샘플 갯수를 반올림한 값이 노드분할을 위한 최소한의 데이터 셋이 된다.

 

min_sample_split를 적용하기 전(기본값 2, 좌)과 후(4로 설정, 우)
min_sample_split를 적용하기 전(기본값 2, 좌)과 후(4로 설정, 우)

 

사후 가지치기를 위한 파라미터는 아직 ccp_alpha만 지원한다.

# 사후가지치기로 ccp_alpha를 설정해줄 수 있다. 
# 사전가지치기 파라미터를 설정하고 사후가지치기를 진핼 할 수도 있다

dt_clf = DecisionTreeClassifier(random_state=0,  ccp_alpha = 0.035)
dt_clf.fit(X_train, y_train)
dt_pred = dt_clf.predict(X_test)

- ccp_alpha 매개변수 :Minimal Cost-Complexity Pruning(오버피팅을 막기 위한 가지치기 알고리즘)를 위한 매개변수이다. 

모델이 이미 만들어지고 난 뒤에 가지치기를 진행하여 과적합을 막을 수 있다. 결정트리의 성능을 끝까지 쥐어짤 때 사용할 수 있다.

alpha 값이 커질 수록 가지치기를 심하게? 진행하여 너무 크면 과소적합이 되어버린다.

 

 

적절한 ccp_alpha값을 구하는 방법

path = dt_clf.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas, impurities = path.ccp_alphas, path.impurities

clfs = []
for ccp_alpha in ccp_alphas:
    clf = DecisionTreeClassifier(random_state=0, ccp_alpha=ccp_alpha)
    clf.fit(X_train, y_train)
    clfs.append(clf)
print(
    "Number of nodes in the last tree is: {} with ccp_alpha: {}".format(
        clfs[-1].tree_.node_count, ccp_alphas[-1]
    )
)

train_scores = [clf.score(X_train, y_train) for clf in clfs]
test_scores = [clf.score(X_test, y_test) for clf in clfs]

fig, ax = plt.subplots()
ax.set_xlabel("alpha")
ax.set_ylabel("accuracy")
ax.set_title("Accuracy vs alpha for training and testing sets")
ax.plot(ccp_alphas, train_scores, marker="o", label="train", drawstyle="steps-post")
ax.plot(ccp_alphas, test_scores, marker="o", label="test", drawstyle="steps-post")
ax.legend()

코드는 sklearn 공식홈페이지 예제를 따왔다.

ccp에 따른 학습결과를 clfs에 저장하고 이를 시각화한다.

학습데이터의 accuracy가 최소로 떨어지면서 테스트데이터의 accuracy가 최대로 늘어나는 ccp_alpha값은 0.035 ~ 0.045 사이로 확인된다.

 

사전가지치기와 사후가지치기를 적용해 학습을 진행해보자

 

파라미터를 최적화를 통해 약간의 성능상승을 확인 할 수 있다.

정확도 : 80.0% -> 83.3%
정밀도 : 77.2% -> 80.7%
재현율 : 79.0% -> 81.3%

이 파라미터는 결정트리를 기반으로 하는 다른 알고리즘에도 동일하게 적용할 수 있다.

다른 앙상블 모델에 적용하여 성능을 쥐어짜보자.

728x90

관련글 더보기