> 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 |