본문 바로가기
인과관계분석

의사결정나무(Decision Tree) with R

by 다빈치스탁 2020. 9. 10.
728x90
반응형

의사결정나무는 기존의 다변량분석기법(로짓회귀, 선형회귀, 주성분, 요인 등)과 비교하여 비교적 직관적인 표를 이용하여 분석하고자 하는 방법이다. 분석의 대상이 연속형 자료인가 범주형 자료인가에 따라 회귀트리, 분류트리로 구분된다. 통계적 분석에서 봤을 때 크게 군집분석의 한 종류로도 볼 수 있다. 

 

우선 트리의 구조는 회귀트리, 분류트리 할 것 없이 기본적으로는 루트마디, 자식마디, 부모마디, 끝 마디, 중간마디, 가지, 깊이 등으로 구성된다. 그냥 임의로 자료를 분류하거나 예측하는 것이 아니라 일정한 규칙 예를 들면 가지의 분기기분, 중지규칙, 가지치기 규칙 등에 따라 필요한 통계량이 각 각 다르다.

 

노드를 분류하는 핵심은 부모노드에서 자식노드로 분기할 때 무슨 변수를 어떻게 분류하여 구분하는 것이 결과를 가장 잘 설명할 수 있는가하는 것이다. 이때 결과의 분포를 구별할 수 있는 기준으로 순수도 혹은 비순수도를 이용한다. 이때 이산형 변수(범주)의 경우 카이제곱 통계량, 지니계수, 엔트로피 지수 등을 이용하고 연속형 변수일 경우 F통계량, 분산감소량 등을 분기의 기준으로 적용한다. 그리고 노드를 분류한 후에 노드가 너무 많으면 예측오차가 커질 위험 즉 과적합의 위험이 존재하기 때문에 중간 중간 분기를 중지하는 규칙과 불필요한 노드를 날려버리는 가지치기 과정도 함께 적용되는데 이를 재귀적 분할(Recursive partitioning)이라고 표현하기도 한다.

 

자, 적당히 알아봤으면 이제 늘 그래왔듯이 실전으로 돌입하자. 우리가 실험해 볼 건 뭐냐? 코스피 지수가 오르고 코스닥 지수는 내리고 반도체는 올랐을 때 삼성전자의 주가는 오를 것인가? 아닐 것인가? 라는 트리를 한번 만들어보자.

R 에서 의사결정트리는 rpart라는 패키지에 있으니 라이브러리를 통해서 불러와서 수행하자. 그전에 우선 삼성정자의 주가가 상승일 경우 2, 하락일 경우 1이라고 변형이 필요하다. 귀찮은 사람은 첨부된 엑셀파일을 다운로드 하자. 모델은 변수를 업종지수 22개를 다 주고, 방법은 클래스(분류)라고 정의해서 나무를 호출한다. summary 를 해석하자면 우선 가장 처음에 cp와 에러가 나오는데 이건 가지치기를 어느 수준에서 할 것인가를 결정하는 지표가 된다. 통상 xerror 중 가장 낮은 값 + xstd의 값을 더해준 값을 기준으로 이보다 큰 xerror를 가지는 cp를 기준으로 가지치기가 들어간다는 점만 알아두자. 지금 분석한 값으로는 0.41+0.03 = 0.44 인데 이보다 큰 에러를 가지는 트리가 없다. 따라서 가지치기의 기준 cp는 0.01이 된다. 하나마나 똑같은 결과가 도출된다.(<-가지치기 할 필요 없다는 뜻)

 

#작업경로를 지정하는 명령어
setwd("")

#데이터 끌어오기(중회귀자료, 다수의 독립변수와 하나의 종속변수)
mydatat<-read.csv("tree.csv",
                  header=TRUE, na.strings = "")
mydatat
str(mydatat)

library(rpart)
rt=rpart(mydatat$삼성전자~.,data=mydatat[,1:22], method="class")

summary(rt)
plot(rt,branch = 0.5, margin = 0.05)
text(rt,use.n = T, all = T, cex=0.9)

> summary(rt)
Call:
rpart(formula = mydatat$삼성전자 ~ ., data = mydatat[, 1:22], 
    method = "class")
  n= 498 

          CP nsplit rel error    xerror       xstd
1 0.60493827      0 1.0000000 1.0000000 0.04590419
2 0.02057613      1 0.3950617 0.4032922 0.03651086
3 0.01234568      5 0.2839506 0.3868313 0.03593633
4 0.01000000      7 0.2592593 0.4156379 0.03692623

Variable importance
  IT소프트 코스피지수     반도체 화학에너지   서비스업       증권 소비자유통 코스닥지수 비은행금융       철강     바이오       조선       건설 
        22         19         12         10         10          9          5          3          2          2          1          1          1 
    자동차 미디어통신   섬유의복 
         1          1          1 

Node number 1: 498 observations,    complexity param=0.6049383
  predicted class=2  expected loss=0.4879518  P(node) =1
    class counts:   243   255
   probabilities: 0.488 0.512 
  left son=2 (281 obs) right son=3 (217 obs)
  Primary splits:
      IT소프트   < 0.00335724   to the left,  improve=96.55675, (0 missing)
      코스피지수 < 7.57e-05     to the left,  improve=85.68884, (0 missing)
      반도체     < -0.003747402 to the left,  improve=52.02774, (0 missing)
      증권       < -0.004591294 to the left,  improve=40.98657, (0 missing)
      소비자유통 < 0.004121344  to the left,  improve=40.04531, (0 missing)
  Surrogate splits:
      코스피지수 < 0.002298838  to the left,  agree=0.847, adj=0.650, (0 split)
      반도체     < 0.001206254  to the left,  agree=0.801, adj=0.544, (0 split)
      화학에너지 < 0.004479706  to the left,  agree=0.767, adj=0.465, (0 split)
      증권       < 0.001271489  to the left,  agree=0.733, adj=0.387, (0 split)
      서비스업   < 0.003003634  to the left,  agree=0.731, adj=0.382, (0 split)

Node number 2: 281 observations,    complexity param=0.02057613
  predicted class=1  expected loss=0.2384342  P(node) =0.564257
    class counts:   214    67
   probabilities: 0.762 0.238 
  left son=4 (116 obs) right son=5 (165 obs)
  Primary splits:
      코스피지수 < -0.006111428 to the left,  improve=13.773540, (0 missing)
      IT소프트   < -0.01382807  to the left,  improve=12.073920, (0 missing)
      반도체     < -0.009923348 to the left,  improve= 6.793776, (0 missing)
      은행       < -0.006029242 to the left,  improve= 6.693370, (0 missing)
      비은행금융 < -0.01178995  to the left,  improve= 4.970603, (0 missing)
  Surrogate splits:
      IT소프트   < -0.008722322 to the left,  agree=0.865, adj=0.672, (0 split)
      비은행금융 < -0.006897129 to the left,  agree=0.826, adj=0.578, (0 split)
      소비자유통 < -0.005671154 to the left,  agree=0.822, adj=0.569, (0 split)
      철강       < -0.007350589 to the left,  agree=0.815, adj=0.552, (0 split)
      증권       < -0.01511581  to the left,  agree=0.804, adj=0.526, (0 split)

Node number 3: 217 observations,    complexity param=0.01234568
  predicted class=2  expected loss=0.1336406  P(node) =0.435743
    class counts:    29   188
   probabilities: 0.134 0.866 
  left son=6 (110 obs) right son=7 (107 obs)
  Primary splits:
      코스피지수 < 0.007001882  to the left,  improve=5.578160, (0 missing)
      전기가스   < -0.001511241 to the left,  improve=4.252753, (0 missing)
      소비자유통 < 0.003542663  to the left,  improve=4.008538, (0 missing)
      IT소프트   < 0.01390074   to the left,  improve=3.146409, (0 missing)
      보험       < -0.004780799 to the left,  improve=2.850419, (0 missing)
  Surrogate splits:
      조선       < 0.006632444  to the left,  agree=0.788, adj=0.570, (0 split)
      코스닥지수 < 0.00699158   to the left,  agree=0.774, adj=0.542, (0 split)
      자동차     < 0.005928644  to the left,  agree=0.774, adj=0.542, (0 split)
      소비자유통 < 0.005145845  to the left,  agree=0.770, adj=0.533, (0 split)
      건설       < 0.008559888  to the left,  agree=0.765, adj=0.523, (0 split)

Node number 4: 116 observations
  predicted class=1  expected loss=0.05172414  P(node) =0.2329317
    class counts:   110     6
   probabilities: 0.948 0.052 

Node number 5: 165 observations,    complexity param=0.02057613
  predicted class=1  expected loss=0.369697  P(node) =0.3313253
    class counts:   104    61
   probabilities: 0.630 0.370 
  left son=10 (101 obs) right son=11 (64 obs)
  Primary splits:
      코스닥지수 < -0.001696954 to the right, improve=9.084160, (0 missing)
      바이오     < -0.003282421 to the right, improve=8.540047, (0 missing)
      화학에너지 < -0.007441816 to the right, improve=6.519620, (0 missing)
      서비스업   < 0.002701432  to the right, improve=5.824242, (0 missing)
      소비자유통 < -0.005579308 to the right, improve=4.983854, (0 missing)
  Surrogate splits:
      바이오     < -0.006135014 to the right, agree=0.855, adj=0.625, (0 split)
      반도체     < -0.005503724 to the right, agree=0.721, adj=0.281, (0 split)
      코스피지수 < -0.003020294 to the right, agree=0.715, adj=0.266, (0 split)
      미디어통신 < -0.006666027 to the right, agree=0.715, adj=0.266, (0 split)
      화학에너지 < -0.007159398 to the right, agree=0.697, adj=0.219, (0 split)

Node number 6: 110 observations,    complexity param=0.01234568
  predicted class=2  expected loss=0.2454545  P(node) =0.2208835
    class counts:    27    83
   probabilities: 0.245 0.755 
  left son=12 (12 obs) right son=13 (98 obs)
  Primary splits:
      서비스업   < 0.01233842   to the right, improve=6.857699, (0 missing)
      코스닥지수 < 0.01434746   to the right, improve=4.392513, (0 missing)
      운송       < 0.00995246   to the right, improve=4.139174, (0 missing)
      음식료     < 0.002222451  to the right, improve=3.927273, (0 missing)
      건설       < 0.01905902   to the right, improve=3.286370, (0 missing)
  Surrogate splits:
      음식료     < 0.01808206   to the right, agree=0.918, adj=0.250, (0 split)
      미디어통신 < 0.01711463   to the right, agree=0.909, adj=0.167, (0 split)
      은행       < -0.0231178   to the left,  agree=0.900, adj=0.083, (0 split)

Node number 7: 107 observations
  predicted class=2  expected loss=0.01869159  P(node) =0.2148594
    class counts:     2   105
   probabilities: 0.019 0.981 

Node number 10: 101 observations
  predicted class=1  expected loss=0.2376238  P(node) =0.2028112
    class counts:    77    24
   probabilities: 0.762 0.238 

Node number 11: 64 observations,    complexity param=0.02057613
  predicted class=2  expected loss=0.421875  P(node) =0.1285141
    class counts:    27    37
   probabilities: 0.422 0.578 
  left son=22 (49 obs) right son=23 (15 obs)
  Primary splits:
      코스피지수 < 0.0003948395 to the left,  improve=6.973852, (0 missing)
      소비자유통 < -0.005579308 to the right, improve=5.510417, (0 missing)
      반도체     < -0.006408944 to the left,  improve=4.014828, (0 missing)
      화학에너지 < -0.007441816 to the right, improve=3.863772, (0 missing)
      섬유의복   < -0.001907677 to the left,  improve=3.226570, (0 missing)
  Surrogate splits:
      건설       < 0.01107884   to the left,  agree=0.844, adj=0.333, (0 split)
      조선       < 0.008716517  to the left,  agree=0.844, adj=0.333, (0 split)
      화학에너지 < 0.003984455  to the left,  agree=0.828, adj=0.267, (0 split)
      철강       < 0.01208162   to the left,  agree=0.828, adj=0.267, (0 split)
      소비자유통 < 0.00741039   to the left,  agree=0.828, adj=0.267, (0 split)

Node number 12: 12 observations
  predicted class=1  expected loss=0.25  P(node) =0.02409639
    class counts:     9     3
   probabilities: 0.750 0.250 

Node number 13: 98 observations
  predicted class=2  expected loss=0.1836735  P(node) =0.1967871
    class counts:    18    80
   probabilities: 0.184 0.816 

Node number 22: 49 observations,    complexity param=0.02057613
  predicted class=1  expected loss=0.4489796  P(node) =0.09839357
    class counts:    27    22
   probabilities: 0.551 0.449 
  left son=44 (35 obs) right son=45 (14 obs)
  Primary splits:
      소비자유통 < -0.006424467 to the right, improve=9.016327, (0 missing)
      화학에너지 < -0.007441816 to the right, improve=7.195775, (0 missing)
      은행       < -0.000741164 to the right, improve=6.887755, (0 missing)
      비은행금융 < -4.5116e-05  to the right, improve=6.319408, (0 missing)
      운송       < -0.009641525 to the right, improve=4.444898, (0 missing)
  Surrogate splits:
      반도체     < 0.001724638  to the left,  agree=0.816, adj=0.357, (0 split)
      비은행금융 < -0.007709394 to the right, agree=0.796, adj=0.286, (0 split)
      서비스업   < -0.009099204 to the right, agree=0.796, adj=0.286, (0 split)
      섬유의복   < -0.01665632  to the right, agree=0.796, adj=0.286, (0 split)
      자동차     < -0.009287947 to the right, agree=0.776, adj=0.214, (0 split)

Node number 23: 15 observations
  predicted class=2  expected loss=0  P(node) =0.03012048
    class counts:     0    15
   probabilities: 0.000 1.000 

Node number 44: 35 observations
  predicted class=1  expected loss=0.2571429  P(node) =0.07028112
    class counts:    26     9
   probabilities: 0.743 0.257 

Node number 45: 14 observations
  predicted class=2  expected loss=0.07142857  P(node) =0.02811245
    class counts:     1    13
   probabilities: 0.071 0.929 

 

자 그러면 위의 해석은 아래의 그림과 함께 봐야 이해가 쉽다. 우선 첫 번째 노드(루트)에서 IT소프트가 0.3% 이하일 경우의 수는 488개 중 243개, 0.3%이상 상승할 경우의 수는 255개로 분석되었다. summary 처음에 나와 있는 probil... 값을 확인하면 대략 49% : 51% 정도 된다. 

 

두 번째 노드에서 조금 덜 복잡한 방향인 오른쪽(아니오, 0.3%이상일 경우)으로 가보면 코스피 지수가 0.7% 이하(summary node 3)일 경우(예, 왼쪽)와 이상일 경우(오른쪽, 아니오)로 갈리게 된다. 자 이제 IT소프트가 0.3% 이상 상승하고 코스피가 0.7%이상 상승할 때 삼성전자의 주가는 107개의 경우의 수(summary node 7)에서 105번 상승(거의 99%)한다고 분석하고 있다. 

 

자 이러한 방식으로 의사결정트리를 해석해 나갈 수 있다. 통상 의사결정 트리를 가지고 무언가를 예측하는데에는 별로 사용하지 않는다. 예측의 방법으로는 회귀분석, SVM 등의 방법이 더 효과적이기 때문이지. 그러나 아래의 결과를 통해 우리는 또 한 가지 새로운 사실을 알 수 있다. 반도체 업종이 최상위로 갈 것이라 생각했는데 그게 아니라 IT소프트를 루트노드로 가지고 있다는 점. 곰곰히 한번 생각해보자. IT소프트의 발달과 반도체 제조업간에 무슨 연관관계가 있겠는가? 매우 많다. 지난 2016년 말부터 액면분할하기 전까지 삼성전자의 주가는 80만원에서 300만원까지 끊임없이 상승해왔다. 왜?? 갑자기 반도체 수요가 증가해서?? 그럼 반도체는 왜 갑자기 수요가 증가했을까?? 그 배경에는 [머신러닝]이라는 새로운 IT기술이 등장했기때문이지. 기존의 IT와는 다르게 빅데이터를 다루는 머신러닝은 엄청난 메모리 수요을 가져왔고 그에 따라 삼성전자나 SK하이닉스 같은 업체는 엄청난 반사이익을 거두었기때문에 매 분기 어닝서프라이즈의 연속을 기록했고 그에 따라 주가도 쉼없이 상승해왔다.

그렇다. 단순히 데이터(수치형자료)만 분석해도 이렇게 정성적 직관을 얻는데 도움이 될만한 것들을 충분히 건질 수 있다. 이제 의사결정트리는 여기까지 할건데 prune(가지치기)을 안하고 넘어가면 섭섭하니 아래 소스코드 전문을 올려둔다. cp 를 선정하는 기준은 위에 설명을 해놓았기때문에 아래의 코드를 참고해서 여러가지 데이터로 실험해보면 좋을 듯 하다.

 

#작업경로를 지정하는 명령어
setwd("")

#데이터 끌어오기(중회귀자료, 다수의 독립변수와 하나의 종속변수)
mydatat<-read.csv("tree.csv",
                  header=TRUE, na.strings = "")
mydatat
str(mydatat)

library(rpart)
rt=rpart(mydatat$삼성전자~.,data=mydatat[,1:22], method="class")

summary(rt)
plot(rt,branch = 0.5, margin = 0.05)
text(rt,use.n = T, all = T, cex=0.9)

#가지치기
rt2<-prune(rt, cp=0.01)
plot(rt2,branch = 0.5, margin = 0.05)
text(rt2,use.n = T, all = T, cex=0.9)
summary(rt2)

tree.csv
0.13MB

728x90
반응형

댓글