의사결정나무와 랜덤 포레스트 이해 및 코드 실습

의사결정나무는 SVM과 마찬가지로 범용적인 머신러닝 알고리즘입니다. 여러 의사결정나무 분류기를 모아서 더 강력한 머신러닝 알고리즘이 되는 것이 랜덤 포레스트입니다. 이들 모두 기본적이지만 매우 강력한 도구로, 단순하고 유연하여 여전히 많은 사랑을 받고 있습니다.

  1. 의사결정나무

1.1 의사결정나무란?

의사결정나무를 IF/ELSE 문으로 구성된 깊이 중첩된 이진 트리 구조라고 생각할 수 있습니다. 예를 들어, 붓꽃 데이터셋에서 꽃잎 길이와 너비를 기준으로 종을 분류하는 경우를 살펴보겠습니다.

다음은 간단한 의사결정나무 구조입니다:

  • 꽃잎 길이가 2.45보다 작으면 setosa,
  • 그렇지 않으면 꽃잎 너비가 1.75보다 작으면 versicolor,
  • 나머지는 virginica입니다.

따라서 임의의 붓꽃 샘플에 대해 우리는 의사결정나무의 루트 노드에서 리프 노드까지 순회하면서 붓꽃의 종을 결정할 수 있습니다.

1.2 의사결정나무 코드 실습

데이터셋을 불러오고 모델을 학습시킵니다:

import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier

# 데이터셋 로드
df = pd.read_csv('https://example.com/iris.csv')

# 의사결정나무 모델
X = df[['petal_length', 'petal_width']].to_numpy()
y = df['species']
tree_clf = DecisionTreeClassifier(max_depth=2, random_state=42)
tree_clf.fit(X, y)

의사결정나무 시각화:

import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(12,8))
plot_tree(tree_clf, filled=True);

루트 노드의 총 인스턴스 수는 150개이며, value = [50, 50, 50]으로 각 종별로 50개씩 분포되어 있음을 알 수 있습니다. 오른쪽 리프 노드(value = [0, 1, 45])에서는 0개의 setosa, 1개의 versicolor, 45개의 virginica 인스턴스가 있습니다.

Gini 계수는 다음과 같이 계산됩니다:

$$ G_i = 1 - \sum_{k=1}{n}{p2_{i,k}} $$

예를 들어, virginica 노드의 Gini 계수는 1-((0/46)**2 + (1/46)**2 + (45/46)**2) ≈ 0.043입니다.

  1. 랜덤 포레스트

2.1 대수의 법칙과 랜덤 포레스트

랜덤 포레스트는 의사결정나무들을 무작위로 조합하여 만들어집니다. 이를 통해 개별 의사결정나무보다 더 효과적인 모델을 얻을 수 있습니다.

대수의 법칙에 따르면, 충분히 많은 횟수의 시도를 통해 평균값이 안정적으로 나타납니다. 즉, 품질보다 수량을 늘려 모델의 성능을 향상시킬 수 있습니다.

2.2 랜덤 포레스트 코드 실습

2.2.1 새로운 데이터셋 사용

필요한 라이브러리를 추가합니다:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

데이터셋을 불러옵니다:

df = pd.read_csv("https://example.com/penguins_size.csv")
df = df.dropna()
df.head()

페인귄 데이터셋은 다음과 같은 특징과 레이블을 포함하고 있습니다:

  • 특징: 섬(island), 부리 길이(culmen_length_mm), 부리 깊이(culmen_depth_mm), 날개 길이(flipper_length_mm), 체중(body_mass_g), 성별(sex)
  • 레이블: 종(species): Chinstrap, Adélie, Gentoo

2.2.2 데이터 관찰

sns.pairplot(df, hue='species')

2.2.3 전처리

X = pd.get_dummies(df.drop('species', axis=1), drop_first=True)
y = df['species']
X.head()

2.2.4 데이터 학습

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=101)
model = RandomForestClassifier(n_estimators=10, max_features='auto', random_state=101)
model.fit(X_train, y_train)

from sklearn.metrics import accuracy_score
preds = model.predict(X_test)
accuracy_score(y_test, preds)

랜덤 포레스트 분류기로 학습한 결과 정확도는 약 97%입니다.

2.2.5 그리드 서치와 AdaBoost(추가)

AdaBoost를 사용하여 의사결정나무 분류기를 결합하고 그리드 서치로 최적 파라미터를 찾습니다:

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import AdaBoostClassifier

ada_clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), random_state=101)
ada_clf.fit(X_train, y_train)
param_grid = {'n_estimators': [10, 15, 20, 25, 30], 'learning_rate': [0.01, 0.1, 0.5, 1], 'algorithm': ['SAMME', 'SAMME.R']}
grid = GridSearchCV(ada_clf, param_grid)
grid.fit(X_train, y_train)
print("최적 파라미터: ", grid.best_params_, " 최고 점수: ", grid.best_score_)

태그: 의사결정나무 랜덤포레스트 scikit-learn python

6월 10일 01:31에 게시됨