실습에 사용될 라이브러리 설치

다음의 패키지가 설치되어 있지 않으면 설치한다.

#install.packages("mlbench") # 데이터셋
#install.packages("tree")    # 의사결정나무 #R 3.6버전 이상 필요
#install.packages("ipred")   # 배깅
#install.packages("randomForest")  #랜덤포레스트
#install.packages("pdp")     #부분의존도 그림

데이터 전처리 및 분할

실습 데이터

  • R 패키지 mlbench에 내장된 데이터를 사용하여 실습
  • BreastCancer : 유방 낭종의 악성 여부와 관련 의학적 정보를 나타낸 데이터로 분류분석에 적용
  • BostonHousing : 보스턴의 집값과 연관요인을 나타낸 데이터로 회귀분석을 적용

Breast Cancer 데이터

  • R 패키지 mlbench를 불러온 후 data 함수를 통해 내장된 데이터 BreastCancer를 불러올 수 있다.

  • 총 699개의 관측치와 11개의 변수가 있다.

    library(mlbench)
    data(BreastCancer)
    dim(BreastCancer)
    ## [1] 699  11
  • 변수 11개의 이름 및 설명은 다음과 같다.

변수명 변수 설명
ID Sample code number
Cl.thickness Clump Thickness
Cell.size Uniformity of Cell Size
Cell.shape Uniformity of Cell Shape
Marg.adhesion Marginal Adhesion
Epith.c.size Single Epithelial Cell Size
Bare.nuclei Bare Nuclei
Bl.cromatin Bland Chromatin
Normal.nucleoli Normal Nucleoli
Mitoses Mitoses
Class Class
  • 이는 RStudio 콘솔에서 help(BreastCancer) 을 실행하거나, 우측 하단 창의 “Help”로 들어가서 “BreastCancer”를 검색하면 확인할 수 있다.

  • 첫 6개의 관측치는 다음과 같다.

    head(BreastCancer)
    ##        Id Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size
    ## 1 1000025            5         1          1             1            2
    ## 2 1002945            5         4          4             5            7
    ## 3 1015425            3         1          1             1            2
    ## 4 1016277            6         8          8             1            3
    ## 5 1017023            4         1          1             3            2
    ## 6 1017122            8        10         10             8            7
    ##   Bare.nuclei Bl.cromatin Normal.nucleoli Mitoses     Class
    ## 1           1           3               1       1    benign
    ## 2          10           3               2       1    benign
    ## 3           2           3               1       1    benign
    ## 4           4           3               7       1    benign
    ## 5           1           3               1       1    benign
    ## 6          10           9               7       1 malignant
  • Id는 사용하지 않으며, Class가 maligant인지 benign인지 예측하는 것이 목표이다.

Breast Cancer 데이터 전처리

  • Id 열을 제거한다.

    BreastCancer <- BreastCancer[,-1]
  • 변수별 결측치 개수를 확인한다. 결측이 있는 관측치를 제거한다.

    colSums(is.na(BreastCancer))
    ##    Cl.thickness       Cell.size      Cell.shape   Marg.adhesion    Epith.c.size 
    ##               0               0               0               0               0 
    ##     Bare.nuclei     Bl.cromatin Normal.nucleoli         Mitoses           Class 
    ##              16               0               0               0               0
    BreastCancer <- BreastCancer[complete.cases(BreastCancer), ]
    dim(BreastCancer)
    ## [1] 683  10
  • 설명변수의 데이터형을 보면 ordered factor로 되어있다.

    head(BreastCancer$Cell.size)
    ## [1] 1  4  1  8  1  10
    ## Levels: 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10
    class(BreastCancer$Cell.size)
    ## [1] "ordered" "factor"
  • Class를 제외한 설명변수를 모두 수치형으로 변환한다.

    XIdx <- !(names(BreastCancer) %in% 'Class')
    BreastCancer[XIdx] <-
    Map(as.numeric, BreastCancer[XIdx])

Breast Cancer 데이터 분할

  • 전체 데이터의 30%를 테스트 데이터로 사용한다. 테스트 데이터로 사용할 자료점의 인덱스를 BC.TsIdx에 저장한다.

    BC.n <- nrow(BreastCancer)
    ratioTs <- 0.3
    BC.nTs <- round(ratioTs * BC.n)
    BC.nTr <- BC.n-BC.nTs
    set.seed(1)
    BC.TsIdx <- sample(BC.n, BC.nTs)

Boston Housing 데이터

  • mlbench를 불러온 후 data 함수를 통해 내장된 데이터 BostonHousing를 불러올 수 있다.

  • 총 506개의 관측치와 14개의 변수가 있다.

    data(BostonHousing)
    dim(BostonHousing)
    ## [1] 506  14
  • 변수 14개의 이름 및 설명은 다음과 같다.

변수 이름 변수 설명
crim per capita crime rate by town
zn proportion of residential land zoned for lots over 25,000 sq.ft
indus proportion of non-retail business acres per town
chas Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
nox nitric oxides concentration (parts per 10 million)
rm average number of rooms per dwelling
age proportion of owner-occupied units built prior to 1940
dis weighted distances to five Boston employment centres
rad index of accessibility to radial highways
tax full-value property-tax rate per USD 10,000
ptratio pupil-teacher ratio by town
b 1000(B - 0.63)2 where B is the proportion of blacks by town
lstat percentage of lower status of the population
medv median value of owner-occupied homes in USD 1000’s
  • 이는 RStudio 콘솔에서 help(BostonHousing)을 실행하거나, 우측 하단 창의 “Help”로 들어가서 “BostonHousing”을 검색하면 확인할 수 있다.

  • 첫 6개의 관측치는 다음과 같다.

  • 다른 변수들을 이용해 medv를 예측하는 것이 목적이다.

    head(BostonHousing)
    ##      crim zn indus chas   nox    rm  age    dis rad tax ptratio      b lstat
    ## 1 0.00632 18  2.31    0 0.538 6.575 65.2 4.0900   1 296    15.3 396.90  4.98
    ## 2 0.02731  0  7.07    0 0.469 6.421 78.9 4.9671   2 242    17.8 396.90  9.14
    ## 3 0.02729  0  7.07    0 0.469 7.185 61.1 4.9671   2 242    17.8 392.83  4.03
    ## 4 0.03237  0  2.18    0 0.458 6.998 45.8 6.0622   3 222    18.7 394.63  2.94
    ## 5 0.06905  0  2.18    0 0.458 7.147 54.2 6.0622   3 222    18.7 396.90  5.33
    ## 6 0.02985  0  2.18    0 0.458 6.430 58.7 6.0622   3 222    18.7 394.12  5.21
    ##   medv
    ## 1 24.0
    ## 2 21.6
    ## 3 34.7
    ## 4 33.4
    ## 5 36.2
    ## 6 28.7

Boston Housing 전처리 및 데이터 분할

  • 결측치가 없고, 설명변수들의 데이터형에 문제가 없으므로 전처리를 따로 하지 않는다.

  • 전체 데이터의 30%를 테스트 데이터로 사용한다. 테스트 데이터로 사용할 자료점의 인덱스를 BH.TsIdx에 저장한다.

    BH.n <- nrow(BostonHousing)
    ratioTs <- 0.3
    BH.nTs <- round(ratioTs * BH.n)
    BH.nTr <- BH.n-BH.nTs
    set.seed(1)
    BH.TsIdx <- sample(BH.n, BH.nTs)

의사결정나무

의사결정나무

  • tree 패키지의 tree 함수를 사용하여 의사결정나무를 적합할 수 있다.

  • BreastCancer[-BC.TsIdx, ]를 통해 train 데이터를 선택하여 data 인자로 넣어준다.

  • formula로 어떤 변수를 사용하여 어떤 변수를 예측할지 지정해준다. Class~. 는 나머지 모든 변수로 Class를 예측한다는 formula이다.

    library(tree)
    BC.TreeFit<-tree(Class~., data=BreastCancer[-BC.TsIdx, ])
  • 적합 결과를 출력하면 다음과 같이 각 노드에서 어떻게 분할되는지 볼 수 있다.

  • 한 눈에 알아보기는 어렵다.

    BC.TreeFit
    ## node), split, n, deviance, yval, (yprob)
    ##       * denotes terminal node
    ## 
    ##  1) root 478 605.20 benign ( 0.67155 0.32845 )  
    ##    2) Cell.size < 2.5 302  73.88 benign ( 0.97351 0.02649 )  
    ##      4) Cl.thickness < 6.5 297  33.54 benign ( 0.98990 0.01010 )  
    ##        8) Bare.nuclei < 4.5 288   0.00 benign ( 1.00000 0.00000 ) *
    ##        9) Bare.nuclei > 4.5 9  11.46 benign ( 0.66667 0.33333 ) *
    ##      5) Cl.thickness > 6.5 5   0.00 malignant ( 0.00000 1.00000 ) *
    ##    3) Cell.size > 2.5 176 150.90 malignant ( 0.15341 0.84659 )  
    ##      6) Cell.size < 4.5 63  84.63 malignant ( 0.39683 0.60317 )  
    ##       12) Bare.nuclei < 3.5 25  25.02 benign ( 0.80000 0.20000 )  
    ##         24) Normal.nucleoli < 2.5 17   0.00 benign ( 1.00000 0.00000 ) *
    ##         25) Normal.nucleoli > 2.5 8  10.59 malignant ( 0.37500 0.62500 ) *
    ##       13) Bare.nuclei > 3.5 38  29.59 malignant ( 0.13158 0.86842 ) *
    ##      7) Cell.size > 4.5 113  20.10 malignant ( 0.01770 0.98230 )  
    ##       14) Bl.cromatin < 4.5 25  13.94 malignant ( 0.08000 0.92000 ) *
    ##       15) Bl.cromatin > 4.5 88   0.00 malignant ( 0.00000 1.00000 ) *
  • plot 함수로 tree 구조를 그릴 수 있으나 노드에 대한 정보는 보여주지 않는다.

  • text 함수과 같이 쓰면 좋다.

    plot(BC.TreeFit)
    text(BC.TreeFit)

정지규칙

  • tree.control로 마디를 언제까지 분할할지 지정할 수 있다.

  • mindev를 지정하면 끝마디의 deviance가 뿌리마디의 deviance의 mindev 배보다 클 때까지만 분할한다.

  • mindev는 기본 0.01이며 커질수록 더 적게 분할하며 작아질수록 더 많이 분할한다.

    BC.BigTreeFit<-tree(Class~., data=BreastCancer[-BC.TsIdx, ], 
    control = tree.control(BC.nTr, mindev = 0.001))
    BC.SmallTreeFit<-tree(Class~., data=BreastCancer[-BC.TsIdx, ], 
    control = tree.control(BC.nTr, mindev = 0.1))
  • mindev가 작은 경우

    plot(BC.BigTreeFit)
    text(BC.BigTreeFit)

  • mindev가 큰 경우

    plot(BC.SmallTreeFit)
    text(BC.SmallTreeFit)

의사결정나무의 교차검증

  • 이론 강의의 교차검증 예제와 비슷한 방식으로 최적 모형을 고르려고 한다.

  • 교차검증 예제에서는 주어진 모형 집합이 있으나 의사결정나무에서는 데이터에 따라 모형이 결정되므로 그대로 적용할 수는 없다.

  • 최적 모형을 선택하는 대신 최적 끝마디 수를 선택한다.

  • cv.tree에 적합된 의사결정나무와 fold의 수 K를 입력해주면 된다. K의 기본값은 10이다.

  • 다음 그래프는 끝마디 수에 따른 교차검증 deviance를 나타낸 것이다.

  • \(\text{비용복잡도}(\alpha)=\text{나무 } T\text{의 } deviance + \alpha |T|\)에서 \(x\)축이 \(|T|\), \(y\)축이 교차검증 \(deviance\)에 해당된다.

  • \(\text{비용복잡도}(\alpha)\)를 최소로 하는 \(|T|\)\(\alpha\)의 함수로 볼 수 있으며 \(x\)축을 \(|T|\) 대신 \(\alpha\)에 대해서 표현할 수 있다. 그래프 위에 나타나 있다.

    BC.TreeCV <- cv.tree(BC.BigTreeFit)
    plot(BC.TreeCV)

가지치기

  • BC.TreeCV에는 끝마디 수에 따른 교차검증 deviance가 저장되어있으며 이를 최소로하는 끝마디 수를 BestSize에 저장한다.

  • prune.tree 함수를 이용해 적합된 나무 BC.TreeFit를 끝마디 수가 BestSize가 되도록 가지치기한다.

    BestSize <- BC.TreeCV$size[which.min(BC.TreeCV$dev)]
    BestSize
    ## [1] 5
    BC.TreePruned <- prune.tree(BC.BigTreeFit, best = BestSize)
  • 가지치기된 나무는 다음과 같다.

    plot(BC.TreePruned)
    text(BC.TreePruned)

의사결정나무 예측 - Breast Cancer

  • BC.TreeFit을 사용하여 테스트 데이터를 예측한다.

  • predict에서 type'class'로 하여 속한 그룹을 예측하도록 한다. 지정하지 않을 경우 확률이 계산된다.

  • confusion matrix와 accuracy를 계산한다.

    BC.TreeFit.pred <- predict(BC.TreeFit, BreastCancer[BC.TsIdx, ], type = 'class')
    table(pred=BC.TreeFit.pred, true=BreastCancer$Class[BC.TsIdx])
    ##            true
    ## pred        benign malignant
    ##   benign       114         3
    ##   malignant      9        79
    BC.TreeFit.Acc <- mean(BC.TreeFit.pred==BreastCancer$Class[BC.TsIdx])
    BC.TreeFit.Acc
    ## [1] 0.9414634

가지치기된 나무 예측 - Breast Cancer

  • 다음은 BC.TreePruned의 예측 결과이다.

    BC.TreePruned.pred <- predict(BC.TreePruned, BreastCancer[BC.TsIdx, ], type = 'class')
    table(pred=BC.TreePruned.pred, true=BreastCancer$Class[BC.TsIdx])
    ##            true
    ## pred        benign malignant
    ##   benign       119         7
    ##   malignant      4        75
    BC.TreePruned.Acc <- mean(BC.TreePruned.pred==BreastCancer$Class[BC.TsIdx])
    BC.TreePruned.Acc
    ## [1] 0.9463415

의사결정나무 학습 - Boston Housing

  • 회귀분석 자료에도 같은 방식으로 의사결정나무를 적합한다.

  • 반응변수인 medv가 수치형이며 별도의 설정없이 자동으로 회귀모형이 적합된다.

    class(BostonHousing$medv)
    ## [1] "numeric"
    BH.TreeFit<-tree(medv~., data=BostonHousing[-BH.TsIdx, ])
    BH.TreeFit
    ## node), split, n, deviance, yval
    ##       * denotes terminal node
    ## 
    ##  1) root 354 30070.0 22.76  
    ##    2) lstat < 9.615 149 11640.0 29.89  
    ##      4) rm < 6.941 100  3846.0 25.70  
    ##        8) dis < 1.77785 5   528.4 44.86 *
    ##        9) dis > 1.77785 95  1385.0 24.69  
    ##         18) rm < 6.5435 61   534.0 22.98 *
    ##         19) rm > 6.5435 34   350.3 27.76 *
    ##      5) rm > 6.941 49  2460.0 38.44  
    ##       10) rm < 7.435 28   295.4 34.08 *
    ##       11) rm > 7.435 21   922.7 44.25  
    ##         22) ptratio < 17.7 16   213.6 46.68 *
    ##         23) ptratio > 17.7 5   312.7 36.48 *
    ##    3) lstat > 9.615 205  5365.0 17.58  
    ##      6) lstat < 15 91  1057.0 21.19 *
    ##      7) lstat > 15 114  2177.0 14.70  
    ##       14) crim < 5.51111 57   631.6 17.22 *
    ##       15) crim > 5.51111 57   820.3 12.18 *
    plot(BH.TreeFit)
    text(BH.TreeFit)

정지규칙

  • tree.control로 마디를 언제까지 분할할지 지정할 수 있다.

  • mindev를 지정하면 끝마디의 deviance가 뿌리마디의 deviance의 mindev 배보다 클 때까지만 분할한다.

  • mindev는 기본 0.01이며 커질수록 더 적게 분할하며 작아질수록 더 많이 분할한다.

    BH.BigTreeFit<-tree(medv~., data=BostonHousing[-BH.TsIdx, ], 
    control = tree.control(BH.nTr, mindev = 0.001))
    BH.SmallTreeFit<-tree(medv~., data=BostonHousing[-BH.TsIdx, ], 
    control = tree.control(BH.nTr, mindev = 0.1))
  • mindev가 작은 경우

    plot(BH.BigTreeFit)
    text(BH.BigTreeFit)

  • mindev가 큰 경우

    plot(BH.SmallTreeFit)
    text(BH.SmallTreeFit)

회귀모형 평가 방법

  • Breast Cancer 데이터와 비슷하게 예측값을 계산하고 성능을 확인한다.
  • 분류가 아닌 회귀모형이므로 confusion matrix와 accuracy 대신 산점도와 평균제곱오차(MSE)를 구한다.

의사결정나무 예측 - Boston Housing

BH.TreeFit.pred <- predict(BH.TreeFit, BostonHousing[BH.TsIdx, ])
plot(x=BH.TreeFit.pred, y=BostonHousing$medv[BH.TsIdx])

#예측값의 범주 수가 끝마디 수 이하라는 한계가 있음.
BH.TreeFit.MSE <- mean((BH.TreeFit.pred-BostonHousing$medv[BH.TsIdx])^2)
BH.TreeFit.MSE
## [1] 18.81051

배깅

Bagging

  • Bagging은 패키지 “ipred”의 bagging 함수를 사용하여 학습할 수 있다.
  • bagging 함수에서는 정해진 개수만큼 나무를 만드는데 이를 nbagg에 지정하면 된다.

Bagging 학습 - Breast Cancer

library(ipred)
BC.Bag <- bagging(Class~., data = BreastCancer[-BC.TsIdx, ], 
nbagg = 100, coob=TRUE)
BC.Bag
## 
## Bagging classification trees with 100 bootstrap replications 
## 
## Call: bagging.data.frame(formula = Class ~ ., data = BreastCancer[-BC.TsIdx, 
##     ], nbagg = 100, coob = TRUE)
## 
## Out-of-bag estimate of misclassification error:  0.0356

Bagging 구조 확인

  • BC.Bag은 100개의 나무로 이루어져있으며 이 나무들의 정보는 BC.Bag$mtrees에 저장되어있다.

  • BC.Bag$mtrees는 길이가 100인 리스트이며 하나의 원소가 하나의 나무를 나타낸다.

    length(BC.Bag$mtrees)
    ## [1] 100
  • BC.Bag의 첫번째 나무를 확인하면 다음과 같다.

    BC.Bag$mtrees[[1]]$btree
    ## n= 478 
    ## 
    ## node), split, n, loss, yval, (yprob)
    ##       * denotes terminal node
    ## 
    ##   1) root 478 163 benign (0.658995816 0.341004184)  
    ##     2) Cell.size< 3.5 333  23 benign (0.930930931 0.069069069)  
    ##       4) Bare.nuclei< 3.5 300   3 benign (0.990000000 0.010000000)  
    ##         8) Cl.thickness< 7 298   1 benign (0.996644295 0.003355705)  
    ##          16) Normal.nucleoli< 7.5 297   0 benign (1.000000000 0.000000000) *
    ##          17) Normal.nucleoli>=7.5 1   0 malignant (0.000000000 1.000000000) *
    ##         9) Cl.thickness>=7 2   0 malignant (0.000000000 1.000000000) *
    ##       5) Bare.nuclei>=3.5 33  13 malignant (0.393939394 0.606060606)  
    ##        10) Cell.size< 1.5 11   2 benign (0.818181818 0.181818182)  
    ##          20) Epith.c.size>=1.5 9   0 benign (1.000000000 0.000000000) *
    ##          21) Epith.c.size< 1.5 2   0 malignant (0.000000000 1.000000000) *
    ##        11) Cell.size>=1.5 22   4 malignant (0.181818182 0.818181818)  
    ##          22) Normal.nucleoli>=6 6   2 benign (0.666666667 0.333333333)  
    ##            44) Cl.thickness< 6.5 4   0 benign (1.000000000 0.000000000) *
    ##            45) Cl.thickness>=6.5 2   0 malignant (0.000000000 1.000000000) *
    ##          23) Normal.nucleoli< 6 16   0 malignant (0.000000000 1.000000000) *
    ##     3) Cell.size>=3.5 145   5 malignant (0.034482759 0.965517241)  
    ##       6) Marg.adhesion< 1.5 6   2 malignant (0.333333333 0.666666667)  
    ##        12) Cl.thickness< 7 2   0 benign (1.000000000 0.000000000) *
    ##        13) Cl.thickness>=7 4   0 malignant (0.000000000 1.000000000) *
    ##       7) Marg.adhesion>=1.5 139   3 malignant (0.021582734 0.978417266)  
    ##        14) Cell.size< 4.5 15   2 malignant (0.133333333 0.866666667)  
    ##          28) Marg.adhesion< 5.5 3   1 benign (0.666666667 0.333333333)  
    ##            56) Cl.thickness>=7.5 2   0 benign (1.000000000 0.000000000) *
    ##            57) Cl.thickness< 7.5 1   0 malignant (0.000000000 1.000000000) *
    ##          29) Marg.adhesion>=5.5 12   0 malignant (0.000000000 1.000000000) *
    ##        15) Cell.size>=4.5 124   1 malignant (0.008064516 0.991935484)  
    ##          30) Bl.cromatin< 4.5 19   1 malignant (0.052631579 0.947368421)  
    ##            60) Normal.nucleoli< 2.5 4   1 malignant (0.250000000 0.750000000)  
    ##             120) Cell.size>=8.5 1   0 benign (1.000000000 0.000000000) *
    ##             121) Cell.size< 8.5 3   0 malignant (0.000000000 1.000000000) *
    ##            61) Normal.nucleoli>=2.5 15   0 malignant (0.000000000 1.000000000) *
    ##          31) Bl.cromatin>=4.5 105   0 malignant (0.000000000 1.000000000) *

Bagging 구조 확인

  • 다음은 BC.Bag의 1 – 3번째 나무를 나타낸 그래프이다.

    par(mfrow=c(1,3))
    for(i in 1:3) {
        plot(BC.Bag$mtrees[[i]]$btree)
        text(BC.Bag$mtrees[[i]]$btree)
    }

    par(mfrow=c(1,1))

Bagging 구조 확인

  • BC.Bag는 이러한 나무 100개로 이루어져있다.
  • 수많은 나무로 이루어진 bagging을 직접 해석하는 것은 어렵다.
  • 부분의존도 그림을 통해 일부 변수에 대해 해석할 수 있다.

Bagging 예측 - Breast Cancer

BC.Bag.pred <- predict(BC.Bag, newdata = BreastCancer[BC.TsIdx, ])
table(pred=BC.Bag.pred, true=BreastCancer$Class[BC.TsIdx])
##            true
## pred        benign malignant
##   benign       119         4
##   malignant      4        78
BC.Bag.Acc <- mean(BC.Bag.pred==BreastCancer$Class[BC.TsIdx])
BC.Bag.Acc
## [1] 0.9609756

부분의존도 그림

  • 패키지 “pdp”의 partial 함수로 부분의존도 함수를 계산한 후 그 결과를 plotPartial에 입력하여 부분의존도 그림을 그릴 수 있다.

  • partial 함수에는 적합된 모델과 모델에 포함된 설명변수 중 관심있는 변수 하나의 이름을 지정해줘야한다.

  • “ipred”나 “randomForest” 등 자주 사용되는 여러 패키지들에서 학습된 모델을 지원한다.

  • 세포 크기(Cell.size)가 증가할수록 Class가 악성(“maligant”)일 확률의 예측값이 증가한다.

    library(pdp)
    BC.Bag.Cell.size <- partial(BC.Bag, pred.var = 'Cell.size', which.class="malignant")
    plotPartial(BC.Bag.Cell.size)

  • 덩어리 굵기(Cl.thickness)가 증가할수록 Class가 악성(“maligant”)일 확률의 예측값이 증가한다.

    BC.Bag.Cl.thickness <- partial(BC.Bag, pred.var = 'Cl.thickness',  which.class="malignant")
    plotPartial(BC.Bag.Cl.thickness)

  • 접착력(Marg.adhesion)이 증가할수록 Class가 악성(“maligant”)일 확률의 예측값이 증가한다.

    BC.Bag.Marg.adhesion <- partial(BC.Bag, pred.var = 'Marg.adhesion',  which.class="malignant")
    plotPartial(BC.Bag.Marg.adhesion)

Bagging 학습 - Boston Housing

  • 수치형 자료에 대해서도 별 다른 설정없이 회귀모형을 적합시킬 수 있다.

    BH.Bag <- bagging(medv~., data = BostonHousing[-BH.TsIdx, ],  nbagg = 100, coob=TRUE)
    BH.Bag
    ## 
    ## Bagging regression trees with 100 bootstrap replications 
    ## 
    ## Call: bagging.data.frame(formula = medv ~ ., data = BostonHousing[-BH.TsIdx, 
    ##     ], nbagg = 100, coob = TRUE)
    ## 
    ## Out-of-bag estimate of root mean squared error:  4.321
    BH.Bag.pred <- predict(BH.Bag, newdata = BostonHousing[BH.TsIdx, ])
    plot(x=BH.Bag.pred, y=BostonHousing$medv[BH.TsIdx])

    BH.Bag.MSE <- mean((BH.Bag.pred-BostonHousing$medv[BH.TsIdx])^2)
    BH.Bag.MSE
    ## [1] 11.43528

Bagging 부분의존도 그림

  • 범죄율(crim)이 증가할수록 집값(medv)의 예측값이 감소한다.

    library(pdp)
    BH.Bag.crim <- partial(BH.Bag, pred.var = 'crim')
    plotPartial(BH.Bag.crim)

  • 방의 수(rm)가 증가할수록 집값(medv)의 예측값이 증가한다.

    BH.Bag.rm <- partial(BH.Bag, pred.var = 'rm')
    plotPartial(BH.Bag.rm)

Bagging 부분의존도 그림 (lstat)

  • 지위가 낮은 사람의 비율(lstat)이 증가할수록 집값(medv)의 예측값이 감소한다.

    BH.Bag.dis <- partial(BH.Bag, pred.var = 'lstat')
    plotPartial(BH.Bag.dis)

랜덤포레스트

Random Forest

  • 패키지 “randomForest”의 randomForest 함수를 이용하여 랜덤포레스트를 적합할 수 있다.
  • randomForest에서는 나무의 개수 ntree와 각 노드에서 사용할 후보 변수의 수 mtry를 지정해야한다.
  • 총 설명변수의 수를 \(p\)라 할 때, ntree의 기본값은 500이며 분류모형일 때, mtry \(\approx \sqrt{p}\), 회귀모형일 때, mtry \(\approx p/3\)이다.

Random Forest 학습 - Breast Cancer

library(randomForest)
BC.RF <- randomForest(Class~., data = BreastCancer[-BC.TsIdx, ],  importance = TRUE)
BC.RF
## 
## Call:
##  randomForest(formula = Class ~ ., data = BreastCancer[-BC.TsIdx,      ], importance = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 500
## No. of variables tried at each split: 3
## 
##         OOB estimate of  error rate: 2.93%
## Confusion matrix:
##           benign malignant class.error
## benign       313         8  0.02492212
## malignant      6       151  0.03821656

Random Forest 예측 - Breast Cancer

BC.RF.pred <- predict(BC.RF, newdata = BreastCancer[BC.TsIdx, ])
table(pred=BC.RF.pred, true=BreastCancer$Class[BC.TsIdx])
##            true
## pred        benign malignant
##   benign       119         3
##   malignant      4        79
BC.RF.Acc <- mean(BC.RF.pred==BreastCancer$Class[BC.TsIdx])
BC.RF.Acc
## [1] 0.9658537

Random Forest 변수중요도

  • importance 함수를 사용하여 중요도를 구할 수 있다.

  • 특정 변수의 값을 데이터 내에서 랜덤하게 섞어서 예측에 도움이 되지 않도록 만든 후 예측했을 때, 결과가 얼마나 안 좋아지는지를 계산한다.

  • 더 많이 나빠질수록 예측에 중요한 변수라 볼 수 있다.

    head(importance(BC.RF)[,3:4])
    ##               MeanDecreaseAccuracy MeanDecreaseGini
    ## Cl.thickness              16.35911         8.078830
    ## Cell.size                 20.71841        55.937150
    ## Cell.shape                16.82963        36.713881
    ## Marg.adhesion             11.57630         7.561247
    ## Epith.c.size              12.11946        15.477940
    ## Bare.nuclei               24.01128        34.412627

Random Forest 변수중요도 그림

  • varImpPlot 함수를 사용하면 중요도를 그림으로 나타낼 수 있다.

  • 두 가지 기준 공통으로 Cell.size, Bare.nuclei가 중요한 것으로 보인다.

    varImpPlot(BC.RF)

Random Forest 부분의존도 그림

  • 세포 크기(Cell.size)가 증가할수록 Class가 악성(“maligant”)일 확률의 예측값이 증가한다.

    library(pdp)
    BC.RF.Cell.size <- partial(BC.RF, pred.var = 'Cell.size', which.class="malignant")
    plotPartial(BC.RF.Cell.size)

  • 덩어리 굵기(Cl.thickness)가 증가할수록 Class가 악성(“maligant”)일 확률의 예측값이 증가한다.

    BC.RF.Cl.thickness <- partial(BC.RF, pred.var = 'Cl.thickness', 
    which.class="malignant")
    plotPartial(BC.RF.Cl.thickness)

  • 접착력(Marg.adhesion)이 증가할수록 Class가 악성(“maligant”)일 확률의 예측값이 증가한다.

    BC.RF.Marg.adhesion <- partial(BC.RF, pred.var = 'Marg.adhesion', 
    which.class="malignant")
    plotPartial(BC.RF.Marg.adhesion)

Random Forest 학습 - Boston Housing

BH.RF <- randomForest(medv~., data = BostonHousing[-BH.TsIdx, ],  importance = TRUE)
BH.RF
## 
## Call:
##  randomForest(formula = medv ~ ., data = BostonHousing[-BH.TsIdx,      ], importance = TRUE) 
##                Type of random forest: regression
##                      Number of trees: 500
## No. of variables tried at each split: 4
## 
##           Mean of squared residuals: 12.77443
##                     % Var explained: 84.96

Random Forest 예측 - Boston Housing

BH.RF.pred <- predict(BH.RF, newdata = BostonHousing[BH.TsIdx, ])
plot(x=BH.RF.pred, y=BostonHousing$medv[BH.TsIdx])

BH.RF.MSE <- mean((BH.RF.pred-BostonHousing$medv[BH.TsIdx])^2)
BH.RF.MSE
## [1] 8.248459

Random Forest 변수중요도

  • importance 함수를 사용하여 중요도를 구할 수 있다.

  • 특정 변수의 값을 데이터 내에서 랜덤하게 섞어서 예측에 도움이 되지 않도록 만든 후 예측했을 때, 결과가 얼마나 안 좋아지는지를 계산한다.

  • 더 많이 나빠질수록 예측에 중요한 변수라 볼 수 있다.

    head(importance(BH.RF))
    ##         %IncMSE IncNodePurity
    ## crim  15.485362     2022.2782
    ## zn     3.665558      182.2067
    ## indus 12.583043     2523.8158
    ## chas   3.036134      125.7982
    ## nox   16.168554     2001.0150
    ## rm    34.064639     8152.3665

Random Forest 변수중요도 그림

  • varImpPlot 함수를 사용하면 중요도를 그림으로 나타낼 수 있다.

  • 두 가지 기준 공통으로 lstat, rm이 중요한 것으로 보인다.

    varImpPlot(BH.RF)

  • 범죄율(crim)이 증가할수록 집값(medv)의 예측값이 감소한다.

    BH.RF.crim <- partial(BH.RF, pred.var = 'crim')
    plotPartial(BH.RF.crim)

  • 방의 수(rm)가 증가할수록 집값(medv)의 예측값이 증가한다.

    BH.RF.rm <- partial(BH.RF, pred.var = 'rm')
    plotPartial(BH.RF.rm)

  • 고용센터와의 거리(dis)가 증가할수록 집값(medv)의 예측값이 감소한다.

    BH.RF.dis <- partial(BH.RF, pred.var = 'dis')
    plotPartial(BH.RF.dis)

방법론 비교

예측모형 방법론들

  • 예측모형은 반응변수(\(Y\))의 형태에 따라 분류분석과 회귀분석으로 나뉜다.

  • 분류분석 : 반응변수가 범주형

    • Logistic regression
    • Decision tree
    • Bagging
    • Random forest
  • 회귀분석 : 반응변수가 연속형

    • Linear regression
    • Decision tree
    • Bagging
    • Random forest

Breast Cancer – 로지스틱 회귀

BC.LoR <- glm(Class~.,family=binomial, data = BreastCancer[-BC.TsIdx, ])
BC.LoR
## 
## Call:  glm(formula = Class ~ ., family = binomial, data = BreastCancer[-BC.TsIdx, 
##     ])
## 
## Coefficients:
##     (Intercept)     Cl.thickness        Cell.size       Cell.shape  
##        -9.27948          0.42112         -0.05391          0.32709  
##   Marg.adhesion     Epith.c.size      Bare.nuclei      Bl.cromatin  
##         0.27034          0.21076          0.33346          0.52543  
## Normal.nucleoli          Mitoses  
##         0.18384          0.19185  
## 
## Degrees of Freedom: 477 Total (i.e. Null);  468 Residual
## Null Deviance:       605.2 
## Residual Deviance: 76.76     AIC: 96.76
BC.LoR.prob <- predict(BC.LoR, newdata = BreastCancer[BC.TsIdx, ],  type="response")
BC.LoR.pred=ifelse(BC.LoR.prob<0.5,"benign","malignant")
table(pred=BC.LoR.pred, true=BreastCancer$Class[BC.TsIdx])
##            true
## pred        benign malignant
##   benign       120         4
##   malignant      3        78
BC.LoR.Acc <- mean(BC.LoR.pred==BreastCancer$Class[BC.TsIdx])
BC.LoR.Acc
## [1] 0.9658537

Breast Cancer 예측 성능 비교

  • 로지스틱 회귀모형과 Random Forest의 예측성능이 가장 좋다.

    BC.LoR.Acc           # Logistic regression
    ## [1] 0.9658537
    BC.TreeFit.Acc       # Decision tree
    ## [1] 0.9414634
    BC.TreePruned.Acc    # Decision tree (pruning)
    ## [1] 0.9463415
    BC.Bag.Acc           # Bagging
    ## [1] 0.9609756
    BC.RF.Acc            # Random Forest
    ## [1] 0.9658537

Boston Housing – 선형회귀

BH.LM <- lm(medv~., data = BostonHousing[-BH.TsIdx, ])
BH.LM
## 
## Call:
## lm(formula = medv ~ ., data = BostonHousing[-BH.TsIdx, ])
## 
## Coefficients:
## (Intercept)         crim           zn        indus        chas1          nox  
##   34.541276    -0.102680     0.038190     0.010701     2.170592   -18.288461  
##          rm          age          dis          rad          tax      ptratio  
##    3.908293     0.001806    -1.384502     0.259984    -0.008548    -0.928456  
##           b        lstat  
##    0.009673    -0.539785
BH.LM.pred <- predict(BH.LM, newdata = BostonHousing[BH.TsIdx, ])
plot(x=BH.LM.pred, y=BostonHousing$medv[BH.TsIdx])

BH.LM.MSE <- mean((BH.LM.pred-BostonHousing$medv[BH.TsIdx])^2)
BH.LM.MSE
## [1] 19.26122

Boston Housing 예측 성능 비교

  • Random Forest의 예측성능이 가장 좋으며 Bagging이 그 다음으로 좋다.

    BH.LM.MSE       # Linear model
    ## [1] 19.26122
    BH.TreeFit.MSE  # Decision tree
    ## [1] 18.81051
    BH.Bag.MSE      # Bagging
    ## [1] 11.43528
    BH.RF.MSE       # Random forest
    ## [1] 8.248459

연습문제

ISLR 패키지에 있는 Carseats 데이터에서 유아 카시트 판매량를 분석해보려고 한다. 먼저 ISLR 패키지를 다운받는다. 이는 Gareth James, Daniela Witten 등이 저술한 책 An Introduction to Statistical Learning with Applications in R에서 다루는 데이터셋이 모여있는 패키지이다.

install.packages("ISLR")

Carseats 데이터는 400개의 매장에서 유아 카시트 판매량을 기록한 자료이다. (help(Carseats, package = "ISLR") 참고) 데이터는 아래와 같이 불어올 수 있다.

library(ISLR)
data(Carseats)
head(Carseats, n=3)
##   Sales CompPrice Income Advertising Population Price ShelveLoc Age Education
## 1  9.50       138     73          11        276   120       Bad  42        17
## 2 11.22       111     48          16        260    83      Good  65        10
## 3 10.06       113     35          10        269    80    Medium  59        12
##   Urban  US
## 1   Yes Yes
## 2   Yes Yes
## 3   Yes Yes

먼저 Sales 변수는 연속형 변수이므로 regression tree를 적합하려고 한다. 다음 물음에 답하여라.

  1. 데이터를 먼저 train 데이터와 test 데이터로 나눈 후 train 데이터에 대해 의사결정나무를 적합한 후 test 데이터에 대해 예측 오차(MSE)를 계산하여라. 재현성을 위해 set.seed(2023217)를 실행하여 random seed를 2023217로 고정한다.
  2. 교차검증을 이용해 최적의 의사결정나무를 찾고, 해당 의사결정나무의 예측 오차(test MSE)를 앞서 a에서 계산한 예측 오차와 비교하여라.
  3. 랜덤포레스트 모형을 적합하고 예측 오차를 계산하여라. 어떤 변수가 가장 중요한 변수인가? mtry 옵션을 바꿔가며 예측 오차가 어떻게 나오는지 살펴보아라.

앞서 Sales 변수를 연속형 변수로 다뤘다면 이번에는 이를 전처리하여 새로운 High라는 변수를 만들어 categorical tree를 적합하려고 한다. High 변수는 Sales가 8 초과면 yes, 8 이하면 no로 정의된다.

High <- ifelse(Carseats$Sales <= 8, "No", "Yes")
Carseats.cat <- data.frame(Carseats, High)
  1. 로지스틱 회귀모형과 랜덤포레스트 모형을 적합하고 예측 정확도를 비교하여라.