2020. 8. 2. 13:53ㆍADP | ADsP with R/Knowledge
Ensemble 모형에는 대표적으로 Bagging/RandomForest/Boosting이 있다. 이 앙상블 기법에 대한 개념적 설명은 아래 링크를 통해 남겨 놓겠다. 이번 게시글에는 R을 활용해 Bagging/RandomForest/Boosting을 실습하려고 한다.
Bagging/RandomForest
https://todayisbetterthanyesterday.tistory.com/48
Boosting
https://todayisbetterthanyesterday.tistory.com/49
1. Bagging
# 패키지 설치
install.packages("adabag")
# 라이브러리 & 데이터 로딩
library(adabag)
data(iris)
# Bagging model
iris.bagging <- bagging(Species~., data=iris, mfinal=10)
iris.bagging$importance
위에서 mfinal을 통해 10번 반복복원추출하여 학습한다고 명령하였다. 이를 통해 나온 변수의 중요도를 보면 위의 그림과 같다. 분류기의 분류기준을 보는 것은 아래 plot을 통해 직관적으로 볼 수 있다.
# 도식화
plot(iris.bagging$trees[[10]])
text(iris.bagging$trees[[10]])
위의 결과는 bagging 분류결과를 tree형태로 표현한 것이다. 변수 중요도 부분에서 봤던 Petal.Length와 Petal.Width가 분류기의 기준으로 작용한 것을 확인할 수 있다. 이제 이 모형의 정확성을 확인해보자.
# 예측값
pred <- predict(iris.bagging, newdata=iris)
# 정오분류표
table(pred$class, iris[,5])
예측 결과를 pred라는 변수에 넣었다. 그리고 이를 confusion_matrix,정오분류표로 표현하였다. 위의 결과를 보면 setosa의 경우는 50개 중에서 50개, versicolor는 54개 중에서 49개, virginica는 46개 중에서 45개를 정확하게 분류한 것을 볼 수 있다. 즉, 성능이 좋은 편이다. 물론 학습데이터가 그대로 예측에 사용되었기 때문일 수도 있다.
2. Boosting
# 라이브러리 & 데이터 로딩
library(adabag)
data(iris)
# boosting model
boo.adabag <- boosting(Species~., data=iris, boos=TRUE, mfinal=10)
boo.adabag$importance
위의 경우는 가장 기본적인 boosting기법 AdaBoost기법이다. 동일하게 bagging처럼 반복 복원추출과정을 거치면서, 각 step에서 잘못 분류된 데이터에 가중치를 부여하여 표본을 추출한다. 그 결과로 보았을 때, Sepal 변수의 중요도가 상승한 것을 알 수 있다.
# 도식화
plot(boo.adabag$trees[[10]])
text(boo.adabag$trees[[10]])
AdaBoosting의 Tree는 보다 더 leaf-wise하고, depth 또한 더 깊은 것을 확인할 수 있다.
# 예측값
pred <- predict(boo.adabag, newdata = iris)
# 정오분류표
tb <- table(pred$class,iris[,5])
tb
위의 경우는 bagging보다 더 좋은 성능을 보였다. 물론 train 데이터를 예측한 것이기에 Overfitting이 되었다고 볼 수도 있다.
# 오분류율
error.rpart <- 1-(sum(diag(tb)/sum(tb)))
error.rpart
위의 정오분류표에서 모두 잘 분류된것을 확인할 수 있었다. 그렇기에 오분류율 또한 0이다.
setosa의 경우는 항상 분류가 잘 되는 것을 보았다. 그렇기에 setosa를 제외하고 다시 boosting을 한 번 진행해보자. 아래의 실습에서는 ada 패키지의 ada()함수를 통해서 adaboosting을 진행할 것이다.
# Adaboost library
install.packages("ada")
library(ada)
# setosa 제외
data(iris)
iris[iris$Species != "setosa", ] -> iris
n <- dim(iris)[1]
# 60개의 train data / 40개의 test data
raind <- sample(1:n, floor(.6*n), FALSE)
testd <- setdiff(1:n, traind)
iris[,5] <- as.factor((levels(iris[,5])[2:3])[as.numeric(iris[,5])-1])
# Ada boost 훈련용 데아터로 모형구축
# test데이터에 대한 오분류율 0%
gdis <- ada(Species~., data=iris[traind,],iter=20, nu=1,type="discrete")
gdis <- addtest(gdis, iris[testd, -5], iris[testd, 5])
gdis
위의 결과를 plot, varplot, pais함수를 통해서 시각화 해보자.
# plot()
plot(gdis,TRUE,TRUE)
plot()함수는 오차와 일치도를 나타내는 kappa계수를 그려준다. 두 개의 TRUE input은 train/test 모두 그림을 그린다는 것이다.
# varplot()
varplot(gdis)
varplot함수는 변수의 중요도(importance)를 나타낸다. setosa를 제외한 versicolor와 virginica를 구분하는데 Sepal.Width 변수가 분류에서 가장 중요하다는 것을 뜻한다. 이는 분명하게 위에서 setosa가 있었을 때의 결과와는 다르다.
# pairs()
pairs(gdis, iris[traind,-5], maxvar=4)
pairs()함수는 두 예측변수의 조합별 분류결과를 그려준다. maxvar= 옵션은 변수의 수를 지정하는 것인데, 이때, 중요도가 높은 순으로 상위 변수의 개수를 선택할 수 있다. 위에 code에서는 변수의 수가 중요한 것으로 상위 4개를 그린것이다(즉, 전부 다 표시했다.)
3. RandomForest
# 라이브러리 로딩
install.packages("randomForest")
library(randomForest)
library(rpart)
# 데이터 로딩
data(stagec)
# train/test split
stagec1 <- stagec[complete.cases(stagec),]
set.seed(1234)
ind <- sample(2, nrow(stagec1), replace = TRUE, prob = c(0.7,0.3))
trainData <- stagec1[ind==1,] # n = 102
testData <- stagec1[ind==2,] # n = 32
# randomforest
rf <- randomForest(ploidy~., data=trainData, ntree=100, proximity=TRUE)
# confusion_matrix
table(predict(rf),trainData$ploidy)
# model summary
print(rf)
위의 결과창을 보면 OOB estimate of error rate이 존재한다. 앙상블에서는 검증용 데이터를 사용하지 않고 bootstrap(반복복원추출)에서 제외된 데이터들을 대상으로 1차적인 오류율을 구할 수 있다. 이를 Out of Bag(OOB) error라고 한다.
# plot
plot(rf)
위의 plot함수는 트리의 수에 따른 종속변수의 범주별 오분류율을 나타낸다. 검은색은 전체 오분류율. 오분류율이 1로 나타난 파란 점선은 aneuploid 범주로 개체수가 매우 작은 범주에서 발생된 오분류율이다.
# 중요도
importance(rf)
# 중요도 plot
varImpPlot(rf)
위의 출력창과 plot을 통해 각 변수의 중요도를 확인할 수 있다. 위 그림은 해당 변수로 분할작업이 이루어질때, 불순도(impurity)의 감소가 얼마나 일어나는지 나타낸다. 즉 Gini지수가 노드의 불순도를 나타내는 값이다. 그리고 불순도의 감소가 클수록 순수도가 증가한다. 위의 경우는 분류이기에 Gini지수를 통해서 표현되지만, 회귀의 경우 잔차제곱합을 통해서 측정된다.
# test 데이터 예측
rf.pred <- predict(rf, newdata = testData)
table(rf.pred, testData$ploidy)
# margin값
plot(margin(rf))
위의 예측 정오분류표와 margin표를 통해서 정확도를 확인할 수 있다. margin이란 랜덤포레스트의 classifier가운데 정분류를 수행한 비율을 다른 클래스로 분류한 비율의 최대치를 뺀 값을 나타낸다. 즉, positive margin은 정확한 분류이며, negative margin은 그와 반대이다.
# party 패키지를 활용한 randomforest
install.packages("party")
library(party)
set.seed(1234)
cf <- cforest(ploidy~., data=trainData)
cf.pred<-predict(cf,newdata=testData, OOB = TRUE, type="response")
위의 코드는 party패키지의 cforest함수를 사용하여서 randomforest를 진행할 수 있기에 잠깐 보여주는 예시이다.
'ADP | ADsP with R > Knowledge' 카테고리의 다른 글
[ADP] R을 활용한 모형평가 방법(2) - Confusion matrix, ROC Curve, Gain chart (2) | 2020.08.02 |
---|---|
[ADP] R을 활용한 모형평가 방법(1) - Holdout, K-fold, Boostrap (0) | 2020.08.02 |
[ADP] R로 하는 의사결정나무(Decision Tree) 모형 (1) | 2020.07.24 |
[ADP] R로 하는 신경망(Neural Network) 모형 (0) | 2020.07.24 |
[ADP] R로 하는 로지스틱 회귀분석 (0) | 2020.07.20 |