R

[R] caret 패키지로 modeling & model tuning (iris classification :: knn algorithm)

슈퍼짱짱 2020. 9. 16. 14:38
반응형

이전에 caret 패키지로 Data Scaling 하는 방법을 알아보았다.

2020/09/03 - [R] - [R] caret 패키지로 scale 하는 방법 :: scale in R (preProcess in caret) :: 표준화 vs 정규화

 

[R] caret 패키지로 scale 하는 방법 :: scale in R (preProcess in caret) :: 표준화 vs 정규화

Data Scaling in R 데이터 scale 이란 전처리 과정 중 하나로, 각 컬럼의 분포를 맞춰주기 위해 필요한 과정이다. scale 과정 없이 모델링을 한다고 했을 때 문제점은 예를 들어, X1의 범위는 0~1 이고, X2의

leedakyeong.tistory.com

 

이번에는 caret 패키지를 이용하여 모델을 만들고, random search, grid search 로 모델을 튜닝하는 것까지 소개하려 한다.

 


Classification with KNN in caret package

 

실습에는 iris data 를 사용한다.

 

irir dataset (붓꽃 데이터셋)

 

150개의 레코드, 5개의 컬럼으로 구성

Sepal Length : 꽃받침 길이

Sepal Width   : 꽃받침 너비

Petal Length  : 꽃잎의 길이

Petal Width    : 꽃잎의 너비

Species           : 꽃의 종류(setosa / versicolor / virginica) :: Label

 

Sepal Length, Sepal Width, Petal Length, Petal Width 로 Species를 분류하는 문제를 해결하는 것이 목표이다.

편의를 위해 Species는 세 가지가 아니라 두 가지로 진행한다.

 

library(tidyverse)

data <- iris %>% mutate(Species = as.character(Species))
data <- data %>% filter(Species %in% c("setosa","versicolor"))
data$Species <- as.factor(data$Species)

 

(Species를 character형으로 바꾸지 않으면 두 개의 Species만 filtering해도 여전히 3개의 Factor Level을 가지고 있기 때문에 이후 모델링 과정에서 에러가 발생한다.)

 

> str(data)

'data.frame': 100 obs. of  5 variables:

 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...

 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...

 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...

 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...

 $ Species     : Factor w/ 2 levels "setosa","versicolor": 1 1 1 1 1 1 1 1 1 1 ...

 


1. Split data set (train/test)

 

전체 100건의 데이터셋에 대해 70%/30%로 train set과 test set을 분리한다.

(매번 같은 데이터셋을 만들기 위해 seed를 지정해 주었다. 생략 가능)

 

library(caret)

set.seed(1)
idx <- sample(1:nrow(data), nrow(data)*0.7)
train <- data[idx,]
test <- data[-idx,]

 

> nrow(train)

[1] 70

> nrow(test)

[1] 30

 

> table(train$Species)

 

    setosa versicolor 

        34         36 

 

> table(test$Species)

 

    setosa versicolor 

        16         14 

 


2. Modeling (Classification with KNN)

 

knn 알고리즘으로 iris 데이터에서 Species(꽃의 종류)를 분류하는 모델을 만든다.

(분류 알고리즘에는 knn 말고도 다양한 알고리즘이 존재하며, caret 패키지에서 제공하는 알고리즘 종류는 topepo.github.io/caret/available-models.html 에서 확인할 수 있다.)

 

2-1. tuning method = "none"

아무런 파라미터 없이 기본 코드는 다음과 같다.

 

tune <- caret::trainControl(method = "none")
model1 <- caret::train(Species ~ ., data = train,
                       method = "knn",
                       trControl = tune)

 

Cross Validation도, 파라미터 지정도, 튜닝도 없이 mthod = "none"으로 지정해 주었다.

 

* (참고) Cross Validation을 할 때는 method = "CV"로 지정해주고, number로 몇 개의 fold로 나눌지 정해준다.

아래는 5 fold Cross Validation 할 때 코드이다.

tune <- caret::trainControl(method = "CV", number = 5)

 

이를 test set 에 적용해 예측값을 뽑고, 실제값과 예측값의 confusion matrix를 뽑아 성능을 비교하는 코드는 다음과 같다.

 

preds1 <- predict(model1, newdata = test)
caret::confusionMatrix(preds1, test$Species)

 

> caret::confusionMatrix(preds1, test$Species)

Confusion Matrix and Statistics

 

            Reference

Prediction   setosa versicolor

  setosa         16          0

  versicolor      0         14

                                     

               Accuracy : 1          

                 95% CI : (0.8843, 1)

    No Information Rate : 0.5333     

    P-Value [Acc > NIR] : 6.456e-09  

                                     

                  Kappa : 1          

                                     

 Mcnemar's Test P-Value : NA         

                                     

            Sensitivity : 1.0000     

            Specificity : 1.0000     

         Pos Pred Value : 1.0000     

         Neg Pred Value : 1.0000     

             Prevalence : 0.5333     

         Detection Rate : 0.5333     

   Detection Prevalence : 0.5333     

      Balanced Accuracy : 1.0000     

                                     

       'Positive' Class : setosa

 

* confusion matirx에 대한 설명은 이전에 올려놓은 포스트를 참고

2020/04/07 - [통계 지식/기초통계] - 분류 모델 성능 평가 지표 - Confusion Matrix란? :: 정확도(Accuracy), 정밀도(Precision), 재현도(Recall), F1 Score

 

분류 모델 성능 평가 지표 - Confusion Matrix란? :: 정확도(Accuracy), 정밀도(Precision), 재현도(Recall), F1 Sc

분류 모델 성능 평가 지표 Linear 모델에 대해서는 R-Square, MSE 등 으로 모델의 성능을 평가한다. 그렇다면 분류 모델에 대해서는 모델의 성능을 어떻게 평가할 수 있을까? 여러가지 방법이 있지만,

leedakyeong.tistory.com

iris data set이 워낙 깨끗해서 아무런 파라미터 튜닝 없이도 결과가 너무 좋다.

하지만 현실에서 다룰 실제 데이터는 이렇게 깨끗하지 않고, 처음부터 모델의 결과가 이렇게나 좋기 쉽지 않다. 따라서 파라미터 튜닝 과정을 통해 모델을 고도화한다.

 


2-2. Parameter Tuning with Random Search in caret

caret 패키지에서는 각 모델 알고리즘 별 필요한 파라미터가 무엇인지 modelLookup(model = ) 을 통해 제공한다.

 

> caret::modelLookup("knn")
  model parameter      label forReg forClass probModel
1   knn         k #Neighbors   TRUE     TRUE      TRUE

 

* (참고) xgbLinear 모델은 다음과 같이 4개의 hyper parameter를 필요로 한다.

 

> caret::modelLookup("xgbLinear")

      model parameter                 label forReg forClass probModel

1 xgbLinear   nrounds # Boosting Iterations   TRUE     TRUE      TRUE

2 xgbLinear    lambda     L2 Regularization   TRUE     TRUE      TRUE

3 xgbLinear     alpha     L1 Regularization   TRUE     TRUE      TRUE

4 xgbLinear       eta         Learning Rate   TRUE     TRUE      TRUE 

 

knn 알고리즘은 k 라는 하나의 파라미터를 필요로 한다. (참고로 k의 의미는 "탐색할 이웃의 수" 이다.)

 

랜덤 서치 방법으로 파라미터를 찾는 코드는 다음과 같다.

 

tuneLength를 지정하여 tuneLength개의 파라미터를 랜덤 하게 서치 한다.

Cross Validation을 해주지 않으면 에러가 나는데, 파라미터를 서치 하는 과정에서 validation set이 없으면 Accuracy를 계산하지 못해서가 아닐까 추측한다.

 

tune2 <- caret::trainControl(method = "CV", number = 5)
model2 <- caret::train(Species ~ ., data = train,
                       method = "knn",
                       trControl = tune2,
                       tuneLength = 20)

 

결과는 다음과 같다.

 

> model2

k-Nearest Neighbors 

 

70 samples

 4 predictor

 2 classes: 'setosa', 'versicolor' 

 

No pre-processing

Resampling: Cross-Validated (5 fold) 

Summary of sample sizes: 56, 55, 56, 57, 56 

Resampling results across tuning parameters:

 

  k   Accuracy   Kappa    

   5  1.0000000  1.0000000

   7  1.0000000  1.0000000

   9  1.0000000  1.0000000

  11  1.0000000  1.0000000

  13  1.0000000  1.0000000

  15  1.0000000  1.0000000

  17  1.0000000  1.0000000

  19  1.0000000  1.0000000

  21  1.0000000  1.0000000

  23  1.0000000  1.0000000

  25  1.0000000  1.0000000

  27  1.0000000  1.0000000

  29  1.0000000  1.0000000

  31  1.0000000  1.0000000

  33  1.0000000  1.0000000

  35  1.0000000  1.0000000

  37  1.0000000  1.0000000

  39  1.0000000  1.0000000

  41  1.0000000  1.0000000

  43  0.9857143  0.9714286

 

Accuracy was used to select the optimal model using the largest value.

The final value used for the model was k = 41.

 

랜덤 하게 뽑은 20개의 파라미터에 대해 validation set에 대한 Accuracy와 최종 선택된 k를 제공한다. 

위에서 언급했듯 iris 데이터가 너무 깨끗해 어떤 k값을 주어도 Accuracy는 1로 나왔다.

 

각 k에 대한 Accuracy를 그래프로 확인할 수도 있다.

 

> plot(model2)

x축은 k, y 축은 Accuracy이다.

 


2-3. Parameter Tuning with Grid Search in caret

다음은 직접 지정한 파라미터 중 가장 좋은 값을 찾아주는 Grid Search 방법이다.

코드는 아래와 같다.

 

model3 <- caret::train(Species ~ ., data = train,
                       method = "knn",
                       trControl = tune2,
                       tuneGrid = expand.grid(k = 1:10))

 

tuneGrid 에 직접 지정한 파라미터의 범위를 넣어준다. 단, knn은 파라미터가 k 하나지만, xgbLinear 처럼 여러 개인 경우 모든 파라미터를 다 지정해 주어야 한다.

꼭 범위를 넣어준 필요는 없고 k = 2 처럼 하나의 값을 지정해 줄 수도 있다.

 

결과는 다음과 같다.

 

> model3

k-Nearest Neighbors 

 

70 samples

 4 predictor

 2 classes: 'setosa', 'versicolor' 

 

No pre-processing

Resampling: Cross-Validated (5 fold) 

Summary of sample sizes: 56, 56, 56, 56, 56 

Resampling results across tuning parameters:

 

  k   Accuracy  Kappa

   1  1         1    

   2  1         1    

   3  1         1    

   4  1         1    

   5  1         1    

   6  1         1    

   7  1         1    

   8  1         1    

   9  1         1    

  10  1         1    

 

Accuracy was used to select the optimal model using the largest value.

The final value used for the model was k = 10.

 

 

Random Search와 마찬가지로 파라미터 값 별 Accuracy는 plot으로 그려 볼 수 있다.

 

데이터 셋의 크기가 크고, 지정해 주어야 할 파라미터의 수가 많으면 모든 값을 Grid Search로 하기에는 시간이 너무 오래 걸린다.

따라서 Random Search로 값을  먼저 찾아보고, 가장 좋았던 값 주변의 몇 개를 다시 Grid Search로 찾는 것을 추천한다.

 

 

반응형