분류앙상블 – 배깅, 부스팅, 랜덤 포레스트
1) 데이터 입력
> setwd('c:/Rwork')
> german=read.table('germandata.txt',header=T)
> german$numcredits = factor(german$numcredits)
> german$residence = factor(german$residence)
> german$residpeople = factor(german$residpeople)
2) 랜덤 포레스트 방법의 실행
> library(randomForest)
> rf.german<-randomForest(y~.,data=german,ntree=100,mytr=5,importance=T,na.action = na.omit)
> summary(rf.german)
Length Class Mode
call 7 -none- call
type 1 -none- character
predicted 1000 factor numeric
err.rate 300 -none- numeric
confusion 6 -none- numeric
votes 2000 matrix numeric
oob.times 1000 -none- numeric
classes 2 -none- character
importance 80 -none- numeric
importanceSD 60 -none- numeric
localImportance 0 -none- NULL
proximity 0 -none- NULL
ntree 1 -none- numeric
mtry 1 -none- numeric
forest 14 -none- list
y 1000 factor numeric
test 0 -none- NULL
inbag 0 -none- NULL
terms 3 terms call
함수 설명:
randomForest(y~.,data=german,ntree=100,mytr=5,importance=T,na.action = na.omit ntree는 랜덤포레스트 방법에서 생성하게 될 분류기의 개수 B이다. 100개의 분류기는 분류나무를 이용하여 생성되도록 하였다. mtry는 중간노드마다 랜덤하게 선택되는 변수의 개수를 의미한다. 5개의 입력변수를 중간노드마다 모두 선택하고 이 중에서 분할점이 탐색되도록 하였다. importance는 변수의 중요도를 계산하는 옵션이고, na.action은 결측치를 처리하는 방법에 대한 사항이다. 변수의 중요도를 계산하게 하고, 결측치는 필요한 경우에만 삭제되도락 하였다.
2) 랜덤 포레스트 방법의 실행 – 변수 중요도 보기
> names(rf.german)
[1] "call" "type" "predicted" "err.rate" "confusion"
[6] "votes" "oob.times" "classes" "importance" "importanceSD"
[11] "localImportance" "proximity" "ntree" "mtry" "forest"
[16] "y" "test" "inbag" "terms"
> head(rf.german$predicted,10) #데이터의 예측집단을 출력
1 2 3 4 5 6 7 8 9 10
good bad good bad bad good good good good bad
Levels: bad good
> importance(rf.german)
bad good MeanDecreaseAccuracy MeanDecreaseGini
check 13.14268724 9.63208341 15.1106884 44.838547
duration 3.33563217 8.10482760 8.6281030 41.273512
history 3.87863720 4.50449203 5.8685013 25.731461
purpose 2.67025503 3.09871408 4.1078354 35.651165
credit 2.44312087 4.16670498 4.8800356 52.641745
savings 7.48182326 2.84190645 6.1879918 21.705909
employment 1.91049595 2.70568977 3.2416484 23.910509
installment 0.02100147 3.49542966 3.0522029 15.714499
personal 2.10802207 1.83819513 3.0602966 15.365475
debtors -0.17277289 4.39384503 3.8963219 6.718969
residence 0.74571096 0.90284661 1.1155901 17.932937
property 2.16016716 3.85454658 4.7010080 18.803008
age 2.69637542 4.35170316 5.4753585 41.451103
others 0.31569112 3.60499256 3.3679530 11.399935
housing 2.70314243 2.06074416 3.0737900 9.596539
numcredits -0.24996827 0.95259106 0.6502566 7.944861
job 1.53070574 1.18486660 2.1420488 12.054190
residpeople 0.88657814 -0.43166449 0.1370845 4.234831
telephone 1.46824003 -0.24200291 0.6110284 6.427048
foreign 1.26297478 -0.05431566 0.5733125 1.519832
> importance(rf.german,type=1)
MeanDecreaseAccuracy
check 15.1106884
duration 8.6281030
history 5.8685013
purpose 4.1078354
credit 4.8800356
savings 6.1879918
employment 3.2416484
installment 3.0522029
personal 3.0602966
debtors 3.8963219
residence 1.1155901
property 4.7010080
age 5.4753585
others 3.3679530
housing 3.0737900
numcredits 0.6502566
job 2.1420488
residpeople 0.1370845
telephone 0.6110284
foreign 0.5733125
결과 해석: check가 가장 중요하고 duration이 두번째로 중요
> order(importance(rf.german)[,'MeanDecreaseAccuracy'],decreasing = T)
[1] 1 2 6 3 13 5 12 4 10 14 7 15 9 8 17 11 16 19 20 18
> which.max(importance(rf.german)[,'MeanDecreaseAccuracy'])
check
1
> importance(rf.german)[which.max(importance(rf.german)[,'MeanDecreaseAccuracy']),]
bad good MeanDecreaseAccuracy MeanDecreaseGini
13.142687 9.632083 15.110688 44.838547
> rf.german$importance
bad good MeanDecreaseAccuracy MeanDecreaseGini
check 5.728619e-02 2.488337e-02 3.461467e-02 44.838547
duration 1.262784e-02 2.059686e-02 1.820397e-02 41.273512
history 1.165482e-02 8.234252e-03 9.100115e-03 25.731461
purpose 1.001589e-02 5.877403e-03 7.125436e-03 35.651165
credit 8.957835e-03 9.469900e-03 9.342178e-03 52.641745
savings 1.873739e-02 4.572813e-03 8.795598e-03 21.705909
employment 5.377379e-03 4.391391e-03 4.647218e-03 23.910509
installment 5.083834e-05 4.492258e-03 3.109720e-03 15.714499
personal 4.903039e-03 2.481005e-03 3.188303e-03 15.365475
debtors -1.380717e-04 3.198633e-03 2.202015e-03 6.718969
residence 1.833243e-03 1.342976e-03 1.400876e-03 17.932937
property 6.357328e-03 5.871030e-03 6.069060e-03 18.803008
age 1.026633e-02 8.969565e-03 9.239623e-03 41.451103
others 6.321219e-04 4.940365e-03 3.562374e-03 11.399935
housing 5.086080e-03 2.740150e-03 3.358222e-03 9.596539
numcredits -3.793953e-04 7.653351e-04 4.256327e-04 7.944861
job 2.803065e-03 1.422938e-03 1.912685e-03 12.054190
residpeople 9.171770e-04 -2.801992e-04 7.286163e-05 4.234831
telephone 2.173474e-03 -2.108124e-04 4.743466e-04 6.427048
foreign 5.935867e-04 -1.538455e-05 1.547421e-04 1.519832
추가:
rf.german$importance #이건 importance(rf.german) 의 결과와 어떻게 다른지 좀 더 공부하자
3) 분류예측치를 구하고 정확도 평가
> pred.rf.german<-predict(rf.german,newdata=german)
> head(pred.rf.german,10)
1 2 3 4 5 6 7 8 9 10
good bad good good bad good good good good bad
Levels: bad good
> tab=table(german$y,pred.rf.german,dnn=c("Actual","Predicted"))
> tab
Predicted
Actual bad good
bad 300 0
good 0 700
> addmargins(tab)
Predicted
Actual bad good Sum
bad 300 0 300
good 0 700 700
Sum 300 700 1000
> 1-sum(diag(tab)/sum(tab))
[1] 0
결과 해석: 기존 cart 분류나무 모형 오분류율은 19.6%, 배깅은 3.7%, 부스팅은 22.6%인 반면
랜덤 포레스트는 오분류율이 0%로 기존 그 어떠한 모형보다 대단히 우수한 결과를 보임을 알 수 있다
(분류나무 cart 모형 바로가기) / (분류앙상블 모형 – 배깅 바로가기) / (분류앙상블 모형 – 부스팅 바로가기)
4) 몇개의 분류기가 적당할까?
> plot(rf.german,'l')
결과 해석: x축은 분류기, y축은 OOB 오분류율을 의미 out of bag의 약자로 부트스트랩에 포함되지 못한 데이터를 의미. 결국 oob데이터는 검증데이터의 역할과 비슷. 가장 아래선은 목표변수 중 good에 대한 오분율, 가장 위쪽 선은 bad에 대한 오분율. 가운데는 전체 오분류율. 그림에 따르면 분류기 개수가 80개이상이면 안정적인 형태로 보인다
5) 훈련 데이터와 검증데이터로 분할하여 랜덤포레스트 방법을 평가해 보자.
> set.seed(1234)
> i=sample(1:nrow(german),round(nrow(german)*0.7)) #70% for training 훈련 data, 30% test 검증 데이
> german.train = german[i,]
> german.test = german[-i,]
> rf.train.german<-randomForest(y~.,data=german.train,ntree=100,mtry=5,importance=T,na.action = na.omit)
> pred.rf.train.german<-predict(rf.train.german,newdata=german.test)
> tab.train = table(german.test$y,pred.rf.train.german,dnn=c('Actual','Predicted'))
> tab.train
Predicted
Actual bad good
bad 39 60
good 15 186
> addmargins(tab.train)
Predicted
Actual bad good Sum
bad 39 60 99
good 15 186 201
Sum 54 246 300
> 1-sum(diag(tab.train) / sum(tab.train)) #오분류율이 25%로 어느정도 향상
[1] 0.25
결과 해석: 검증데이터에 대한 오분류율은 기존 cart 분류 나무는 26.3%, 배깅 역시 26.3%, 부스팅은 25.3%. 랜덤포레스트는 25%로, 조금 향상 되었음.
(분류나무 cart 모형 바로가기) / (분류앙상블 모형 – 배깅 바로가기) / (분류앙상블 모형 – 부스팅 바로가기)
출처: 데이터마이닝(장영재, 김현중, 조형준 공저)
'KNOU > 2 데이터마이닝' 카테고리의 다른 글
제5장 신경망모형 - 분류 (5) | 2016.12.20 |
---|---|
제5장 신경망모형 - 회귀 (0) | 2016.11.14 |
제4장 앙상블 모형 - 분류앙상블모형 - 부스팅 (0) | 2016.11.07 |
제4장 앙상블 모형 - 분류앙상블모형 - 배깅 (0) | 2016.11.03 |
제4장 앙상블 모형 - 회귀앙상블모형 - 랜덤포레스트 (1) | 2016.11.02 |