데이터 과학의 기본 데이터셋으로 인정받던 붓꽃(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_~ body_mass_g
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Adelie Torge~ 39.1 18.7 181 3750
2 Adelie Torge~ 39.5 17.4 186 3800
3 Adelie Torge~ 40.3 18 195 3250
4 Adelie Torge~ NA NA NA NA
5 Adelie Torge~ 36.7 19.3 193 3450
6 Adelie Torge~ 39.3 20.6 190 3650
7 Adelie Torge~ 38.9 17.8 181 3625
8 Adelie Torge~ 39.2 19.6 195 4675
9 Adelie Torge~ 34.1 18.1 193 3475
10 Adelie Torge~ 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 <- magick::image_join(.)
%>%
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 <- magick::image_join(.)
%>%
tidymodels_pkgs_img image_scale('150') %>%
image_append(stack = FALSE)
나름 잘 정리되어 있어 결측값만 처리하고 연도와 펭귄이 거주하고 있는 섬만 제거한다.
penguin %>%
penguin_df <- filter(!is.na(sex)) %>%
select(-year, -island) %>%
mutate_if(is.character, as.factor)
펭귄 데이터셋에서 성별(sex
)을 예측하는 모형을 구축해본다.
initial_split()
함수로 훈련/시험 데이터셋으로 나누고, training()
, testing()
함수로 훈련/시험 데이터를 기계학습을 위한 데이터로 준비한다.
library(tidymodels)
# 훈련 시험 데이터 분할
initial_split(penguin_df, prop = 0.8, strata = sex)
splits <- training(splits)
penguin_train <- testing(splits) penguin_test <-
parsnip
팩키지를 사용해서 데이터를 학습할 혹은 데이터를 가장 잘 설명할 수 있는 모형을 구축한다. 분류 모형이냐 예측모형이냐에 따라 적합한 모형명세(Model Specification) 작업을 수행한다. 펭귄 성별 수컷과 암컷을 예측하는 문제는 분류문제이기 때문에 GLM 모형으로 모형을 선정한다.
library(tidymodels)
logistic_reg() %>%
glm_model <- set_engine('glm') %>%
set_mode('classification')
fit()
함수를 통해 모형 공식을 작성하고 데이터에 적합시킨다. 모형공식은 sex ~ .
으로 종속예측변수는 sex
가 되고 나머지 모든 변수를 예측에 사용하도록 모형공식을 작성한다.
glm_model %>%
glm_fit <- fit(sex ~ ., data = training(splits))
glm_fit
예측모형이 준비되면 시험 데이터 testing(splits)
을 준비하여 시험데이터에 대한 예측값을 뽑아낼 수 있다. 특히 predict()
함수의 인자값을 범주(type = 'class'
)나 확률(type = 'prob'
)로 지정함으로써 예측값을 정답과 편하게 비교할 수 있다.
glm_fit %>%
class_pred <- predict(new_data = testing(splits), type = 'class')
glm_fit %>%
prob_pred <- predict(new_data = testing(splits), type = 'prob')
testing(splits) %>%
evaluation_tbl <- select(sex) %>%
bind_cols(class_pred) %>%
bind_cols(prob_pred)
evaluation_tbl
# A tibble: 65 x 4
sex .pred_class .pred_female .pred_male
<fct> <fct> <dbl> <dbl>
1 female female 0.672 0.328
2 female female 0.679 0.321
3 female female 0.949 0.0507
4 male female 0.689 0.311
5 female female 0.973 0.0270
6 female female 0.939 0.0612
7 female female 0.996 0.00436
8 male male 0.0140 0.986
9 female female 0.990 0.00962
10 male male 0.0000891 1.00
# ... with 55 more rows
모형성능에 대한 평가는 yardstick
팩키지의 다양한 평가함수를 통해 수행한다. 이를 위해서 시험데이터에 대한 정답과 모형의 예측값과 예측확률이 함께 준비되어야 한다. 가장 먼저 정답과 모형의 성능을 평가하는 가장 일반적인 방식이 오차행렬(confusion matrix)을 사용하는 것이다. 이를 위해서 앞서 준비한 evaluation_tbl
데이터프레임을 정답과 모형 예측값과 관측점별로 비교하여 오차표를 작성한다.
conf_mat(evaluation_tbl,
truth = sex,
estimate = .pred_class)
Truth
Prediction female male
female 30 5
male 2 28
혹은 한 발 더 나아가 conf_mat()
함수와 summmary()
함수를 파이프로 조합시키게 되면 가능한 모형성능 측정지표를 얻을 수 있다.
conf_mat(evaluation_tbl,
truth = sex,
estimate = .pred_class) %>%
summary()
# A tibble: 13 x 3
.metric .estimator .estimate
<chr> <chr> <dbl>
1 accuracy binary 0.892
2 kap binary 0.785
3 sens binary 0.938
4 spec binary 0.848
5 ppv binary 0.857
6 npv binary 0.933
7 mcc binary 0.788
8 j_index binary 0.786
9 bal_accuracy binary 0.893
10 detection_prevalence binary 0.538
11 precision binary 0.857
12 recall binary 0.938
13 f_meas binary 0.896
범주 분류예측모형에서 가장 많이 인용되는 분류모형 측정지표(metric)을 사용해서 앞서 개발한 예측모형에 대한 성능을 파악해보자.
metric_set(accuracy, sens, precision, recall, f_meas)
penguin_metrics <-
penguin_metrics(evaluation_tbl,
truth = sex,
estimate = .pred_class)
# A tibble: 5 x 3
.metric .estimator .estimate
<chr> <chr> <dbl>
1 accuracy binary 0.892
2 sens binary 0.938
3 precision binary 0.857
4 recall binary 0.938
5 f_meas binary 0.896
roc_auc()
함수를 사용하게 되면 한계점(threshold) 별로 모형성능을 판단할 수 있다. ROC AUC 값은 다음과 같은 모형성능 등급표가 많이 참고되고 있다.
roc_auc(evaluation_tbl,
truth = sex,
.pred_female)
# A tibble: 1 x 3
.metric .estimator .estimate
<chr> <chr> <dbl>
1 roc_auc binary 0.982
이를 시각화하면 다음과 같다.
roc_curve(evaluation_tbl,
truth = sex,
%>%
.pred_female) autoplot()
훈련/시험 데이터셋 구분부터 시작하여 예측모형 설정과 적합 및 평가과정을 자동화할 수 있다. 특히 마지막 last_fit()
, collect_metrics()
, collect_predictions()
을 통해서 중간과정을 생략하고 Auto-ML에 한 걸음 다가설 수 있다.
# 훈련 시험 데이터 분할
initial_split(penguin_df, prop = 0.8, strata = sex)
splits <-
# 모형상세
logistic_reg() %>%
glm_model <- set_engine('glm') %>%
set_mode('classification')
# 모형 최종적합
glm_model %>%
glm_last_fit <- last_fit(sex ~ ., split = splits)
# 모형 평가
%>%
glm_last_fit collect_metrics()
# A tibble: 2 x 4
.metric .estimator .estimate .config
<chr> <chr> <dbl> <chr>
1 accuracy binary 0.892 Preprocessor1_Model1
2 roc_auc binary 0.942 Preprocessor1_Model1
# 모형 예측
glm_last_fit %>%
last_fit_tbl <- collect_predictions()
last_fit_tbl
# 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.893 0.107 3 female fema~ Preprocessor1_~
2 train/test s~ 0.639 0.361 4 female fema~ Preprocessor1_~
3 train/test s~ 0.000533 0.999 10 male male Preprocessor1_~
4 train/test s~ 0.000000662 1.00 15 male male Preprocessor1_~
5 train/test s~ 0.737 0.263 17 female male Preprocessor1_~
6 train/test s~ 0.920 0.0799 20 female male Preprocessor1_~
7 train/test s~ 0.947 0.0529 23 female fema~ Preprocessor1_~
8 train/test s~ 0.00543 0.995 46 male male Preprocessor1_~
9 train/test s~ 1.00 0.0000293 53 female fema~ Preprocessor1_~
10 train/test s~ 0.216 0.784 54 male male Preprocessor1_~
# ... with 55 more rows
# 모형 평가 최종 지표 : https://github.com/tidymodels/yardstick/issues/128
# classification_metrics <- metric_set(accuracy, sens, spec, precision, recall, roc_auc)
#
# classification_metrics(last_fit_tbl,
# truth = sex,
# estimate = .pred_female,
# .pred_class)
데이터 과학자 이광춘 저작
kwangchun.lee.7@gmail.com