[머신러닝] 결정 트리
결정 트리 소개
결정 트리의 기본 개념
결정 트리(Decision Tree)는 데이터를 분류하거나 값을 예측하는 데 사용되는 중요한 머신러닝 알고리즘입니다. 그 이름에서 알 수 있듯이, 결정 트리는 결정 노드와 리프 노드로 구성된 트리 구조를 사용하여 데이터를 분석합니다. 결정 노드(Decision Node)는 데이터를 분할하는 질문이나 조건을 나타내며, 리프 노드(Leaf Node)는 결정 결과 즉, 최종 분류 레이블이나 예측 값을 나타냅니다. 이 구조를 통해 데이터를 보다 잘 이해하고 인사이트를 얻으며 예측을 수행할 수 있습니다.
결정 트리의 중요성과 사용 사례
결정 트리는 그 직관적인 모델 구조로 인해 매우 인기 있는 머신러닝 알고리즘 중 하나입니다. 모델의 노드들을 따라가며 어떻게 데이터가 분류되거나 예측이 이루어지는지 쉽게 이해할 수 있기 때문에, 모델의 설명 가능성이 매우 높습니다. 이로 인해 의사 결정 과정에서 결정 트리의 결과를 더 쉽게 해석하고 신뢰할 수 있습니다.
결정 트리는 은행의 고객 신용 위험 분석, 의료 분야의 질병 진단, 전자상거래에서의 고객 구매 예측 등 다양한 분야에서 널리 사용됩니다. 이런 다양한 사례는 결정 트리가 가지는 광범위한 적용 가능성을 보여줍니다.
결정 트리와 다른 머신러닝 모델과의 비교
결정 트리는 종종 다른 머신러닝 모델과 비교됩니다. 예를 들어, 랜덤 포레스트(Random Forest)와 그라디언트 부스팅(Gradient Boosting) 같은 앙상블 학습 방법은 결정 트리를 기반으로 하여 결정 트리의 단일 모델 성능 제한을 넘어서려고 합니다. 이 앙상블 모델들은 여러 개의 결정 트리를 결합하여 더 강력한 예측 모델을 만듭니다.
비선형 데이터 패턴을 학습하는 능력 측면에서 인공신경망(ANN)과 비교될 때, 결정 트리는 보다 해석이 쉽지만, 복잡한 비선형 관계를 모델링하는 데 있어서는 인공신경망에 비해 제한적일 수 있습니다. 그러나 결정 트리는 데이터의 전처리 요구가 상대적으로 적고, 데이터의 비선형 관계와 상호작용을 자연스럽게 포착할 수 있는 장점이 있습니다.
결국, 선택한 머신러닝 모델은 특정 문제에 대한 요구 사항, 데이터의 특성, 설명 가능성에 대한 요구 등 여러 요소를 고려하여 결정해야 합니다. 결정 트리는 이해하기 쉽고 설명하기 쉬운 모델이 필요할 때, 특히 유용할 수 있습니다.
결정 트리(Decision Trees)는 분류(classification)나 회귀(regression) 문제에 널리 사용되는 머신러닝 알고리즘입니다. 이 알고리즘의 핵심 원리는 데이터를 가장 잘 분류할 수 있는 질문을 찾아내어, 해당 질문을 기준으로 데이터 집합을 분할하는 과정을 반복하는 것입니다. 이 과정에서 사용되는 주요 개념은 노드(Node), 엣지(Edge), 리프(Leaf), 정보 이득(Information Gain), 그리고 지니 불순도(Gini Impurity)입니다.
노드(Node), 엣지(Edge), 리프(Leaf) 정의
- 노드(Node): 결정 트리에서 데이터를 분할하는 질문이나 결정이 이루어지는 지점입니다. 노드는 두 가지 유형이 있습니다. 하나는 데이터 집합을 분할하는 질문을 포함하는 **내부 노드(Internal Node)**이고, 또 하나는 최종 결정이 된 리프 노드(Leaf Node) 혹은 종단 노드(Terminal Node)입니다.
- 엣지(Edge): 결정 트리에서 노드 사이의 연결선입니다. 각 엣지는 하나의 노드에서 다른 노드로 데이터를 분류할 때 선택하는 경로를 나타냅니다.
- 리프(Leaf): 리프 노드는 더 이상 자식 노드가 없는 결정 트리의 마지막 노드입니다. 여기에서 최종 결정이 이루어지며, 해당 리프 노드에 도달한 데이터는 모두 동일한 예측 결과를 갖습니다.
결정 과정의 시각화
결정 트리는 그 이름처럼 나무 구조로 시각화할 수 있습니다. 루트에서 시작하여 각 노드에서 질문을 하며, 그 질문의 답변(예/아니오)에 따라 다음 노드로 넘어갑니다. 이 과정을 반복하며 리프 노드에 도달할 때까지 데이터 집합을 분할해 나갑니다.
정보 이득(Information Gain)과 지니 불순도(Gini Impurity)
결정 트리가 어떤 질문을 할지 결정하는 기준은 정보 이득과 지니 불순도를 사용하여 계산합니다.
- 정보 이득(Information Gain): 특정 데이터 집합을 분할하기 전과 후의 엔트로피(또는 불확실성) 차이를 측정합니다. 정보 이득이 높을수록 그 분할은 유용한 정보를 더 많이 제공하는 것으로 간주됩니다. 정보 이득이 최대가 되는 방향으로 데이터를 분할합니다.
- 지니 불순도(Gini Impurity): 한 노드에서 임의로 선택된 데이터가 잘못 분류될 확률을 나타냅니다. 지니 불순도가 낮을수록, 즉 0에 가까울수록 데이터 집합의 순도가 높은 것입니다. 지니 불순도를 최소화하는 방향으로 데이터를 분할합니다.
여기서 는 i번째 클래스의 데이터 비율입니다.
Python 코드 예시
Scikit-learn 라이브러리를 사용하여 간단한 결정 트리 모델을 학습하는 예시 코드입니다.
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
# 데이터셋 로드
iris = load_iris()
X, y = iris.data, iris.target
# 결정 트리 모델 학습
tree_clf = DecisionTreeClassifier(max_depth=2, criterion='gini') # 기준: 지니 불순도
tree_clf.fit(X, y)
이 코드는 아이리스(Iris) 데이터셋에 대하여 최대 깊이가 2인 결정 트리를 구축하고, 지니 불순도를 기준으로 데이터를 분할합니다.
결정 트리는 높은 해석 가능성(Interpretability) 때문에 데이터 분석가와 기계학습 엔지니어들에게 매우 인기 있는 모델 중 하나입니다. 그러나, 복잡한 결정 경계를 만들거나 과적합(Overfitting)되기 쉬우므로 적절한 사전 가지치기(Pre-pruning) 기법이나 앙상블 학습(Ensemble Learning)과 같은 방법을 사용하여 이를 완화할 수 있습니다.
결정 트리 알고리즘은 데이터를 분류하거나 값을 예측하기 위해 사용되는 알고리즘으로, 데이터의 속성(특징)을 기반으로 결정 규칙을 통해 나무(tree) 모양의 구조를 만들어 나가는 방식입니다. 각각의 알고리즘은 약간의 차이가 있으며, 그 특징을 구체적으로 살펴보겠습니다.
ID3 (Iterative Dichotomiser 3) 알고리즘
ID3 알고리즘은 예/아니오 형태의 결정을 통해 데이터를 분류하는 가장 기본적인 형태의 결정 트리 알고리즘입니다. 이 알고리즘은 정보 이득(Information Gain, IG)을 사용하여 각 속성의 중요도를 평가합니다. 정보 이득이 높은 속성을 결정 트리의 루트 또는 내부 노드로 선택합니다. 정보 이득은 엔트로피(Entropy)라는 개념을 사용하여 계산되며, 엔트로피가 낮을수록 분류 결과의 불확실성이 낮아집니다.
여기서 는 데이터 집합, 는 속성, 는 속성 의 모든 가능한 값, 은 속성 의 값이 인 데이터들의 집합입니다.
C4.5 및 C5.0 알고리즘
C4.5 알고리즘은 ID3의 확장으로, 연속적인 속성 처리, 속성 비용 다루기, 누락된 데이터 처리 등의 기능이 추가되었습니다. C4.5는 정보 이득 대신 정보 이득 비율(Gain Ratio)을 사용하여 분할 기준을 선택합니다. 이는 정보 이득만 사용할 때 발생하는 편향을 줄여줍니다. C5.0은 C4.5의 더욱 개선된 버전으로, 실행 속도와 메모리 사용량을 최적화한 알고리즘입니다.
여기서 는 속성 에 따른 데이터 분할 정보량을 나타냅니다.
CART (Classification And Regression Trees) 알고리즘
CART 알고리즘은 분류(Classification)와 회귀(Regression) 모두에 사용할 수 있는 트리 기반의 알고리즘입니다. CART는 이진 트리를 사용하는 것이 주요 특징입니다. 즉, 각 노드에서 두 개의 자식 노드로만 분할됩니다. CART는 지니 불순도(Gini Impurity) 또는 평균 제곱 오차(Mean Squared Error, MSE - 회귀의 경우)를 사용하여 최적의 분할을 찾습니다.
결정 트리 알고리즘의 Python 코드 예시
Python의 사이킷런(scikit-learn) 라이브러리를 사용하여 결정 트리 모델을 간단하게 구현할 수 있습니다. CART 알고리즘을 예로 들어보겠습니다.
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
# 데이터 로드
iris = load_iris()
X = iris.data
y = iris.target
# 훈련 데이터와 테스트 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# CART 결정 트리 모델 생성 및 훈련
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
# 모델 평가
score = clf.score(X_test, y_test)
print("Accuracy:", score)
각 알고리즘은 데이터의 특징과 분석 목적에 따라 적절히 선택하여 사용해야 합니다.
결정 트리 구축
결정 트리의 구축은 데이터를 가장 잘 분류하는 질문(조건)을 찾고, 그 질문에 대한 답(예/아니오)에 따라 트리의 가지를 나누는 과정을 반복하는 것으로 구성됩니다. 이 과정은 광범위한 분류와 회귀 문제에 사용될 수 있습니다. 구축 과정의 핵심 부분은 특성 선택과 가지치기(Pruning) 기법에 중점을 둡니다.
특성 선택 과정
특성 선택의 목적은 데이터를 가장 잘 분류할 수 있는 특성을 찾는 것입니다. 결정 트리에서는 이를 위해 여러 메트릭을 사용합니다.
엔트로피(Entropy): 데이터 세트의 무질서도를 측정하는 지표로, 엔트로피가 낮을수록 정보의 순도가 높습니다. 엔트로피는 다음과 같은 수식으로 계산됩니다.
여기서, 는 선택된 클래스에 속하는 사례의 비율입니다.
정보 이득(Information Gain): 분할 전과 후의 엔트로피 차이로, 정보 이득이 높은 특성을 분할 기준으로 선택합니다. 정보 이득은 다음과 같은 수식으로 계산됩니다.
여기서, 는 번째 부분 집합의 크기이고, 은 전체 트레이닝 세트의 크기입니다.
지니 불순도(Gini Impurity): 지니 불순도는 또 다른 트리 구축 시 사용되는 메트릭으로, 한 노드에 같은 클래스의 레코드가 얼마나 혼합되어 있는지를 측정합니다. 계산 방법은 다음과 같습니다.
일반적으로, 정보 이득이 가장 높거나 지니 불순도가 가장 낮은 특성을 선택합니다.
가지치기(Pruning) 기법
결정 트리가 너무 깊어지면 과적합(Overfitting)이 발생할 수 있습니다. 과적합을 방지하기 위해 트리의 성장을 제한하는 가지치기 기법을 사용합니다.
- 사전 가지치기(Pre-Pruning): 트리의 성장 단계에서 사전에 과적합을 방지하기 위한 방법입니다. 특정 깊이에 도달하거나, 노드가 분할되기 위한 최소 샘플 수에 도달하면 더 이상 분할을 하지 않습니다.
from sklearn.tree import DecisionTreeClassifier
# 사전 가지치기 예시
clf = DecisionTreeClassifier(max_depth=3, min_samples_split=10)
clf.fit(X_train, y_train)
- 사후 가지치기(Post-Pruning): 트리를 완전히 성장시킨 후, 노드의 중요도에 따라 가지를 제거하는 방법입니다. 이 방법은 Cost complexity pruning이라고도 하며, 트리의 복잡도와 오류율 간의 가장 좋은 균형을 찾는 데 사용됩니다.
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
# 사후 가지치기 예시
clf = DecisionTreeClassifier(ccp_alpha=0.01) # ccp_alpha는 가지치기의 복잡도 파라미터
clf.fit(X_train, y_train)
tree.plot_tree(clf) # 가지치기된 트리 시각화
결과적으로, 이러한 특성 선택과 가지치기 과정을 통해 모델의 오버피팅을 방지하고 일반화 성능을 높일 수 있습니다.
결정 트리는 데이터 분석 및 머신러닝에서 분류와 회귀 문제를 해결하기 위해 널리 사용되는 알고리즘입니다. 여기서는 결정 트리의 주요 장단점에 대해 자세히 설명하고, 이로 인한 영향을 살펴보겠습니다.
장점
-
해석 용이성: 결정 트리 알고리즘의 가장 큰 장점 중 하나는 그 결과를 쉽게 해석할 수 있다는 점입니다. 각 분기점(노드)는 분류 기준 또는 결정 기준을 나타내며, 최종적으로 어떤 결정이 내려졌는지 그 과정을 명확하게 이해할 수 있습니다. 예를 들어, 의사 결정 트리는 의료 진단에서 패턴을 식별하고 이를 통해 진단을 내릴 수 있게 해줍니다.
-
데이터 전처리의 요구성이 낮음: 결정 트리는 누락된 값이 있거나, 데이터의 스케일이 서로 다를 때도 상대적으로 잘 작동합니다. 예를 들어, 특성이 서로 다른 단위나 범위를 가지고 있어도, 결정 트리를 사용할 때 반드시 표준화나 정규화 같은 전처리 과정을 거칠 필요가 없습니다.
-
다양한 데이터 유형 처리 가능: 결정 트리는 숫자형 데이터뿐만 아니라 범주형 데이터도 처리할 수 있는 능력을 가지고 있습니다. 이 때문에 다양한 유형의 데이터를 가진 문제에 유연하게 적용될 수 있습니다.
단점
-
과적합(Overfitting) 경향성: 결정 트리는 훈련 데이터에 대해서 너무 세세하게 학습을 진행할 경우 과적합이 발생하는 경향이 있습니다. 이는 무엇보다 트리가 너무 깊어지면 발생하기 쉽습니다. 트리의 최대 깊이를 제한하거나, 가지치기(pruning) 기법을 적용하여 과적합을 방지할 수 있습니다.
# 예시: sklearn에서 결정 트리의 깊이 제한하기 from sklearn.tree import DecisionTreeClassifier # max_depth를 설정하여 과적합 방지 decision_tree = DecisionTreeClassifier(max_depth=3)
-
안정성의 부족: 결정 트리는 훈련 데이터에 있는 작은 변화에도 매우 민감하게 반응할 수 있습니다. 예를 들어, 훈련 데이터에서 단 하나의 항목을 제거하더라도 생성된 트리의 구조가 크게 달라질 수 있습니다. 이러한 불안정성은 특히 작은 데이터 세트를 사용할 때 문제가 될 수 있습니다. 이를 개선하기 위해, 앙상블 기법을 사용하여 여러 개의 결정 트리를 조합하는 방법이 있습니다. 대표적으로 랜덤 포레스트가 있으며, 이는 여러 개의 결정 트리를 통해 예측을 진행하고, 그 결과를 평균내어 안정성을 높이는 방식입니다.
결정 트리는 그 구조가 단순하고 이해하기 쉬운 반면, 과적합과 데이터의 작은 변화에 대한 민감성이라는 취약점을 가지고 있습니다. 이러한 장단점을 이해하고 적절한 전략을 통해 단점을 완화한다면, 결정 트리는 여전히 강력하고 유용한 도구로 활용될 수 있습니다.
결정 트리의 응용 분야는 매우 다양하며, 주로 분류 작업, 회귀 작업, 그리고 특징 중요도 평가를 포함합니다. 아래에서 이러한 응용 분야에 대해 구체적으로 설명하고, Python을 사용한 예시 코드를 제시하겠습니다.
분류 작업(Classification Tasks)
분류는 데이터를 미리 정의된 여러 그룹 중 하나로 분류하는 프로세스입니다. 결정 트리는 분류 문제를 해결하는 데 널리 사용되는 기법 중 하나입니다. 데이타의 특성(피처)을 바탕으로 특정 클래스 레이블(예: 이메일이 스팸인지 아닌지)을 예측할 수 있습니다.
Python 예시: 결정 트리를 이용한 분류
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
# 데이터 로드
iris = load_iris()
X, y = iris.data, iris.target
# 훈련세트와 테스트세트 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 결정 트리 모델 훈련
dt_classifier = DecisionTreeClassifier(random_state=42)
dt_classifier.fit(X_train, y_train)
# 예측
predictions = dt_classifier.predict(X_test)
# 정확도 출력
print(f'Accuracy: {dt_classifier.score(X_test, y_test)}')
회귀 작업(Regression Tasks)
회귀는 데이터의 모든 점들 사이의 관계를 모델링하고, 이를 바탕으로 연속적인 수치(예: 주택 가격)를 예측하는 작업입니다. 결정 트리는 분류뿐만 아니라 회귀 문제에도 유용하게 사용될 수 있습니다.
Python 예시: 결정 트리를 이용한 회귀
from sklearn.tree import DecisionTreeRegressor
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
# 데이터 로드
boston = load_boston()
X, y = boston.data, boston.target
# 훈련세트와 테스트세트 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 결정 트리 회귀 모델 훈련
dt_regressor = DecisionTreeRegressor(random_state=42)
dt_regressor.fit(X_train, y_train)
# 예측
predictions = dt_regressor.predict(X_test)
# 정확도 출력
print(f'Accuracy: {dt_regressor.score(X_test, y_test)}')
특징 중요도 평가
결정 트리의 큰 이점 중 하나는 모델을 해석하기 쉽다는 것입니다. 결정 트리는 각 특성(피처)이 최종 예측에 미치는 중요도를 쉽게 계산할 수 있어, 어떤 변수가 결과에 큰 영향을 미치는지 파악할 수 있습니다.
Python 예시: 결정 트리를 이용한 특징 중요도 평가
import numpy as np
import matplotlib.pyplot as plt
# 특징 중요도 추출
importances = dt_classifier.feature_importances_
# 특징 중요도 시각화
indices = np.argsort(importances)[::-1]
plt.figure()
plt.title("Feature Importances")
plt.bar(range(X.shape[1]), importances[indices],
color="r", align="center")
plt.xticks(range(X.shape[1]), iris.feature_names, rotation=90)
plt.xlim([-1, X.shape[1]])
plt.show()
위 예시는 결정 트리를 사용하여 분류 작업, 회귀 작업, 그리고 특징 중요도 평가를 수행하는 방법을 보여줍니다. 이들 응용 분야에서 결정 트리를 사용함으로써 데이터의 복잡한 패턴을 해석하고, 중요한 통찰을 얻을 수 있습니다.