데이터 과학의 기본 데이터셋으로 인정받던 붓꽃(Iris) 데이터가 이제는 자리를 펭귄 데이터셋에게 자리를 물려주는 듯 싶다. 기초 통계학, 시각화 뿐만 아니라 tidymodels
에도 이를 기본 데이터셋으로 활용하는 사례가 심심치 않게 보여주고 있다. 이런 추세는 최근 TidyTuesday 2020년 31번째 데이터셋(2020-07-28)으로 팔머 팽귄(Palmer Penguins)으로 당첨되면서 Iris 데이터를 대체하는 것은 기정사실화 된 듯 싶다.
library(tidyverse)
<- tidytuesdayR::tt_load('2020-07-28') tuesdata
Downloading file 1 of 2: `penguins.csv`
Downloading file 2 of 2: `penguins_raw.csv`
<- tuesdata$penguins
penguin
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>
tidymverse
팩키지데이터 팩키지와는 별도로 tidymodels
예측모형 개발에 간접적으로 사용된 팩키지는 다음과 같다.
library(magick)
<- c('tidyverse', 'tidymodels', 'parsnip', 'ggplot2', 'pipe', 'purrr', 'usethis')
pkgs
<- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{pkgs}.svg")
pkgs_path
<- purrr::map(pkgs_path, magick::image_read) %>%
pkgs_img ::image_join(.)
magick
%>%
pkgs_img image_scale('150') %>%
image_append(stack = FALSE)
tidymodels
팩키지tidymodels
를 구성하는 핵심 팩키지는 다음과 같다.
<- c('rsample', 'recipes', 'parsnip', 'yardstick', 'tune', 'dials', 'workflows', 'plumber')
tidymodels_pkgs
<- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{tidymodels_pkgs}.svg")
tidymodels_pkgs_path
<- purrr::map(tidymodels_pkgs_path, magick::image_read) %>%
tidymodels_pkgs_img ::image_join(.)
magick
%>%
tidymodels_pkgs_img image_scale('150') %>%
image_append(stack = FALSE)
나름 잘 정리되어 있어 결측값만 처리하고 연도와 펭귄이 거주하고 있는 섬만 제거한다.
<- penguin %>%
penguin_tbl filter(!is.na(sex)) %>%
select(-year, -island) %>%
mutate_if(is.character, as.factor)
펭귄 데이터셋에서 성별(sex
)을 예측하는 모형을 구축해본다. 이를 위해서 사용되는 기본적인 팩키지는 다음과 같다.
recipes
parsnip
workflows
yardstick
<- c('rsample', 'recipes', 'parsnip', 'workflows', 'yardstick')
pkgs
<- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{pkgs}.svg")
pkgs_path
<- purrr::map(pkgs_path, magick::image_read) %>%
pkgs_img ::image_join(.)
magick
%>%
pkgs_img image_scale('150') %>%
image_append(stack = FALSE)
initial_split()
함수로 훈련/시험 데이터셋으로 나누고, 필요한 경우 vfold_cv()
함수를 사용해서 hyper parameter 튜닝 등을 통한 최적 모형 선정을 위해서 교차검증 데이터셋을 준비한다.
library(tidymodels)
# 훈련 시험 데이터 분할
<- initial_split(penguin_tbl, prop = 0.8, strata = sex) splits
피처 공학(Feature Engineering)을 적용하여 예측모형 정확도 향상에 사용될 모형 행렬(Model Matrix)을 준비한다.
<- recipe(sex ~ ., data = training(splits)) %>%
penguin_recipe 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()
펭귄 성별 예측에 사용될 모형 아키텍처를 선정하는데 우선 가장 많이 사용되는 GLM 모형을 선택한다.
<- logistic_reg() %>%
glm_spec set_mode("classification") %>%
set_engine("glm")
glm_spec
Logistic Regression Model Specification (classification)
Computational engine: glm
workflows
팩키지를 사용해서 예측 모형 작업흐름을 완성한다. 먼저 workflow()
를 설정한다. 다양한 모형조합을 작업흐름에 맞춰 유연하고 수월히 최적 모형 구축을 할 수 있다.
<- workflow() %>%
penguin_wf 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
CV 교차검증 표본 이전에 기본적으로 작업흐름을 통해 훈련/시험 데이터셋을 대상으로 예측모형 개발을 자동화시킨다.
<- penguin_wf %>%
penguin_wf_fit 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…
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
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
초모수(Hyper Parameter)를 활용할 수 있는 예측모형이 더 성능이 높은 것으로 알려져 있어, 펭귄 데이터셋에서 성별(sex
)을 예측하는 모형을 구축해본다. 이를 위해서 사용되는 기본적인 팩키지는 기존 단순 훈련/시험 예측모형에 추가하여 tune
, dials
팩키지가 추가된다.
recipes
parsnip
workflows
yardstick
tune
, dials
<- c('rsample', 'recipes', 'parsnip', 'tune', 'dials', 'workflows', 'yardstick')
pkgs
<- glue::glue("https://raw.githubusercontent.com/rstudio/hex-stickers/master/SVG/{pkgs}.svg")
pkgs_path
<- purrr::map(pkgs_path, magick::image_read) %>%
pkgs_img ::image_join(.)
magick
%>%
pkgs_img image_scale('150') %>%
image_append(stack = FALSE)
initial_split()
함수로 훈련/시험 데이터셋으로 나누고, 초모수가 포함된 강력한 예측모형 구축을 위해서 vfold_cv()
함수를 사용해서 hyper parameter 튜닝 등을 통한 최적 모형 선정을 위해서 교차검증 데이터셋을 준비한다.
library(tidymodels)
# 훈련 시험 데이터 분할
<- initial_split(penguin_tbl, prop = 0.8, strata = sex)
splits
# 교차검증 데이터셋
set.seed(777)
<- vfold_cv(training(splits),
penguin_folds 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
피처 공학(Feature Engineering)을 적용하여 예측모형 정확도 향상에 사용될 모형 행렬(Model Matrix)을 준비한다.
<- recipe(sex ~ ., data = training(splits)) %>%
penguin_recipe 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()
펭귄 성별 예측에 사용될 모형 아키텍처를 선정하는데 우선 가장 많이 사용되는 GLM 모형을 선택한다.
<- logistic_reg() %>%
glm_spec set_mode("classification") %>%
set_engine("glm")
glm_spec
Logistic Regression Model Specification (classification)
Computational engine: glm
workflows
팩키지를 사용해서 예측 모형 작업흐름을 완성한다. 먼저 workflow()
를 설정한다. 다양한 모형조합을 작업흐름에 맞춰 유연하고 수월히 최적 모형 구축을 할 수 있다.
<- workflow() %>%
penguin_wf 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
CV 교차검증 표본을 활용하여 각 재표집 표본별로 데이터에 앞서 정의한 예측모형 glm
을 적합시킨다.
<- penguin_wf %>%
penguin_rs_wf_fit 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]>
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
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