R에서 의사결정 나무 (rpart(), rpart.plot())

제공

안녕하세요! 오늘은 데이터 분석에서 핫한 알고리즘 중 하나, 바로 의사결정 나무에 대해 같이 알아보는 시간을 가져보려고 해요. 마치 나무가 가지를 뻗어 나가듯 데이터를 분석하는 재미있는 방법이랍니다. R 언어의 강력한 도구인 rpart() 함수와 예쁜 시각화를 위한 rpart.plot() 함수를 활용하면, 복잡한 데이터도 쉽고 직관적으로 이해할 수 있어요. 궁금하시죠? 어려운 이론보다는 실제 데이터를 가지고 예시를 보여드릴 테니 걱정 마세요! 함께 rpart()rpart.plot()매력에 푹 빠져볼까요?

 

 

의사결정 나무란 무엇인가?

혹시 여러 갈래 길 앞에서 고민해 본 적 있으신가요? 어떤 길로 가야 할지 결정하기 위해 여러 가지 요소들을 따져보곤 하죠? 마치 “만약 날씨가 맑다면 공원에 가고, 흐리다면 박물관에 가자!” 와 같이 말이에요. 의사결정 나무는 이런 우리의 의사결정 방식을 시각적으로 표현한 알고리즘이라고 할 수 있어요! 😊

데이터 과학에서의 의사결정 나무

데이터 과학 분야에서 의사결정 나무는 예측 모델링에 널리 사용되는 지도 학습 알고리즘 중 하나입니다. 쉽게 말해, 주어진 데이터를 바탕으로 새로운 데이터에 대한 예측을 하는 데 사용되는 거죠. 마치 나무가 가지를 뻗어 나가듯, 데이터의 특징을 기준으로 가지를 나누고 최종적으로는 “잎”에 해당하는 예측 결과를 도출해냅니다.🌳 이러한 의사결정 나무는 분류(Classification)와 회귀(Regression) 두 가지 유형의 문제에 모두 적용할 수 있다는 장점이 있어요. 강아지와 고양이를 분류하는 문제, 또는 집값을 예측하는 문제 모두 의사결정 나무를 활용할 수 있다는 말이죠!

의사결정 나무의 구조

의사결정 나무의 구조는 크게 세 가지 요소로 이루어져 있습니다. 먼저, 뿌리 노드(Root Node)는 전체 데이터셋을 나타내는 시작점입니다. 다음으로, 내부 노드(Internal Node)는 특정 속성을 기준으로 데이터를 분할하는 역할을 합니다. 마지막으로, 잎 노드(Leaf Node)는 최종적인 예측 결과를 나타냅니다. 각 노드 사이의 연결은 가지(Branch)라고 부르며, 각 가지는 내부 노드에서 분할되는 조건을 나타냅니다.

의사결정 나무의 장점: 해석력

의사결정 나무의 가장 큰 장점 중 하나는 해석력이 뛰어나다는 점이에요. 복잡한 수식 없이, 나무 구조를 따라가면서 어떤 기준으로 예측이 이루어졌는지 쉽게 이해할 수 있죠. 예를 들어, 대출 심사 모델을 의사결정 나무로 구현한다면, 어떤 요소들이 대출 승인/거절에 영향을 미치는지 한눈에 파악할 수 있습니다. 신용 점수가 700점 이상이고, 연체 이력이 없다면 대출 승인! 이런 식으로 말이죠! 참 쉽죠잉~? 😉

의사결정 나무의 단점: 과적합

하지만, 의사결정 나무는 과적합(Overfitting)이 발생하기 쉽다는 단점도 가지고 있습니다. 과적합이란, 학습 데이터에 너무 잘 맞춰져서 새로운 데이터에 대한 예측 성능이 떨어지는 현상을 말해요. 마치 족집게 과외 선생님처럼, 기출문제는 완벽하게 풀지만 새로운 유형의 문제는 풀지 못하는 것과 비슷합니다.😅 이러한 과적합을 방지하기 위해 가지치기(Pruning)와 같은 기법들을 활용합니다. 가지치기는 마치 정원사가 나무의 불필요한 가지를 잘라내는 것처럼, 의사결정 나무의 복잡도를 줄여 과적합을 방지하는 역할을 합니다.

다양한 의사결정 나무 알고리즘

의사결정 나무 알고리즘에는 다양한 종류가 있는데, 대표적으로 CART, ID3, C4.5, CHAID 등이 있습니다. 각 알고리즘은 데이터를 분할하는 기준과 가지치기 방법 등에서 차이가 있어요. 예를 들어, CART 알고리즘은 지니 불순도(Gini Impurity)를 기준으로 데이터를 분할하고, C4.5 알고리즘은 정보 획득량(Information Gain)을 기준으로 데이터를 분할합니다. 어떤 알고리즘을 선택할지는 데이터의 특성과 분석 목적에 따라 달라지겠죠? 🤔

앙상블 기법

의사결정 나무는 그 자체로도 강력한 예측 모델이지만, 여러 개의 의사결정 나무를 결합하여 더욱 강력한 모델을 만들 수도 있어요. 이러한 앙상블 기법의 대표적인 예로는 랜덤 포레스트(Random Forest)그래디언트 부스팅 머신(Gradient Boosting Machine)이 있습니다. 랜덤 포레스트는 여러 개의 의사결정 나무를 무작위로 생성하고, 각 나무의 예측 결과를 평균하여 최종 예측 결과를 도출합니다. 마치 여러 전문가의 의견을 종합하여 최종 결정을 내리는 것과 비슷하죠! 👍 그래디언트 부스팅 머신은 여러 개의 의사결정 나무를 순차적으로 생성하고, 이전 나무의 오차를 보완하는 방식으로 학습합니다. 마치 여러 번의 시행착오를 거쳐 점점 더 정확한 예측을 하는 것과 같아요! 💪

R에서의 구현

자, 이제 의사결정 나무에 대한 기본적인 개념을 이해하셨나요? 다음에는 R에서 의사결정 나무를 구현하는 방법에 대해 알아볼 거예요. rpart() 함수와 rpart.plot() 함수를 이용하여 직접 의사결정 나무를 만들고 시각화하는 방법을 배우게 될 겁니다. 기대되시죠?! 😄

 

rpart() 함수 사용법

드디어! R에서 의사결정 나무를 만들어주는 rpart() 함수를 만나볼 시간이에요~! R로 데이터 분석을 하다 보면, 어떤 변수가 중요하고 어떻게 상호작용하는지 궁금할 때가 많잖아요? 그럴 때 바로 이 rpart() 함수가 엄청난 도움을 줄 수 있답니다!

rpart() 함수는 재귀적 분할(recursive partitioning)을 사용해서 데이터를 분석하고, 나무 모양으로 결과를 보여주는 아주 멋진 친구예요. 마치 나무가 가지를 뻗어 나가듯, 데이터를 계속해서 작은 부분으로 나눠가면서 패턴을 찾아내는 거죠. 이해하기 쉽고 결과를 해석하기도 편해서 정말 애정하는 함수 중 하나랍니다!

rpart() 함수의 기본 사용법

자, 이제 rpart() 함수의 기본적인 사용법을 알아볼까요? rpart(formula, data, method, control) 이렇게 네 가지 주요 인자를 가지고 있어요.

  • formula: 어떤 변수를 예측하고 싶은지, 그리고 어떤 변수를 사용해서 예측할 건지를 정의하는 부분이에요. 예를 들어, “y ~ x1 + x2″처럼 적으면 y를 x1과 x2를 사용해서 예측하겠다는 뜻이죠!
  • data: 분석에 사용할 데이터 프레임을 지정하는 부분이에요.
  • method: 분석의 목표를 지정하는 부분이에요. “class”는 분류, “anova”는 회귀, “poisson”는 포아송 회귀, “exp”는 생존 분석에 사용돼요. 분석 목적에 따라 잘 선택해야겠죠?!
  • control: 나무의 성장을 제어하는 다양한 옵션을 설정할 수 있어요. minsplit, cp, maxdepth 등 중요한 옵션들이 있는데, 이 부분은 조금 더 자세히 알아볼게요!

control 옵션 설명

rpart.control() 함수를 사용해서 control 옵션을 설정할 수 있어요. 몇 가지 중요한 옵션들을 살펴보면~:

  • minsplit: 한 노드에 있어야 할 최소 관측치 수를 정의해요. 너무 작은 값을 설정하면 과적합될 수 있으니 주의해야 해요! 보통 20 정도로 설정하는 경우가 많답니다.
  • cp: 복잡도 매개변수(complexity parameter)라고 하는데, 나무의 가지치기를 조절하는 역할을 해요. cp 값이 클수록 가지치기가 많이 되어서 단순한 나무가 만들어져요. 0.01이나 0.001처럼 작은 값부터 시작해서 적절한 값을 찾는 게 중요해요!
  • maxdepth: 나무의 최대 깊이를 제한하는 옵션이에요. 너무 깊어지면 해석하기 어려워질 수 있으니 적절한 값을 설정해야 한다는 점! 잊지 마세요! 보통 30 정도로 설정하는 경우가 많아요.

rpart() 함수 활용 예시

자, 이제 실제 데이터를 사용해서 rpart() 함수를 어떻게 활용하는지 예시를 통해 알아볼까요? iris 데이터셋을 사용해서 품종(Species)을 예측하는 의사결정 나무를 만들어 보겠습니다!

library(rpart)

# iris 데이터셋을 사용해서 품종(Species)을 예측하는 모델 생성!
model <- rpart(Species ~ ., data = iris, method = "class", 
               control = rpart.control(minsplit = 20, cp = 0.01, maxdepth = 30))

# 모델 결과 출력!
print(model)

# 더 자세한 정보를 보고 싶다면 summary() 함수를 사용해 보세요!
summary(model)

위 코드에서 Species ~ . 는 Species를 제외한 모든 변수를 사용해서 Species를 예측하겠다는 의미에요. method = "class"는 분류 모델을 만들겠다는 뜻이고, control 옵션에서는 minsplit, cp, maxdepth를 설정해 주었어요. rpart() 함수를 사용해서 만든 model 객체에는 다양한 정보가 담겨 있답니다. print(model) 함수를 사용하면 간단한 정보를 확인할 수 있고, summary(model) 함수를 사용하면 더욱 자세한 정보를 확인할 수 있어요.

rpart() 함수는 정말 강력하고 유용한 도구지만, 항상 데이터의 특성과 분석 목적을 고려해서 적절한 옵션을 설정하는 것이 중요해요! 다양한 옵션들을 조절해보면서 최적의 모델을 찾아보는 연습을 꾸준히 해보면 좋을 것 같아요!

 

rpart.plot() 시각화

의사결정 나무 모델을 만들었다면, 이제 그 결과를 눈으로 확인해야겠죠? 복잡한 규칙들을 한눈에 파악하기 쉽게 그림으로 나타내는 게 정말 중요해요! 바로 여기서 `rpart.plot()` 함수가 등장합니다! `rpart()` 함수로 만든 모델을 예쁘고 보기 쉽게 시각화해주는 아주 강력한 도구랍니다.

`rpart.plot()` 함수는 다양한 옵션을 제공해서, 사용자의 입맛에 딱 맞는 시각화를 만들 수 있도록 도와줘요. 기본적인 나무 구조부터, 각 노드의 예측값, 분할 기준, 그리고 더 나아가 복잡한 통계 정보까지! 원하는 정보를 보기 좋게 표시할 수 있으니 정말 편리하죠?!

자, 그럼 `rpart.plot()` 함수의 다양한 옵션들을 하나씩 살펴볼까요? 마치 마법 상자를 여는 것처럼 신나는 경험이 될 거예요!

`rpart.plot()` 함수의 다양한 옵션

1. type: 이 옵션은 나무의 모양을 결정하는 중요한 역할을 해요. 0부터 5까지의 숫자로 다양한 스타일을 지정할 수 있답니다. 0은 기본적인 나무 구조를, 1은 노드에 분할 기준을 추가하고, 2는 예측값을 표시해 줘요. 3은 1과 2를 합친 형태이고, 4는 확률 정보를, 5는 4에 추가로 클래스 레이블까지 표시해준답니다! 각각의 옵션을 직접 사용해보면서 어떤 차이가 있는지 확인해보는 것도 재미있을 거예요~!

2. extra: 이 옵션은 노드에 표시되는 추가 정보를 설정해요. 숫자와 문자를 조합해서 원하는 정보를 표시할 수 있죠! 예를 들어, extra=101을 설정하면 노드에 케이스 수, 예측값, 그리고 분할 기준을 함께 표시해준답니다. 마치 마법의 주문처럼 다양한 조합을 시도해보세요!

3. fallen.leaves: 이 옵션은 나무의 잎사귀(terminal node)를 아래쪽으로 정렬할지 여부를 결정해요. TRUE로 설정하면 잎사귀들이 가지런히 정렬되어 보기 좋게 표시되고, FALSE로 설정하면 원래 위치에 그대로 표시된답니다. 깔끔한 시각화를 원한다면 TRUE로 설정하는 것을 추천해요!

4. branch: 이 옵션은 가지의 모양을 조절해요. 0은 수직으로, 1은 대각선으로, 0.5는 중간 형태로 표시해준답니다. 취향에 따라 원하는 스타일을 선택해서 나무의 모양을 바꿔보세요!

5. shadow.col: 이 옵션은 그림자 색상을 지정해요. 기본값은 “gray”이지만, 원하는 색상을 지정해서 나무에 깊이감을 더할 수 있어요. “pink”나 “lightblue”처럼 화사한 색상으로 나무를 꾸며보는 것도 재미있을 거예요!

6. box.palette: 이 옵션은 노드의 색상 팔레트를 설정해요. “auto”, “heat”, “gray” 등 다양한 옵션을 제공하고, 사용자 정의 팔레트를 사용할 수도 있답니다. 데이터의 특성에 맞는 색상 팔레트를 선택해서 정보를 더욱 효과적으로 전달해보세요! “BuRd”나 “GnYlRd”와 같은 RColorBrewer 패키지의 팔레트를 사용하면 더욱 다채로운 시각화를 만들 수 있어요!

7. tweak: 이 옵션은 텍스트 크기를 조절해요. 1보다 큰 값을 설정하면 텍스트가 커지고, 1보다 작은 값을 설정하면 텍스트가 작아진답니다. 적절한 크기로 조절해서 가독성을 높여보세요!

`rpart.plot()` 활용 예시

자, 이제 `rpart.plot()` 함수의 다양한 옵션들을 살펴봤으니, 실제로 어떻게 활용하는지 예시를 통해 알아볼까요?

library(rpart)
library(rpart.plot)

# 데이터 생성 (예시)
data <- data.frame(
  x1 = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
  x2 = c(10, 9, 8, 7, 6, 5, 4, 3, 2, 1),
  y = factor(c("A", "A", "A", "B", "B", "B", "A", "A", "B", "B"))
)

# 의사결정 나무 모델 생성
model <- rpart(y ~ ., data = data, method = "class")

# 기본적인 나무 시각화
rpart.plot(model)

# 다양한 옵션을 사용한 시각화
rpart.plot(model, type = 3, extra = 101, fallen.leaves = TRUE, branch = 0.5, shadow.col = "lightblue", box.palette = "BuRd", tweak = 1.2)

위 코드에서 box.palette = "BuRd" 처럼 RColorBrewer 패키지의 팔레트를 사용했는데요, 만약 해당 패키지가 설치되어 있지 않다면 install.packages("RColorBrewer") 명령어를 통해 설치 후 사용하실 수 있답니다. 다양한 옵션들을 조합해서 자신만의 스타일로 나무를 꾸며보세요! 마치 예술 작품을 만드는 것처럼 즐거운 시간을 보낼 수 있을 거예요!

`rpart.plot()` 함수는 단순히 나무를 그리는 것 이상의 기능을 제공해요. 다양한 옵션을 통해 모델의 결과를 더욱 깊이 있게 이해하고, 중요한 정보를 효과적으로 전달할 수 있도록 도와준답니다. 이제 `rpart.plot()` 함수를 자유자재로 활용해서 데이터 분석의 마법사가 되어보세요~!

 

실제 데이터 활용 예시

자, 이제 드디어! 배운 rpart()rpart.plot() 함수를 실제 데이터에 적용해 볼 시간이에요! 두근두근~? 이론만으론 감이 잘 안 왔던 부분들이 싹~ 해소될 거예요.^^ 여기서는 여러분도 쉽게 따라 해 볼 수 있도록, R에 기본적으로 내장된 iris 데이터셋을 사용하겠습니다. iris 데이터는 붓꽃의 종류(setosa, versicolor, virginica)와 꽃받침 길이(Sepal.Length), 꽃받침 너비(Sepal.Width), 꽃잎 길이(Petal.Length), 꽃잎 너비(Petal.Width)를 포함하고 있어요. 데이터 분석 입문자들에게는 정말 친숙한 데이터죠?!

데이터 살펴보기

먼저, iris 데이터를 불러와서 어떤 구조로 되어 있는지 살펴볼까요? head() 함수를 사용하면 데이터의 앞부분을 살짝 엿볼 수 있답니다. str() 함수는 데이터의 구조와 각 변수의 타입을 보여주고요. summary() 함수는 각 변수의 통계적 요약 정보(평균, 중앙값, 최솟값, 최댓값 등)를 제공해 줍니다. 이 세 가지 함수는 데이터 분석의 시작점이라고 할 수 있어요! 꼭 기억해 두세요~

head(iris)
str(iris)
summary(iris)

의사결정 나무 모델 생성 및 시각화

이제 본격적으로 의사결정 나무 모델을 만들어 봅시다! 우리의 목표는 붓꽃의 종류(Species)를 예측하는 거예요. rpart() 함수를 사용해서 모델을 만들고, rpart.plot() 함수로 시각화까지 해볼게요!

library(rpart)
library(rpart.plot)

# 의사결정 나무 모델 생성
model <- rpart(Species ~ ., data = iris, method = "class")

# 모델 시각화
rpart.plot(model, type = 3, extra = 101, fallen.leaves = TRUE, cex = 0.8, main = "Iris 데이터 의사결정 나무")

rpart() 함수에서 Species ~ .는 Species 변수를 제외한 모든 변수를 예측 변수로 사용한다는 의미입니다. method = "class"는 분류 모델을 생성한다는 것을 명시하는 거고요. rpart.plot() 함수의 type = 3은 노드에 분할 조건과 예측 클래스를 표시해주고, extra = 101은 각 노드에 클래스 비율과 예측 클래스를 함께 표시해 줍니다. fallen.leaves = TRUE는 터미널 노드를 아래로 정렬해서 보기 좋게 만들어 주고, cex = 0.8은 글자 크기를 조정하는 옵션이에요. 마지막으로 main은 그래프 제목을 지정하는 부분이랍니다.

짠! 결과를 보면, Petal.Length (꽃잎 길이) 2.45cm를 기준으로 첫 번째 분할이 이루어지는 것을 알 수 있어요. 2.45cm보다 작으면 setosa 종으로 예측하고, 크면 Petal.Width(꽃잎 너비) 1.75cm를 기준으로 다시 한번 분할이 이루어지죠. 이처럼 의사결정 나무는 데이터를 반복적으로 분할하면서 예측 정확도를 높여간답니다. 정말 신기하지 않나요?!

모델 성능 평가

자, 그럼 이 모델의 성능은 얼마나 좋을까요? predict() 함수를 사용해서 예측값을 생성하고, table() 함수로 혼동 행렬(Confusion Matrix)을 만들어서 확인해 볼 수 있어요. 혼동 행렬은 모델의 예측 성능을 평가하는 데 유용한 도구랍니다!

# 예측값 생성
predictions <- predict(model, iris, type = "class")

# 혼동 행렬 생성
confusion_matrix <- table(iris$Species, predictions)

# 혼동 행렬 출력
print(confusion_matrix)

# 정확도 계산
accuracy <- sum(diag(confusion_matrix)) / sum(confusion_matrix)
print(paste("정확도:", accuracy))

iris 데이터를 사용해서 모델을 만들고 예측까지 해봤는데, 어떠셨나요? 처음에는 조금 어려워 보였지만, 하나씩 따라 해 보니 생각보다 간단하죠? 이제 여러분도 rpart()rpart.plot() 함수를 활용해서 다양한 데이터를 분석하고, 예측 모델을 만들 수 있을 거예요! 다음에는 더욱 흥미로운 주제로 찾아올게요! 기대해 주세요~! 😊

 

자, 이렇게 R을 이용해서 의사결정 나무를 만들고 예쁘게 시각화하는 방법까지 알아봤어요! 어때요, 생각보다 어렵지 않았죠? rpart() 함수와 rpart.plot() 함수만 잘 기억하면 데이터 분석에 날개를 달아줄 강력한 도구를 얻은 거나 다름없답니다. 처음엔 복잡해 보일 수 있지만, 몇 번 연습하다 보면 금방 익숙해질 거예요. 실제 데이터를 가지고 직접 분석해보면서 데이터 속 숨겨진 이야기를 발견하는 재미를 느껴보세요. 데이터 분석의 세계는 정말 흥미진진하니까요! 다음에는 더 재밌는 분석 기법 이야기로 돌아올게요. 그때까지 즐거운 분석 시간 보내세요!

 


코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다