Learning & Reasoning/R

rpart 패키지를 이용해 decision tree 만들기

이현봉 2013. 1. 25. 23:00


weather.csv

> library(rpart)   # rpart 패키지 로드

> library(rattle)   # rattle 패키지를 이용

> weatherDS = new.env()     # decision tree를 담을 environment 생성

> class(weatherDS)
[1] "environment


weather dataset을 읽음.  "weather.csv" 파일이 e: 드라이브에 있다고 가정

> weather = read.csv("e:/weather.csv") 

> dim(weather)       # weather : decision tree 적용 대상 dataset
[1] 366  24
> names(weather)
 [1] "Date"          "Location"      "MinTemp"       "MaxTemp"       "Rainfall"      "Evaporation" 
 [7] "Sunshine"      "WindGustDir"   "WindGustSpeed" "WindDir9am"    "WindDir3pm"    "WindSpeed9am"
[13] "WindSpeed3pm"  "Humidity9am"   "Humidity3pm"   "Pressure9am"   "Pressure3pm"   "Cloud9am"    
[19] "Cloud3pm"      "Temp9am"       "Temp3pm"       "RainToday"     "RISK_MM"       "RainTomorrow"

weather의 variable 중에서 Date, Location, RISK_MM 을 decision tree 만들 때 사용하지 않기로 함.  어떻게 하면 이 3개의 variable을 제외한 data.frame을 만들 수 있을까.  위의 결과를 보니 위치가 1, 2, 23에 있음.  따라서 이 3개이 variable을 제외한 "test" data.frame을 다음가 같이 간단히 만들 수도 있음.

> test = weather[ , -c(1,2,23)]
> names(test)                  # 3개의 variable이 없어짐
 [1] "MinTemp"       "MaxTemp"       "Rainfall"      "Evaporation"   "Sunshine"      "WindGustDir" 
 [7] "WindGustSpeed" "WindDir9am"    "WindDir3pm"    "WindSpeed9am"  "WindSpeed3pm"  "Humidity9am" 
[13] "Humidity3pm"   "Pressure9am"   "Pressure3pm"   "Cloud9am"      "Cloud3pm"      "Temp9am"     
[19] "Temp3pm"       "RainToday"     "RainTomorrow"
> dim(test)     # 확인
[1] 366  21

하지만 variable 들이 많거나 variable 위치가 찾기 힘들 때 패턴으로 찾을 수 있나?  grep을 씀.  data.frame의 variable 명을 이용해 다양한 data.frame 조작을 할 수 있음.

> grep("Rain", names(weather))         # 2번째 패러미터에서 "Rain"을 갖는 패턴을 모두 반환
[1]  5 22 24                             #  weather의 변수명 중 5, 22, 24번 변수가 Rain 패턴을 갖고 있음.

> grep("(Date|Locat|RISK)", names(weather))    # Date, Locat, or RISK 패턴을 찾음.  패턴은 empty space도 포함하므로 [1]  1  2 23                                                      # 찾으려믄 패턴을 정확히 표시하고 빈 칸을 두어서는 안됨.

evalq를 이용해 앞서 만든 weatherDS 환경에서 모델을 만든다.

> evalq({
+ data <- weather                 #  weather은 global scope에서 가져옴. data는 weatherDS scope
+ nobs <- nrow(data)            #  nobs에 data의 observation/row 숫자가 대응.  nobs = 366.
+ vars <- -grep('^(Date|Locat|RISK)', names(weather))     # vars에[ -1, -2, -23] vector가 대응. 
+ }, weatherDS)


> ls(weatherDS)             # weatherDS 환경에 있는 object들을 확인
[1] "data" "nobs" "vars"
> weatherDS$vars               // weather variable중 제외할 변수.  vector앞에 - 가 붙으면 인덱싱할 때 그 것들을 제외함.[1]  -1  -2 -23

weather가 갖고 있는 366개의 observation 중 임의의 70% 만 취해 이것으로 모델을 train 시킨다.  그리고는 formula 를 이용해 RainTomorrow 변수 값이 입력 변수 값에 따라 어떻게 되는지 예측하려함을 표시한다.

> evalq({
+ set.seed(42)
+ train <- sample(nobs, 0.7*nobs)
+ form <- formula(RainTomorrow ~ .)   # target var; RainTomorrow,  input var: RainTomorrow 외의 variable (categorical?)
+ }, weatherDS)

> length(weatherDS$train)          # 1 에서 366 숫자 사이에서 256 개의 숫자를 샘플링했다.
[1] 256

모델을 담을 environment를 별도로 weatherDS의 child로 만든다. 

> weatherRPART <- new.env(parent=weatherDS)   # weatherRPART에서 weatherDS에서 정의된 모든 R 객체 접근 가능

> evalq({
+ model <- rpart(formula=form, data=data[train, vars])    # data에 training set 가 들어감.
+ }, weatherRPART)

모델이 어떻게 되었는지...

> weatherRPART$model
n= 256             // 256개의 observation에 대해 모델

node), split, n, loss, yval, (yprob)    # split: decision 조건, n: 노드에 해당되는 row 수, loss: 판단미스, yval: default 판단
      * denotes terminal node

1) root 256 41 No (0.83984375 0.16015625)         #첫번째 root node: target=No를 기준으로 256개중의 41개가 아님(yes). 
  2) Pressure3pm>=1011.9 204 16 No (0.92156863 0.07843137)  # split조건에 만족하는 204개 중에 16개가 판단미스(yes)로
    4) Cloud3pm< 7.5 195 10 No (0.94871795 0.05128205) * 
    5) Cloud3pm>=7.5 9  3 Yes (0.33333333 0.66666667) *  # 기준판단이 yes. 0.67 probability of rain tomorrow. 
  3) Pressure3pm< 1011.9 52 25 No (0.51923077 0.48076923)  // 조건에 만족하는 52개 중에 0.519 확률로 맞게 No 이었음.
    6) Sunshine>=8.85 25  5 No (0.80000000 0.20000000) *
    7) Sunshine< 8.85 27  7 Yes (0.25925926 0.74074074) *   

간단히 plot 해 봄

> plot(weatherRPART$model)
> text(weatherRPART$model)

가장 오른쪽 leaf node가 7)번 노드.  즉 Pressure3pm< 1011.9 --> Sunshine< 8.85  path로 타고 왔음.  오후3시 기압이 1012보다 낮고, 맑음이 8.85보다 작으면 다음날 비가 올 확률이 74%.  이 노드가 커버한 것은 256개 관측중에 27개 이고, 그 중 7개 (26%)를 틀리게 (즉, 비가 오지 않음)으로 잘 못 분류하는 것으로 판명됨.   


'Learning & Reasoning > R ' 카테고리의 다른 글

AdaBoost  (0) 2013.02.01
random forest  (0) 2013.01.28
R 데이터 cleaning  (0) 2013.01.21
연습할 데이터 만들기  (0) 2013.01.19
Machine Learning과 데이터마이닝을 조금 더 심각하게...  (0) 2013.01.19