1 펭귄 데이터셋1

데이터 과학의 기본 데이터셋으로 인정받던 붓꽃(Iris) 데이터가 이제는 자리를 펭귄 데이터셋에게 자리를 물려주는 듯 싶다. 기초 통계학, 시각화 뿐만 아니라 tidymodels에도 이를 기본 데이터셋으로 활용하는 사례가 심심치 않게 보여주고 있다. 이런 추세는 최근 TidyTuesday 2020년 31번째 데이터셋(2020-07-28)으로 팔머 팽귄(Palmer Penguins)으로 당첨되면서 Iris 데이터를 대체하는 것은 기정사실화 된 듯 싶다.

library(tidyverse)
tuesdata <- tidytuesdayR::tt_load('2020-07-28')

    Downloading file 1 of 2: `penguins.csv`
    Downloading file 2 of 2: `penguins_raw.csv`
penguin <- tuesdata$penguins

penguin
# A tibble: 344 x 8
   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <chr>   <chr>              <dbl>         <dbl>             <dbl>       <dbl>
 1 Adelie  Torgersen           39.1          18.7               181        3750
 2 Adelie  Torgersen           39.5          17.4               186        3800
 3 Adelie  Torgersen           40.3          18                 195        3250
 4 Adelie  Torgersen           NA            NA                  NA          NA
 5 Adelie  Torgersen           36.7          19.3               193        3450
 6 Adelie  Torgersen           39.3          20.6               190        3650
 7 Adelie  Torgersen           38.9          17.8               181        3625
 8 Adelie  Torgersen           39.2          19.6               195        4675
 9 Adelie  Torgersen           34.1          18.1               193        3475
10 Adelie  Torgersen           42            20.2               190        4250
# … with 334 more rows, and 2 more variables: sex <chr>, year <dbl>

2 팩키지2

2.1 tidymverse 팩키지

데이터 팩키지와는 별도로 tidymodels 예측모형 개발에 간접적으로 사용된 팩키지는 다음과 같다.

library(magick)

pkgs <- c('tidyverse', 'tidymodels', 'parsnip', 'ggplot2', 'pipe', 'purrr', 'usethis')

pkgs_path <- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{pkgs}.svg")

pkgs_img <- purrr::map(pkgs_path, magick::image_read) %>% 
  magick::image_join(.)

pkgs_img %>% 
  image_scale('150') %>% 
  image_append(stack = FALSE)  

2.2 tidymodels 팩키지

tidymodels를 구성하는 핵심 팩키지는 다음과 같다.

tidymodels_pkgs <- c('rsample', 'recipes', 'parsnip', 'yardstick', 'tune', 'dials', 'workflows', 'plumber')

tidymodels_pkgs_path <- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{tidymodels_pkgs}.svg")

tidymodels_pkgs_img <- purrr::map(tidymodels_pkgs_path, magick::image_read) %>% 
  magick::image_join(.)

tidymodels_pkgs_img %>% 
  image_scale('150') %>% 
  image_append(stack = FALSE)  

3 데이터 전처리

나름 잘 정리되어 있어 결측값만 처리하고 연도와 펭귄이 거주하고 있는 섬만 제거한다.

penguin_tbl <- penguin %>%
  filter(!is.na(sex)) %>%
  select(-year, -island) %>% 
  mutate_if(is.character, as.factor)

4 성별예측 모형3

펭귄 데이터셋에서 성별(sex)을 예측하는 모형을 구축해본다. 이를 위해서 사용되는 기본적인 팩키지는 다음과 같다.

  • 훈련/시험 데이터 구분을 위해서 `rsample``
  • 피처 공학을 위해서 recipes
  • 예측모형을 지정하기 위해서 parsnip
  • 예측모형 작업흐름 관리를 위해서 workflows
  • 예측모형 성능평가를 위해서 yardstick
pkgs <- c('rsample', 'recipes', 'parsnip', 'workflows', 'yardstick')

pkgs_path <- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{pkgs}.svg")

pkgs_img <- purrr::map(pkgs_path, magick::image_read) %>% 
  magick::image_join(.)

pkgs_img %>% 
  image_scale('150') %>% 
  image_append(stack = FALSE)  

4.1 훈련/교차검증/시험 데이터셋

initial_split() 함수로 훈련/시험 데이터셋으로 나누고, 필요한 경우 vfold_cv()함수를 사용해서 hyper parameter 튜닝 등을 통한 최적 모형 선정을 위해서 교차검증 데이터셋을 준비한다.

library(tidymodels)

# 훈련 시험 데이터 분할
splits <- initial_split(penguin_tbl, prop = 0.8, strata = sex)

4.2 피처 공학

피처 공학(Feature Engineering)을 적용하여 예측모형 정확도 향상에 사용될 모형 행렬(Model Matrix)을 준비한다.

penguin_recipe <- recipe(sex ~ ., data = training(splits)) %>%
  step_corr(all_numeric(), threshold = 0.9) %>% 
  step_normalize(all_numeric()) %>% 
  step_dummy(all_nominal(), -all_outcomes())

penguin_recipe
Data Recipe

Inputs:

      role #variables
   outcome          1
 predictor          5

Operations:

Correlation filter on all_numeric()
Centering and scaling for all_numeric()
Dummy variables from all_nominal(), -all_outcomes()

4.3 모형 아키텍처

펭귄 성별 예측에 사용될 모형 아키텍처를 선정하는데 우선 가장 많이 사용되는 GLM 모형을 선택한다.

glm_spec <- logistic_reg() %>%
  set_mode("classification") %>% 
  set_engine("glm") 

glm_spec
Logistic Regression Model Specification (classification)

Computational engine: glm 

4.4 모형 작업흐름

workflows 팩키지를 사용해서 예측 모형 작업흐름을 완성한다. 먼저 workflow()를 설정한다. 다양한 모형조합을 작업흐름에 맞춰 유연하고 수월히 최적 모형 구축을 할 수 있다.

penguin_wf <- workflow() %>%
  add_recipe(penguin_recipe) %>% 
  add_model(glm_spec)

penguin_wf
══ Workflow ════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: logistic_reg()

── Preprocessor ────────────────────────────────────────────────────────────────
3 Recipe Steps

● step_corr()
● step_normalize()
● step_dummy()

── Model ───────────────────────────────────────────────────────────────────────
Logistic Regression Model Specification (classification)

Computational engine: glm 

4.5 모형 적합(fit)

CV 교차검증 표본 이전에 기본적으로 작업흐름을 통해 훈련/시험 데이터셋을 대상으로 예측모형 개발을 자동화시킨다.

penguin_wf_fit <- penguin_wf  %>% 
  last_fit(split = splits)

penguin_wf_fit
# Resampling results
# Manual resampling 
# A tibble: 1 x 6
  splits       id           .metrics      .notes       .predictions    .workflow
  <list>       <chr>        <list>        <list>       <list>          <list>   
1 <split [268… train/test … <tibble [2 ×… <tibble [0 … <tibble [65 × … <workflo…

4.6 모형 평가

collect_metrics() 함수를 사용해서 앞서 제작한 펭귄성별 예측모형에 대한 성능을 평가해보자.

penguin_wf_fit %>% 
  collect_metrics()
# A tibble: 2 x 4
  .metric  .estimator .estimate .config             
  <chr>    <chr>          <dbl> <chr>               
1 accuracy binary         0.938 Preprocessor1_Model1
2 roc_auc  binary         0.972 Preprocessor1_Model1

4.7 예측

collect_predictions() 함수를 사용해서 예측모형을 통해 실제 예측값을 데이터프레임으로 저장시킨다. 시험 데이터에 대한 펭귄 성별 예측확률과 실제 성별 범주, 예측한 성별 범주값이 관측점 펭귄 별로 데이터프레임으로 저장되어 출력된다.

penguin_wf_fit %>% 
  collect_predictions()
# A tibble: 65 x 7
   id            .pred_female .pred_male  .row .pred_class sex   .config        
   <chr>                <dbl>      <dbl> <int> <fct>       <fct> <chr>          
 1 train/test s…       0.242    0.758        1 male        male  Preprocessor1_…
 2 train/test s…       0.744    0.256        6 female      fema… Preprocessor1_…
 3 train/test s…       0.912    0.0881       8 female      fema… Preprocessor1_…
 4 train/test s…       0.645    0.355       12 female      fema… Preprocessor1_…
 5 train/test s…       0.730    0.270       21 female      fema… Preprocessor1_…
 6 train/test s…       0.0263   0.974       25 male        male  Preprocessor1_…
 7 train/test s…       0.258    0.742       42 male        male  Preprocessor1_…
 8 train/test s…       0.992    0.00837     47 female      fema… Preprocessor1_…
 9 train/test s…       0.0738   0.926       52 male        male  Preprocessor1_…
10 train/test s…       1.00     0.000111    53 female      fema… Preprocessor1_…
# … with 55 more rows

5 성별예측 CV 모형4

초모수(Hyper Parameter)를 활용할 수 있는 예측모형이 더 성능이 높은 것으로 알려져 있어, 펭귄 데이터셋에서 성별(sex)을 예측하는 모형을 구축해본다. 이를 위해서 사용되는 기본적인 팩키지는 기존 단순 훈련/시험 예측모형에 추가하여 tune, dials 팩키지가 추가된다.

  • 훈련/시험 데이터 구분을 위해서 `rsample``
  • 피처 공학을 위해서 recipes
  • 예측모형을 지정하기 위해서 parsnip
  • 예측모형 작업흐름 관리를 위해서 workflows
  • 예측모형 성능평가를 위해서 yardstick
  • 초모수 튜닝: tune, dials
pkgs <- c('rsample', 'recipes', 'parsnip', 'tune', 'dials', 'workflows', 'yardstick')

pkgs_path <- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{pkgs}.svg")

pkgs_img <- purrr::map(pkgs_path, magick::image_read) %>% 
  magick::image_join(.)

pkgs_img %>% 
  image_scale('150') %>% 
  image_append(stack = FALSE)  

5.1 훈련/교차검증/시험 데이터셋

initial_split() 함수로 훈련/시험 데이터셋으로 나누고, 초모수가 포함된 강력한 예측모형 구축을 위해서 vfold_cv()함수를 사용해서 hyper parameter 튜닝 등을 통한 최적 모형 선정을 위해서 교차검증 데이터셋을 준비한다.

library(tidymodels)

# 훈련 시험 데이터 분할
splits <- initial_split(penguin_tbl, prop = 0.8, strata = sex)

# 교차검증 데이터셋
set.seed(777)
penguin_folds <- vfold_cv(training(splits),
                          v = 3,
                          strata = sex)
penguin_folds
#  3-fold cross-validation using stratification 
# A tibble: 3 x 2
  splits           id   
  <list>           <chr>
1 <split [178/90]> Fold1
2 <split [179/89]> Fold2
3 <split [179/89]> Fold3

5.2 피처 공학

피처 공학(Feature Engineering)을 적용하여 예측모형 정확도 향상에 사용될 모형 행렬(Model Matrix)을 준비한다.

penguin_recipe <- recipe(sex ~ ., data = training(splits)) %>%
  step_corr(all_numeric(), threshold = 0.9) %>% 
  step_normalize(all_numeric()) %>% 
  step_dummy(all_nominal(), -all_outcomes())

penguin_recipe
Data Recipe

Inputs:

      role #variables
   outcome          1
 predictor          5

Operations:

Correlation filter on all_numeric()
Centering and scaling for all_numeric()
Dummy variables from all_nominal(), -all_outcomes()

5.3 모형 아키텍처

펭귄 성별 예측에 사용될 모형 아키텍처를 선정하는데 우선 가장 많이 사용되는 GLM 모형을 선택한다.

glm_spec <- logistic_reg() %>%
  set_mode("classification") %>% 
  set_engine("glm") 

glm_spec
Logistic Regression Model Specification (classification)

Computational engine: glm 

5.4 모형 작업흐름

workflows 팩키지를 사용해서 예측 모형 작업흐름을 완성한다. 먼저 workflow()를 설정한다. 다양한 모형조합을 작업흐름에 맞춰 유연하고 수월히 최적 모형 구축을 할 수 있다.

penguin_wf <- workflow() %>%
  add_recipe(penguin_recipe) %>% 
  add_model(glm_spec)

penguin_wf
══ Workflow ════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: logistic_reg()

── Preprocessor ────────────────────────────────────────────────────────────────
3 Recipe Steps

● step_corr()
● step_normalize()
● step_dummy()

── Model ───────────────────────────────────────────────────────────────────────
Logistic Regression Model Specification (classification)

Computational engine: glm 

5.5 CV 교차표본 대상 모형 적합(fit)

CV 교차검증 표본을 활용하여 각 재표집 표본별로 데이터에 앞서 정의한 예측모형 glm을 적합시킨다.

penguin_rs_wf_fit <- penguin_wf  %>% 
  fit_resamples(resamples = penguin_folds)

penguin_rs_wf_fit
# Resampling results
# 3-fold cross-validation using stratification 
# A tibble: 3 x 4
  splits           id    .metrics         .notes          
  <list>           <chr> <list>           <list>          
1 <split [178/90]> Fold1 <tibble [2 × 4]> <tibble [0 × 1]>
2 <split [179/89]> Fold2 <tibble [2 × 4]> <tibble [0 × 1]>
3 <split [179/89]> Fold3 <tibble [2 × 4]> <tibble [0 × 1]>

5.6 CV 교차표본 모형 평가

collect_metrics() 함수를 사용해서 앞서 제작한 펭귄성별 예측모형에 대한 성능을 평가해보자.

penguin_rs_wf_fit %>% 
  collect_metrics()
# A tibble: 2 x 6
  .metric  .estimator  mean     n std_err .config             
  <chr>    <chr>      <dbl> <int>   <dbl> <chr>               
1 accuracy binary     0.899     3  0.0292 Preprocessor1_Model1
2 roc_auc  binary     0.971     3  0.0105 Preprocessor1_Model1

CV가 3이기 때문에 각 재추출표본별로 적합시킨 예측모형 성능을 평가하면 collect_metrics() 함수에 summarize = FALSE를 넣어 결과를 확인할 수 있다.

penguin_rs_wf_fit %>% 
  collect_metrics( summarize = FALSE)
# A tibble: 6 x 5
  id    .metric  .estimator .estimate .config             
  <chr> <chr>    <chr>          <dbl> <chr>               
1 Fold1 accuracy binary         0.844 Preprocessor1_Model1
2 Fold1 roc_auc  binary         0.953 Preprocessor1_Model1
3 Fold2 accuracy binary         0.944 Preprocessor1_Model1
4 Fold2 roc_auc  binary         0.989 Preprocessor1_Model1
5 Fold3 accuracy binary         0.910 Preprocessor1_Model1
6 Fold3 roc_auc  binary         0.973 Preprocessor1_Model1

5.7 최적모형 선택

show_best() 함수로 가장 좋은 모형 평가결과를 확인한다.

penguin_rs_wf_fit %>% 
  show_best(metric = 'roc_auc')
# A tibble: 1 x 6
  .metric .estimator  mean     n std_err .config             
  <chr>   <chr>      <dbl> <int>   <dbl> <chr>               
1 roc_auc binary     0.971     3  0.0105 Preprocessor1_Model1
 

데이터 과학자 이광춘 저작

kwangchun.lee.7@gmail.com