tidymodels
와 XGBoost12“Deep Learning in R” 책에서 François Chollet 와 JJ Allaire는 다음과 같이 XGBoost 의 가치를 평가했다. 즉, 직사각형 정형 데이터에는 XGBoost가 적합하고 비정형 데이터는 딥러닝 모형이 첫번째 데이터 과학자의 도구가 된다.
In 2016 and 2017, Kaggle was dominated by two approaches: gradient boosting machines and deep learning. Specifically, gradient boosting is used for problems where structured data is available, whereas deep learning is used for perceptual problems such as image classification. Practitioners of the former almost always use the excellent XGBoost library.
These are the two techniques you should be the most familiar with in order to be successful in applied machine learning today: gradient boosting machines, for shallow-learning problems; and deep learning, for perceptual problems. In technical terms, this means you’ll need to be familiar with XGBoost and Keras—the two libraries that currently dominate Kaggle competitions.
treesnip
treesnip
팩키지를 통해서 다음 의사결정나무모형을 활용할 수 있다.
tree
엔진: decision_tree()
catboost
엔진: boost_tree()
lightGBM
엔진: boost_tree()
의사결정나무로 예측모형을 개발할 때 모형별로 Hyper Paramter를 튜닝하여 선정해야 한다.
library(tidyverse)
tibble::tribble(
~ parsnip, ~tree,
"min_n", "minsize",
"cost_complexity", "mindev"
) %>% knitr::kable()
parsnip | tree |
---|---|
min_n | minsize |
cost_complexity | mindev |
tibble::tribble(
~ parsnip, ~catboost, ~lightGBM,
'mtry', 'rsm', 'feature_fraction',
'trees', 'iterations', 'num_iterations',
'min_n', 'min_data_in_leaf', 'min_data_in_leaf',
'tree_depth', 'depth', 'max_depth',
'learn_rate', 'learning_rate', 'learning_rate',
'loss_reduction', kableExtra::cell_spec('Not found', color = 'red', bold = TRUE), 'min_gain_to_split',
'sample_size', 'subsample', 'bagging_fraction'
) %>% knitr::kable(escape = FALSE)
parsnip | catboost | lightGBM |
---|---|---|
mtry | rsm | feature_fraction |
trees | iterations | num_iterations |
min_n | min_data_in_leaf | min_data_in_leaf |
tree_depth | depth | max_depth |
learn_rate | learning_rate | learning_rate |
loss_reduction | Not found | min_gain_to_split |
sample_size | subsample | bagging_fraction |
devtools::install_github("curso-r/treesnip")
명령어로 treesnip
을 설치하여 parnsip
에서 활용할 수 있도록 한다.
macOS에서 설치할 경우 Apple Clang의 내용을 참조한다.
GitHub
빌드LightGBM builds 저장소를 참고한다. 먼저 맥 운영체제에 필수적인 두가지 도구를 먼저 설치한다. cmake
, OpenMP
를 설치하고 나서 빌드 과정을 거친다.
brew install cmake
brew install libomp
git clone --recursive https://github.com/microsoft/LightGBM
cd LightGBM
mkdir build
cd build
cmake ..
make -j4
이제 준비가 되어 마지막으로 lightgbm
R 팩키지를 설치힌다.
그리고 나서, 다음과 같이 treesnip
을 설치한다.
직사각형 정형데이터를 기반으로 예측모형을 작성할 경우 일반적으로 Hyper Parameter를 갖는 모형이 우선 검토 대상이 되며 이를 실제 운영에 활용할 경우 Hyper Parameter를 교차검증 데이터에서 추론하여 가장 성능이 좋은 모형을 실제 운영계로 이관하게 된다. 이 과정에서 예측모형의 성능을 평가하는 내용도 필히 살펴봐야 된다.
rsample
recipes
rsample
workflows
parsnip
, treesnip
(XGBoost)dials
tune
yardstick
XGBoost
퍵균 성별 분류기tidymodels
도 tidyverse
와 마찬가지로 library(tidymodels)
명령어로 기계학습에 필요한 팩키지를 모두 가져올 수 있다. tidytuesdayR
를 활용하여 필요한 데이터도 작업공간에 신속히 올려놓는다.
# 팩키지
library(tidyverse)
library(tidymodels)
library(treesnip)
# 데이터
tuesdata <- tidytuesdayR::tt_load('2020-07-28')
Downloading file 1 of 2: `penguins.csv`
Downloading file 2 of 2: `penguins_raw.csv`
간략하게 데이터 정제작업과 함께 범주형, 숫자형 변수에 대한 Feature Engineering도 함께 작업하고 나서, 훈련, 시험, 교차검증 데이터로 쪼개 후속 작업을 준비한다.
# 데이터 전처리
penguin_df <- penguin %>%
filter(!is.na(sex)) %>%
select(-year, -island) %>%
mutate_if(is.character, as.factor)
penguin_rec <- recipe(sex ~ ., data = penguin_df) %>%
# update_role(species, new_role = "id") %>%
update_role(sex, new_role = "outcome") %>%
update_role(
species, bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g,
new_role = "predictor") %>%
# step_string2factor(all_nominal(), -all_outcomes()) %>%
step_normalize(all_numeric()) %>%
# step_novel(all_nominal(), -all_outcomes()) %>%
# step_dummy(all_nominal()) %>%
prep()
# 훈련, 시험, 교차검증 데이터
penguin_split <- initial_split(penguin_df, prop = 0.8, strata = sex)
penguin_train <- training(penguin_split)
penguin_test <- testing(penguin_split)
penguin_cv <- vfold_cv(penguin_train, v =10, repeats = 1)
workflow()
를 정의하기에 앞서 모형 명세작업과 Hyper Parameter 준비작업을 하고 나서 작업흐름을 완성한다.
예측모형을 lightgbm_spec
명세하여 실제 훈련에 사용된 엔진도 함께 명세한다.
Hyper Parameter 탐색공간을 정의한다. 먼저 탐색할 Hyper Parameter를 정의하고 나서, grid_max_entropy()
크기를 size = 30
으로 특정하여 빠른 시간내 탐색이 될 수 있도록 한다.
lightgbm_params <- dials::parameters(
min_n(),
tree_depth()
)
lightgbm_grid <- dials::grid_max_entropy(
lightgbm_params,
size = 30)
lightgbm_grid
# A tibble: 30 x 2
min_n tree_depth
<int> <int>
1 6 13
2 3 11
3 10 7
4 30 6
5 29 2
6 15 8
7 19 13
8 36 9
9 13 12
10 21 1
# … with 20 more rows
workflow
흐름 작성workflow
작업흐름을 생성하고 나서 명세된 모형, 레시피 feature engineering을 순차적으로 적어둔다.
library(doParallel)
all_cores <- parallel::detectCores(logical = FALSE)
registerDoParallel(cores = all_cores)
tictoc::tic()
lightgbm_tuned <- tune::tune_grid(
object = lightgbm_wf,
resamples = penguin_cv,
grid = lightgbm_grid,
metrics = yardstick::metric_set(roc_auc, accuracy),
control = tune::control_grid(verbose = TRUE)
)
tictoc::toc()
102.541 sec elapsed
roc_auc
기준으로 가장 성능좋은 Hyper Paramter 조합을 살펴보자.
# A tibble: 5 x 8
min_n tree_depth .metric .estimator mean n std_err .config
<int> <int> <chr> <chr> <dbl> <int> <dbl> <chr>
1 21 1 roc_auc binary 0.934 10 0.0214 Model10
2 11 1 roc_auc binary 0.933 10 0.0221 Model19
3 4 1 roc_auc binary 0.931 10 0.0221 Model20
4 40 1 roc_auc binary 0.926 10 0.0223 Model16
5 25 2 roc_auc binary 0.916 10 0.0232 Model24
시각화를 통해 Hyper Paramter 탐색결과를 파악하자.
lightgbm_tuned %>%
tune::show_best(metric = "accuracy", n = 10) %>%
tidyr::pivot_longer(min_n:tree_depth, names_to="variable", values_to="value" ) %>%
ggplot(aes(value, mean)) +
geom_line(alpha=1/2)+
geom_point()+
facet_wrap(~variable,scales = "free")+
labs(x="", title = "Best Paramters for Accuracy")
lightgbm_best_params <- lightgbm_tuned %>%
tune::select_best("accuracy")
# lightgbm_best_params
lightgbm_model_final <- lightgbm_spec %>%
finalize_model(lightgbm_best_params)
lightgbm_model_final
Boosted Tree Model Specification (classification)
Main Arguments:
trees = 1000
min_n = 40
tree_depth = 1
Engine-Specific Arguments:
objective = binary:binary_logloss
verbose = -1
Computational engine: lightgbm
lightgbm_wf
작업흐름에 Hyper Parameter가 있어 이를 앞서 Hyper Parameter 탐색을 통해 확정한 최고 성능 Hyper Parameter로 넣어 최종 작업흐름을 완성한다.
══ Workflow ════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: boost_tree()
── Preprocessor ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 Recipe Step
● step_normalize()
── Model ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Boosted Tree Model Specification (classification)
Main Arguments:
trees = 1000
min_n = 40
tree_depth = 1
Engine-Specific Arguments:
objective = binary:binary_logloss
verbose = -1
Computational engine: lightgbm
다음 단계로 last_fit()
을 시험(test) 데이터에 넣어 예측모형 성능을 산출한다.
lightgbm_wf_final_fit <- lightgbm_wf_final %>%
last_fit(penguin_split)
lightgbm_wf_final_fit %>%
collect_metrics()
# A tibble: 2 x 3
.metric .estimator .estimate
<chr> <chr> <dbl>
1 accuracy binary 0.892
2 roc_auc binary 0.968
collect_predictions()
함수로 시험 데이터에 대한 예측 확률과 예측 결과를 담아낸다.
예측확률과 결과가 있기 때문에 conf_mat()
로 confusion matrix도 만들 수 있다.
Truth
Prediction female male
female 27 2
male 5 31
fit()
함수를 사용해서 최종적으로 개발한 모형을 배포한다.
[LightGBM] [Info] Number of positive: 168, number of negative: 176
[LightGBM] [Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 0.000096 seconds.
You can set `force_col_wise=true` to remove the overhead.
[LightGBM] [Info] Total Bins 267
[LightGBM] [Info] Number of data points in the train set: 344, number of used features: 5
[LightGBM] [Info] [binary:BoostFromScore]: pavg=0.488372 -> initscore=-0.046520
[LightGBM] [Info] Start training from score -0.046520
══ Workflow [trained] ══════════════════════════════════════════════════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: boost_tree()
── Preprocessor ────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 Recipe Step
● step_normalize()
── Model ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
<lgb.Booster>
Public:
add_valid: function (data, name)
best_iter: -1
best_score: NA
current_iter: function ()
dump_model: function (num_iteration = NULL, feature_importance_type = 0L)
eval: function (data, name, feval = NULL)
eval_train: function (feval = NULL)
eval_valid: function (feval = NULL)
finalize: function ()
initialize: function (params = list(), train_set = NULL, modelfile = NULL,
lower_bound: function ()
predict: function (data, start_iteration = NULL, num_iteration = NULL,
raw: NA
record_evals: list
reset_parameter: function (params, ...)
rollback_one_iter: function ()
save: function ()
save_model: function (filename, num_iteration = NULL, feature_importance_type = 0L)
save_model_to_string: function (num_iteration = NULL, feature_importance_type = 0L)
set_train_data_name: function (name)
to_predictor: function ()
update: function (train_set = NULL, fobj = NULL)
upper_bound: function ()
Private:
eval_names: NULL
get_eval_info: function ()
handle: 6.94681240057486e-310
higher_better_inner_eval: NULL
init_predictor: NULL
inner_eval: function (data_name, data_idx, feval = NULL)
inner_predict: function (idx)
is_predicted_cur_iter: list
name_train_set: training
name_valid_sets: list
num_class: 1
num_dataset: 1
predict_buffer: list
set_objective_to_none: FALSE
train_set: lgb.Dataset, R6
train_set_version: 1
valid_sets: list
새로운 펭귄을 한 마리 구해서 lightgbm 으로 개발한 예측모형에 넣어 성별을 예측해보자.
new_penguin <- tribble(
~species, ~island, ~bill_length_mm, ~bill_depth_mm, ~flipper_length_mm, ~body_mass_g, ~year,
"Adelie", "Torgersen", 39.1, 18.7, 181, 3750, 2007
)
predict(deploy_model, new_penguin) %>%
bind_cols(predict(deploy_model, new_penguin, type = "prob"))
# A tibble: 1 x 3
.pred_class .pred_female .pred_male
<fct> <dbl> <dbl>
1 male 0.339 0.661
데이터 과학자 이광춘 저작
kwangchun.lee.7@gmail.com