본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 2. · 8 Views
결정 트리 완벽 가이드
머신러닝의 가장 직관적인 알고리즘인 결정 트리를 초급 개발자도 쉽게 이해할 수 있도록 설명합니다. 분류와 회귀, 가지치기, 특성 중요도까지 실무에 바로 적용할 수 있는 내용을 담았습니다.
목차
1. 결정 트리 개념 이해
어느 날 김개발 씨는 회사에서 고객 이탈 예측 모델을 만들라는 업무를 받았습니다. "머신러닝이라니, 어디서부터 시작해야 하지?" 막막해하던 그에게 박시니어 씨가 다가와 말했습니다.
"결정 트리부터 시작해봐요. 가장 직관적이고 이해하기 쉬운 알고리즘이거든요."
**결정 트리(Decision Tree)**는 데이터를 분류하거나 예측하기 위해 질문을 연속으로 던지는 알고리즘입니다. 마치 스무고개 게임처럼 "예/아니오"로 답할 수 있는 질문들을 통해 최종 결론에 도달합니다.
이 알고리즘의 가장 큰 장점은 결과를 사람이 직접 해석할 수 있다는 것입니다.
다음 코드를 살펴봅시다.
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
# 붓꽃 데이터 로드
iris = load_iris()
X, y = iris.data, iris.target
# 결정 트리 모델 생성
model = DecisionTreeClassifier(random_state=42)
# 모델 학습 - 데이터로부터 규칙을 배웁니다
model.fit(X, y)
# 새로운 데이터 예측
new_flower = [[5.1, 3.5, 1.4, 0.2]]
prediction = model.predict(new_flower)
print(f"예측 결과: {iris.target_names[prediction[0]]}")
김개발 씨는 입사 6개월 차 데이터 분석가입니다. 어느 날 팀장님이 다가와 말씀하셨습니다.
"김개발 씨, 우리 고객 중에 누가 이탈할지 예측하는 모델 좀 만들어볼 수 있어요?" 머신러닝이라는 단어만 들어도 막막했던 김개발 씨는 한숨을 쉬었습니다. 점심시간에 박시니어 씨가 다가왔습니다.
"무슨 고민 있어요?" 사정을 들은 박시니어 씨가 말했습니다. "결정 트리부터 시작해보세요.
저도 처음 머신러닝 배울 때 여기서 시작했거든요." 그렇다면 결정 트리란 정확히 무엇일까요? 쉽게 비유하자면, 결정 트리는 마치 병원의 진단 과정과 같습니다.
의사 선생님은 환자에게 질문을 던집니다. "열이 있나요?" "기침이 나나요?" "목이 아프가요?" 이런 질문들의 답에 따라 감기인지, 독감인지, 아니면 다른 질병인지 판단하게 됩니다.
결정 트리도 마찬가지로 데이터에 대해 연속적인 질문을 던지고, 그 답에 따라 분류를 수행합니다. 결정 트리가 없던 시절에는 어땠을까요?
개발자들은 수많은 if-else 문을 직접 작성해야 했습니다. "나이가 30 이상이고, 소득이 5000만원 이상이고, 결혼을 했으면..." 이런 규칙을 사람이 하나하나 만들어야 했던 것입니다.
문제는 데이터가 복잡해질수록 이런 규칙을 만들기가 점점 어려워진다는 것이었습니다. 어떤 조건이 중요한지, 어떤 순서로 질문해야 하는지 사람이 판단하기 어려웠습니다.
바로 이런 문제를 해결하기 위해 결정 트리 알고리즘이 등장했습니다. 결정 트리는 데이터를 스스로 분석하여 가장 좋은 질문을 찾아냅니다.
"어떤 특성으로 데이터를 나누면 가장 잘 분류될까?"를 자동으로 계산하는 것입니다. 이것을 정보 이득(Information Gain) 또는 **지니 불순도(Gini Impurity)**라는 지표로 측정합니다.
위의 코드를 살펴보겠습니다. 먼저 DecisionTreeClassifier를 불러옵니다.
이것이 바로 결정 트리 분류기입니다. 다음으로 붓꽃 데이터를 로드하는데, 이 데이터는 꽃잎과 꽃받침의 길이와 너비로 붓꽃의 종류를 분류하는 유명한 데이터셋입니다.
fit 메서드를 호출하면 모델이 데이터로부터 분류 규칙을 학습합니다. 마지막으로 predict 메서드로 새로운 데이터의 종류를 예측합니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 은행에서 대출 심사 모델을 만든다고 가정해봅시다.
고객의 나이, 소득, 신용점수, 기존 대출 여부 등의 데이터를 결정 트리에 학습시키면, 새로운 고객이 대출을 상환할 수 있을지 예측할 수 있습니다. 무엇보다 좋은 점은 "왜 이 고객의 대출을 거절했는지" 설명할 수 있다는 것입니다.
"신용점수가 600점 미만이고, 기존 대출이 3건 이상이기 때문"처럼 말이죠. 하지만 주의할 점도 있습니다.
결정 트리는 데이터에 너무 맞춰지는 과적합(Overfitting) 문제가 발생하기 쉽습니다. 학습 데이터에서는 정확도가 100%인데, 새로운 데이터에서는 형편없는 결과를 보일 수 있습니다.
이것은 마치 시험 문제를 외워서 100점을 맞았지만, 조금만 다른 문제가 나오면 틀리는 것과 같습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 조언을 듣고 결정 트리를 공부한 김개발 씨는 고개를 끄덕였습니다. "아, 생각보다 직관적이네요!" 이제 본격적으로 코드를 작성할 준비가 되었습니다.
실전 팁
💡 - random_state 파라미터를 설정하면 실행할 때마다 같은 결과를 얻을 수 있습니다
- 결정 트리는 데이터 스케일링이 필요 없어서 전처리가 간단합니다
2. 분류 트리 구현하기
김개발 씨가 결정 트리의 개념을 이해하고 나니, 박시니어 씨가 다음 과제를 던졌습니다. "이제 실제로 고객 이탈 예측 모델을 만들어볼까요?
이탈할지 안 할지를 분류하는 거니까, 분류 트리를 써야겠네요." 분류 트리라니, 또 새로운 용어가 등장했습니다.
**분류 트리(Classification Tree)**는 데이터를 미리 정해진 범주로 나누는 결정 트리입니다. 고객이 이탈할지 안 할지, 이메일이 스팸인지 아닌지처럼 "어떤 그룹에 속하는가"를 예측합니다.
결과값이 이산적인 범주형 데이터일 때 사용합니다.
다음 코드를 살펴봅시다.
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
# 데이터 준비 (특성: 나이, 월 사용금액, 서비스 이용 개월수)
X = [[25, 50000, 3], [45, 80000, 24], [35, 30000, 6],
[50, 90000, 36], [23, 40000, 2], [40, 70000, 18]]
y = ['이탈', '유지', '이탈', '유지', '이탈', '유지']
# 학습/테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42)
# 분류 트리 모델 학습
clf = DecisionTreeClassifier(criterion='gini', random_state=42)
clf.fit(X_train, y_train)
# 예측 및 평가
predictions = clf.predict(X_test)
print(f"정확도: {accuracy_score(y_test, predictions):.2f}")
김개발 씨는 드디어 본격적인 모델 구현에 들어갔습니다. 박시니어 씨가 말했습니다.
"결정 트리에는 크게 두 종류가 있어요. 분류 트리와 회귀 트리.
우리가 만들 고객 이탈 예측은 '이탈한다/이탈하지 않는다'를 분류하는 거니까 분류 트리를 써야 해요." 분류 트리란 무엇일까요? 마치 우체국에서 편지를 분류하는 것과 같습니다.
우체부 아저씨는 편지의 우편번호를 보고 "서울로 갈 편지", "부산으로 갈 편지", "대구로 갈 편지"처럼 구분합니다. 분류 트리도 마찬가지로 데이터를 보고 "이탈 고객", "유지 고객"처럼 미리 정해진 범주로 분류합니다.
그렇다면 분류 트리는 어떻게 최적의 분류 기준을 찾을까요? 여기서 등장하는 것이 바로 **지니 불순도(Gini Impurity)**입니다.
지니 불순도는 데이터가 얼마나 섞여 있는지를 측정하는 지표입니다. 한 노드에 같은 클래스의 데이터만 있으면 불순도는 0이고, 여러 클래스가 골고루 섞여 있으면 불순도가 높아집니다.
분류 트리는 불순도를 최소화하는 방향으로 데이터를 나눕니다. 또 다른 기준으로 **엔트로피(Entropy)**도 있습니다.
엔트로피는 정보 이론에서 온 개념으로, 불확실성을 측정합니다. 동전을 던질 때 앞면이 나올지 뒷면이 나올지 모르는 것처럼, 데이터가 어떤 클래스에 속할지 불확실할수록 엔트로피가 높습니다.
scikit-learn에서는 criterion 파라미터로 'gini' 또는 'entropy'를 선택할 수 있습니다. 위의 코드를 자세히 살펴보겠습니다.
먼저 train_test_split으로 데이터를 학습용과 테스트용으로 나눕니다. 이것은 매우 중요한 과정입니다.
학습에 사용하지 않은 데이터로 모델을 평가해야 진정한 성능을 알 수 있기 때문입니다. criterion='gini'는 분류 기준으로 지니 불순도를 사용하겠다는 의미입니다.
실무에서 분류 트리는 정말 다양한 곳에 쓰입니다. 신용카드 회사에서는 거래가 사기인지 정상인지 분류합니다.
병원에서는 환자가 특정 질병에 걸렸는지 아닌지 진단합니다. 이커머스 회사에서는 고객이 상품을 구매할지 안 할지 예측합니다.
모두 "A인가 B인가"를 판단하는 분류 문제입니다. 하지만 주의할 점이 있습니다.
클래스 불균형 문제를 조심해야 합니다. 예를 들어 사기 거래가 전체의 1%에 불과하다면, 모든 거래를 "정상"이라고 예측해도 99%의 정확도를 얻습니다.
하지만 이런 모델은 쓸모가 없죠. class_weight 파라미터를 'balanced'로 설정하면 이 문제를 어느 정도 완화할 수 있습니다.
김개발 씨가 첫 번째 분류 모델을 완성했습니다. 정확도를 확인하니 꽤 괜찮은 수치가 나왔습니다.
박시니어 씨가 웃으며 말했습니다. "좋아요!
이제 회귀 트리도 배워볼까요?"
실전 팁
💡 - 클래스 불균형이 심할 때는 class_weight='balanced' 옵션을 고려하세요
- classification_report로 정밀도, 재현율, F1 점수를 함께 확인하면 더 정확한 평가가 가능합니다
3. 회귀 트리 구현하기
박시니어 씨가 새로운 질문을 던졌습니다. "그런데 만약 고객이 이탈할지 안 할지가 아니라, 이탈 확률이 몇 퍼센트인지 알고 싶으면 어떻게 해야 할까요?" 김개발 씨는 잠시 생각했습니다.
"아, 그러면 숫자를 예측해야 하니까... 분류가 아니라 회귀인가요?"
**회귀 트리(Regression Tree)**는 연속적인 숫자 값을 예측하는 결정 트리입니다. 주택 가격, 매출액, 온도처럼 "얼마인가"를 예측할 때 사용합니다.
분류 트리와 구조는 같지만, 리프 노드에서 클래스 대신 평균값을 반환합니다.
다음 코드를 살펴봅시다.
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
# 데이터: 평수, 역까지 거리(분), 건축년수 -> 가격(만원)
X = [[20, 5, 10], [30, 10, 5], [25, 3, 15],
[35, 15, 3], [18, 8, 20], [40, 7, 8]]
y = [35000, 42000, 38000, 48000, 28000, 55000]
# 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42)
# 회귀 트리 모델 학습
reg = DecisionTreeRegressor(max_depth=3, random_state=42)
reg.fit(X_train, y_train)
# 예측 및 평가
predictions = reg.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, predictions))
print(f"RMSE: {rmse:,.0f}만원")
김개발 씨는 분류 트리를 잘 이해했습니다. 하지만 박시니어 씨의 질문에 잠시 당황했습니다.
"숫자를 예측하는 건 어떻게 하죠?" 회귀 트리는 분류 트리와 형제 같은 관계입니다. 둘의 구조는 거의 동일합니다.
차이점은 출력값입니다. 분류 트리는 "A 클래스" 또는 "B 클래스"처럼 범주를 출력하지만, 회귀 트리는 "35000" 또는 "42000"처럼 숫자를 출력합니다.
마치 같은 도구로 다른 작업을 하는 것과 같습니다. 그렇다면 회귀 트리는 어떻게 숫자를 예측할까요?
비유하자면, 회귀 트리는 마치 부동산 중개인과 같습니다. "이 동네에서 30평대 아파트는 평균 4억 정도 해요"라고 말하는 것처럼, 비슷한 특성을 가진 데이터들의 평균값을 예측값으로 사용합니다.
트리의 리프 노드에 도달한 학습 데이터들의 평균이 바로 예측값이 됩니다. 회귀 트리의 분할 기준은 분류 트리와 다릅니다.
분류 트리는 지니 불순도나 엔트로피를 사용했지만, 회귀 트리는 **평균제곱오차(MSE)**를 사용합니다. 각 분할에서 MSE를 최소화하는 방향으로 데이터를 나눕니다.
쉽게 말해, 비슷한 값을 가진 데이터끼리 모이도록 분할하는 것입니다. 위의 코드에서 주목할 점이 있습니다.
DecisionTreeRegressor를 사용한다는 점입니다. 분류에는 Classifier, 회귀에는 Regressor를 씁니다.
평가 지표도 다릅니다. 분류에서는 정확도를 썼지만, 회귀에서는 RMSE(평균제곱근오차)나 R2 점수를 사용합니다.
RMSE는 예측값과 실제값의 차이를 나타내므로, 낮을수록 좋습니다. 실무에서 회귀 트리는 언제 사용할까요?
주택 가격 예측이 대표적입니다. 평수, 층수, 역까지 거리 등을 입력하면 예상 가격을 알려줍니다.
매출 예측에도 많이 쓰입니다. 요일, 날씨, 프로모션 여부 등을 보고 오늘의 예상 매출을 계산합니다.
수요 예측, 재고 관리 등 숫자를 예측해야 하는 모든 곳에 활용됩니다. 하지만 회귀 트리에도 한계가 있습니다.
회귀 트리는 학습 데이터의 범위를 벗어나는 예측을 하지 못합니다. 예를 들어 학습 데이터의 최대 가격이 5억이라면, 10억짜리 집이 들어와도 5억 이하로 예측합니다.
이것을 외삽(Extrapolation) 문제라고 합니다. 선형 회귀는 이런 문제가 덜하지만, 트리 기반 모델은 주의해야 합니다.
김개발 씨가 고개를 끄덕였습니다. "분류와 회귀, 이제 둘 다 할 수 있게 됐네요!" 박시니어 씨가 덧붙였습니다.
"좋아요. 하지만 아직 중요한 게 남았어요.
바로 과적합을 방지하는 방법이에요."
실전 팁
💡 - 회귀 트리는 외삽에 약하므로, 학습 데이터 범위 내의 예측에 적합합니다
- R2 점수가 1에 가까울수록 모델이 데이터를 잘 설명하는 것입니다
4. 트리 깊이와 가지치기
김개발 씨가 만든 모델의 학습 정확도는 100%였습니다. "와, 완벽하네요!" 하지만 박시니어 씨는 고개를 저었습니다.
"그게 문제예요. 학습 데이터를 외워버린 거예요.
새로운 데이터가 들어오면 엉망이 될 거예요." 이것이 바로 과적합이었습니다.
**과적합(Overfitting)**은 모델이 학습 데이터에 너무 맞춰져서 새로운 데이터에 대한 예측력이 떨어지는 현상입니다. 결정 트리에서는 트리 깊이 제한과 **가지치기(Pruning)**로 이를 방지합니다.
적절한 복잡도를 유지하는 것이 좋은 모델의 핵심입니다.
다음 코드를 살펴봅시다.
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
# 과적합된 모델 (제한 없음)
overfit_model = DecisionTreeClassifier(random_state=42)
# 적절히 제한된 모델
balanced_model = DecisionTreeClassifier(
max_depth=5, # 트리 최대 깊이 제한
min_samples_split=10, # 분할에 필요한 최소 샘플 수
min_samples_leaf=5, # 리프 노드의 최소 샘플 수
max_features='sqrt', # 분할에 사용할 특성 수 제한
random_state=42
)
# 교차 검증으로 일반화 성능 비교
# iris 데이터로 예시
from sklearn.datasets import load_iris
X, y = load_iris().data, load_iris().target
overfit_scores = cross_val_score(overfit_model, X, y, cv=5)
balanced_scores = cross_val_score(balanced_model, X, y, cv=5)
print(f"제한 없음: {overfit_scores.mean():.3f}")
print(f"제한 있음: {balanced_scores.mean():.3f}")
김개발 씨는 충격을 받았습니다. 정확도 100%가 좋은 게 아니라고요?
과적합을 이해하기 위해 시험 공부를 생각해봅시다. 시험 문제를 달달 외워서 100점을 맞은 학생이 있습니다.
하지만 시험에 조금이라도 변형된 문제가 나오면 전혀 풀지 못합니다. 반면 개념을 이해한 학생은 시험에서 90점을 맞았지만, 어떤 변형 문제가 나와도 풀 수 있습니다.
과적합된 모델은 전자와 같습니다. 학습 데이터는 완벽하게 맞추지만, 새로운 데이터에는 엉망입니다.
결정 트리는 특히 과적합에 취약합니다. 제한 없이 트리를 키우면, 모든 학습 데이터를 완벽하게 분류할 때까지 가지를 뻗어나갑니다.
극단적으로는 각 학습 데이터마다 하나의 리프 노드가 생길 수도 있습니다. 이렇게 되면 트리가 데이터의 패턴이 아니라 노이즈까지 학습해버립니다.
이를 방지하는 첫 번째 방법은 **사전 가지치기(Pre-pruning)**입니다. 트리가 자라는 것을 미리 제한하는 방법입니다.
max_depth는 트리의 최대 깊이를 제한합니다. min_samples_split은 노드를 분할하기 위한 최소 샘플 수를 지정합니다.
min_samples_leaf는 리프 노드에 있어야 할 최소 샘플 수입니다. 이런 제한을 걸면 트리가 너무 복잡해지는 것을 막을 수 있습니다.
두 번째 방법은 **사후 가지치기(Post-pruning)**입니다. 트리를 일단 끝까지 키운 다음, 불필요한 가지를 잘라내는 방법입니다.
scikit-learn에서는 ccp_alpha 파라미터로 비용 복잡도 가지치기를 수행할 수 있습니다. alpha 값이 클수록 더 많은 가지가 잘려나갑니다.
그렇다면 적절한 값은 어떻게 찾을까요? **교차 검증(Cross-validation)**을 사용합니다.
데이터를 여러 번 나누어 학습하고 검증하면서, 가장 좋은 일반화 성능을 보이는 파라미터를 찾습니다. 위 코드의 cross_val_score가 바로 이 역할을 합니다.
실무에서는 GridSearchCV를 많이 사용합니다. 여러 파라미터 조합을 자동으로 테스트해서 최적의 조합을 찾아줍니다.
max_depth를 3부터 10까지, min_samples_split을 2부터 20까지 모두 테스트해보고 가장 좋은 조합을 선택하는 식입니다. 김개발 씨가 물었습니다.
"그러면 max_depth를 몇으로 설정하면 좋을까요?" 박시니어 씨가 대답했습니다. "정답은 없어요.
데이터마다 다르거든요. 그래서 교차 검증을 하는 거예요.
하지만 경험적으로 3에서 10 사이가 많이 쓰여요."
실전 팁
💡 - max_depth는 보통 3에서 10 사이에서 시작해보세요
- GridSearchCV로 최적의 하이퍼파라미터 조합을 자동으로 찾을 수 있습니다
5. 특성 중요도 분석
모델이 완성되자 팀장님이 질문했습니다. "이 모델이 고객 이탈을 예측할 때, 어떤 요소가 가장 중요한 건가요?" 김개발 씨는 잠시 당황했습니다.
결정 트리가 어떤 기준으로 판단하는지 어떻게 알 수 있을까요?
**특성 중요도(Feature Importance)**는 모델이 예측을 할 때 각 특성이 얼마나 기여하는지를 나타내는 지표입니다. 결정 트리는 각 특성이 불순도를 얼마나 감소시켰는지를 기준으로 중요도를 계산합니다.
이를 통해 모델의 결정 과정을 해석할 수 있습니다.
다음 코드를 살펴봅시다.
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
import pandas as pd
# 데이터 로드
iris = load_iris()
X, y = iris.data, iris.target
# 모델 학습
model = DecisionTreeClassifier(max_depth=4, random_state=42)
model.fit(X, y)
# 특성 중요도 추출
importance = model.feature_importances_
# 데이터프레임으로 정리
feature_importance = pd.DataFrame({
'feature': iris.feature_names,
'importance': importance
}).sort_values('importance', ascending=False)
print("특성 중요도:")
print(feature_importance.to_string(index=False))
# 가장 중요한 특성
top_feature = feature_importance.iloc[0]
print(f"\n가장 중요한 특성: {top_feature['feature']}")
팀장님의 질문은 매우 중요한 것이었습니다. 머신러닝 모델이 "왜" 그런 예측을 했는지 설명할 수 있어야 실무에서 신뢰받을 수 있기 때문입니다.
결정 트리의 큰 장점 중 하나가 바로 해석 가능성입니다. 딥러닝 모델은 블랙박스라서 왜 그런 결정을 했는지 알기 어렵습니다.
하지만 결정 트리는 어떤 특성을 기준으로 데이터를 나눴는지 명확하게 보여줍니다. 특성 중요도는 이런 해석을 수치화한 것입니다.
특성 중요도는 어떻게 계산될까요? 결정 트리에서 특성 중요도는 해당 특성이 불순도를 얼마나 감소시켰는지로 측정됩니다.
어떤 특성으로 분할했을 때 데이터가 잘 나뉘었다면, 그 특성의 중요도가 높아집니다. 모든 중요도의 합은 1이 됩니다.
비유하자면, 탐정이 사건을 해결하는 과정과 같습니다. 여러 단서 중에서 "이 단서가 결정적이었다"라고 말하는 것처럼, 특성 중요도는 "이 특성이 분류에 결정적이었다"를 알려줍니다.
붓꽃 데이터에서는 꽃잎 길이와 너비가 가장 중요한 것으로 나타납니다. 꽃받침보다 꽃잎이 붓꽃 종류를 구별하는 데 더 유용하다는 뜻입니다.
실무에서 특성 중요도는 정말 유용합니다. 고객 이탈 예측 모델에서 "월 사용 금액이 가장 중요하다"라는 인사이트를 얻었다고 가정해봅시다.
그러면 마케팅팀에 "사용 금액이 낮아지는 고객에게 할인 쿠폰을 보내세요"라고 구체적인 제안을 할 수 있습니다. 모델이 단순히 예측만 하는 게 아니라 비즈니스 인사이트를 제공하는 것입니다.
하지만 주의할 점도 있습니다. 특성 중요도는 상관관계가 높은 특성들 사이에서 오해를 줄 수 있습니다.
예를 들어 "키"와 "몸무게"가 모두 중요한데, 둘이 상관관계가 높으면 중요도가 나뉘어서 각각 낮게 나올 수 있습니다. 또한 중요도가 낮다고 해서 그 특성이 쓸모없다는 의미는 아닙니다.
김개발 씨는 특성 중요도를 뽑아서 팀장님께 보고했습니다. "서비스 이용 개월 수가 가장 중요하고, 그 다음이 월 사용 금액이네요." 팀장님이 고개를 끄덕였습니다.
"좋아요, 이제 이걸 그래프로 보여줄 수 있어요?"
실전 팁
💡 - 상관관계가 높은 특성은 중요도가 나뉠 수 있으니 주의하세요
- permutation_importance를 사용하면 더 안정적인 중요도를 얻을 수 있습니다
6. 트리 시각화하기
팀장님이 말씀하셨습니다. "다음 주에 임원 보고가 있어요.
이 모델이 어떻게 작동하는지 비개발자도 이해할 수 있게 보여줄 수 있을까요?" 김개발 씨는 고민에 빠졌습니다. 코드로 설명하기엔 임원분들이 개발자가 아닌데...
결정 트리의 가장 큰 장점 중 하나는 시각화가 가능하다는 것입니다. 트리 구조를 그래프로 그려서 비개발자도 모델의 의사결정 과정을 이해할 수 있습니다.
scikit-learn의 plot_tree나 graphviz를 사용하면 아름다운 트리 그래프를 만들 수 있습니다.
다음 코드를 살펴봅시다.
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
# 데이터 로드 및 모델 학습
iris = load_iris()
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(iris.data, iris.target)
# 트리 시각화
plt.figure(figsize=(20, 10))
plot_tree(
model,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True, # 노드에 색상 채우기
rounded=True, # 둥근 모서리
fontsize=12
)
plt.title('Decision Tree Visualization')
plt.tight_layout()
plt.savefig('decision_tree.png', dpi=150)
plt.show()
print("트리가 decision_tree.png로 저장되었습니다.")
박시니어 씨가 말했습니다. "결정 트리의 가장 큰 장점이 바로 이거예요.
다른 머신러닝 알고리즘은 설명하기 어렵지만, 결정 트리는 그림 한 장으로 모든 걸 보여줄 수 있거든요." 트리 시각화는 마치 조직도를 보는 것과 같습니다. 회사 조직도를 보면 맨 위에 CEO가 있고, 아래로 내려가면서 각 부서와 팀이 나뉩니다.
결정 트리 그래프도 마찬가지입니다. 맨 위에 루트 노드가 있고, 아래로 내려가면서 조건에 따라 분기합니다.
최종적으로 리프 노드에서 예측 결과가 나옵니다. plot_tree 함수의 각 파라미터를 살펴봅시다.
feature_names는 각 분할에서 어떤 특성을 사용했는지 보여줍니다. "petal length <= 2.45"처럼 표시됩니다.
class_names는 예측 클래스의 이름을 보여줍니다. filled=True를 설정하면 노드가 색상으로 채워지는데, 클래스별로 다른 색상이 적용되어 한눈에 분류 결과를 알 수 있습니다.
시각화된 트리에서 읽을 수 있는 정보가 많습니다. 각 노드에는 분할 조건, 지니 불순도, 샘플 수, 각 클래스의 비율, 예측 클래스가 표시됩니다.
예를 들어 "gini = 0.0"이면 해당 노드의 데이터가 모두 같은 클래스라는 뜻입니다. 노드의 색상이 진할수록 해당 클래스의 비율이 높습니다.
더 아름다운 시각화를 원한다면 graphviz를 사용할 수 있습니다. export_graphviz 함수로 dot 파일을 생성하고, graphviz로 렌더링하면 더 세련된 그래프를 얻을 수 있습니다.
특히 대형 트리를 시각화할 때 유용합니다. 하지만 시각화의 한계도 있습니다.
트리가 너무 깊거나 노드가 많으면 그래프가 복잡해져서 오히려 이해하기 어려워집니다. 그래서 보고용으로는 max_depth를 3이나 4 정도로 제한한 트리를 시각화하는 것이 좋습니다.
전체 모델의 성능은 더 깊은 트리를 사용하되, 설명용으로는 단순화된 버전을 보여주는 것입니다. 김개발 씨는 예쁜 트리 그래프를 만들어서 발표 자료에 넣었습니다.
임원 보고에서 팀장님이 그래프를 보여주며 설명했습니다. "보시다시피, 서비스 이용 개월 수가 6개월 미만이고 월 사용 금액이 3만원 미만이면 이탈 위험이 높습니다." 임원분들이 고개를 끄덕이며 이해했다는 표정을 지었습니다.
박시니어 씨가 김개발 씨의 어깨를 두드렸습니다. "축하해요.
이제 결정 트리의 기본을 완전히 마스터했네요. 다음엔 랜덤 포레스트를 배워볼까요?
결정 트리 여러 개를 합친 더 강력한 알고리즘이에요."
실전 팁
💡 - 보고용 시각화에는 max_depth를 3-4로 제한하여 간결하게 만드세요
- filled=True와 rounded=True 옵션으로 더 보기 좋은 그래프를 만들 수 있습니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.