본문 바로가기
정보/IT 지식 정보

결정 트리와 랜덤 포레스트란?트리 기반 분류 완전 정리 [6편]

by 안다니. 2026. 3. 27.
반응형
결정트리 랜덤 포레스트

 

표준화 없이 작동하고, 분류 과정이 눈에 보이는 직관적인 모델을 구현합니다

시리즈: 신경망 밑바닥부터 구현하기
1~5편: 퍼셉트론 → ADALINE → SGD → 로지스틱 회귀 → SVM · 6편: 결정 트리 & 랜덤 포레스트 (완결)

결정 트리란?

지금까지 다룬 알고리즘(퍼셉트론, 로지스틱 회귀, SVM)은 모두 직선이나 곡선으로 영역을 나눴습니다. 결정 트리(Decision Tree)는 접근 방식이 다릅니다. 데이터를 질문을 통해 순차적으로 나누어갑니다.

"꽃잎 길이가 2.45cm 이하인가?" → 예: setosa / 아니오: 다음 질문 → "꽃잎 너비가 1.75cm 이하인가?" → 예: versicolor / 아니오: virginica

이런 식으로 질문을 반복하면서 데이터를 분류합니다. 스무고개 게임과 원리가 같습니다.

결정 트리의 장점
첫째, 표준화가 필요 없습니다. 원본 데이터를 그대로 사용할 수 있습니다.
둘째, 분류 과정을 트리 구조로 시각화할 수 있어서 "왜 이렇게 분류했는지" 설명이 가능합니다.

지니 불순도 — 트리가 분할 기준을 정하는 방법

결정 트리는 매 단계에서 "어떤 질문을 해야 가장 효과적으로 나눌 수 있는가"를 판단해야 합니다. 이때 사용하는 기준이 지니 불순도(Gini Impurity)입니다.

불순도란 한 그룹 안에 여러 클래스가 섞여 있는 정도를 말합니다. 한 그룹에 setosa만 있으면 불순도가 0(완벽하게 순수), 세 종류가 골고루 섞여 있으면 불순도가 높습니다. 트리는 분할 후 불순도가 가장 많이 줄어드는 질문을 선택합니다.

지니 불순도 vs 엔트로피
결정 트리의 분할 기준으로 엔트로피(entropy)를 쓸 수도 있습니다. 실제로는 두 방법의 결과 차이가 크지 않아서, scikit-learn의 기본값인 지니 불순도를 많이 사용합니다.

파이썬으로 결정 트리 구현하기

반응형
from sklearn.tree import DecisionTreeClassifier

tree_model = DecisionTreeClassifier(
    criterion='gini',
    max_depth=4,
    random_state=1)

tree_model.fit(X_train, y_train)  # 표준화 안 한 원본 데이터!

주목할 점은 X_train_std가 아니라 X_train(원본 데이터)을 사용한다는 것입니다. 결정 트리는 특성값의 크기 비교만 하기 때문에 표준화가 불필요합니다.

max_depth=4는 트리의 최대 깊이를 4로 제한한다는 뜻입니다. 제한하지 않으면 모든 훈련 데이터를 완벽하게 분류할 때까지 트리가 깊어져서 과적합이 발생합니다.

트리 시각화
from sklearn import tree

plt.figure(figsize=(10, 10))
tree.plot_tree(tree_model,
    impurity=True,
    filled=True,
    rounded=True,
    class_names=['Setosa', 'Versicolor', 'Virginica'],
    feature_names=['petal length', 'petal width'])
plt.show()
시각화 결과
트리의 각 노드에 분할 조건(예: "petal length ≤ 2.45"), 지니 불순도, 샘플 수, 클래스 분포가 표시됩니다. 루트 노드의 첫 번째 질문 하나로 setosa가 완벽하게 분리되고, 이후 질문들로 versicolor와 virginica가 나뉘는 과정을 직접 눈으로 확인할 수 있습니다.

max_depth가 결과에 미치는 영향

max_depth = 4 트리가 충분히 깊어서 대부분의 데이터를 정확히 분류합니다. 결정 경계가 계단 형태로 세밀하게 나뉩니다.
max_depth = 3 트리가 한 단계 얕아져서 일부 세밀한 분류를 놓칩니다. 하지만 더 단순한 모델이므로 새 데이터에 대한 일반화 성능은 오히려 좋을 수 있습니다.

depth를 줄이면 트리가 단순해지고, 늘리면 복잡해집니다. 이것도 결국 과적합과 과소적합 사이의 균형 문제입니다. 보통 교차 검증으로 최적의 depth를 찾습니다.

랜덤 포레스트 — 나무가 모이면 숲이 된다

결정 트리 하나는 과적합에 취약합니다. 이 문제를 해결하는 가장 강력한 방법이 랜덤 포레스트(Random Forest)입니다. 아이디어는 단순합니다. 결정 트리를 여러 개 만들고, 각 트리의 예측을 다수결로 합칩니다.

from sklearn.ensemble import RandomForestClassifier

forest = RandomForestClassifier(
    criterion='gini',
    n_estimators=25,   # 트리 25개 생성
    random_state=1,
    n_jobs=2)          # CPU 2개로 병렬 처리

forest.fit(X_train, y_train)

각 트리가 "다르게" 학습하도록 하는 것이 핵심입니다. 랜덤 포레스트는 두 가지 무작위성을 도입합니다.

첫째, 부트스트랩 샘플링 — 각 트리마다 전체 훈련 데이터에서 중복을 허용하여 랜덤하게 데이터를 뽑습니다. 둘째, 특성 랜덤 선택 — 각 분할마다 전체 특성 중 일부만 랜덤하게 선택합니다.

이렇게 하면 25개의 트리가 각각 다른 관점에서 데이터를 학습하고, 다수결로 합치면 개별 트리보다 더 안정적인 예측을 합니다.

25개 트리의 개별 구조
각 트리를 시각화하면 구조가 모두 다릅니다. 어떤 트리는 petal length를 먼저 물어보고, 어떤 트리는 petal width를 먼저 물어봅니다. 이 다양성이 앙상블의 강점입니다.
실무에서 랜덤 포레스트가 인기 있는 이유
표준화 불필요, 과적합에 강함, 하이퍼파라미터 튜닝이 상대적으로 쉬움, 병렬 처리 가능. 특별한 이유가 없으면 랜덤 포레스트부터 시도하는 것이 실무에서 흔한 접근 방식입니다.

시리즈 최종 정리 — 6가지 분류 알고리즘 비교

알고리즘 핵심 원리 표준화 비선형
퍼셉트론 가중합 → 계단 함수 필요 불가
ADALINE 경사 하강법으로 비용 최소화 필요 불가
로지스틱 회귀 시그모이드 → 확률 출력 필요 불가
선형 SVM 마진 최대화 필요 불가
커널 SVM 커널 트릭으로 고차원 매핑 필요 가능
결정 트리 질문 기반 순차 분할 불필요 가능
랜덤 포레스트 다수의 트리 앙상블 불필요 가능

시리즈를 마치며

1편의 퍼셉트론에서 시작해서 6편의 랜덤 포레스트까지, 분류 알고리즘의 핵심을 코드와 함께 살펴봤습니다.

각 알고리즘은 이전 알고리즘의 한계를 극복하기 위해 등장했습니다. 퍼셉트론의 불안정한 학습 → ADALINE의 경사 하강법 → SGD의 효율성 → 로지스틱 회귀의 확률 출력 → SVM의 마진 최대화 → 커널 트릭의 비선형 분류 → 결정 트리의 직관성 → 랜덤 포레스트의 안정성.

이 흐름을 이해하면 새로운 알고리즘을 만났을 때도 "이건 어떤 한계를 극복하려는 것인가"라는 관점에서 빠르게 파악할 수 있습니다.

신경망 밑바닥부터 구현하기 시리즈 [6편 · 완결]

반응형

댓글