기계학습 \(H_2O\) 모형을 크게 회귀모형과 분류모형으로 나누어서 회귀모형은 mpg 연비데이터, 분류모형은 attrition 데이터로 기계학습 예측모형을 개발한다. 그리고 나서 DALEX를 주된 모형 이해와 해석을 위한 엔진으로 사용해서 살펴본다.
mpg 연비예측 회귀분석 1ggplot2에 포함된 mpg 데이터를 사용해서 \(H_2O\) 기계학습 예측모형을 개발한다.
mpg 연비 데이터mpg 연비 데이터, 즉 데이터프레임을 훈련과 시험데이터로 구분하여 \(H_2O\) 기계학습 모형에 준비한다.
# 0. 환경설정 -----
library(tidyverse)
library(h2o)
library(recipes)
library(skimr)
library(caret)
library(DALEX)
library(cowplot)
## H2O 초기화 ----
h2o.no_progress()
h2o.init() Connection successful!
R is connected to the H2O cluster:
H2O cluster uptime: 4 hours 25 minutes
H2O cluster timezone: Asia/Seoul
H2O data parsing timezone: UTC
H2O cluster version: 3.20.0.2
H2O cluster version age: 2 months and 1 day
H2O cluster name: H2O_started_from_R_victorlee_ygj589
H2O cluster total nodes: 1
H2O cluster total memory: 3.27 GB
H2O cluster total cores: 4
H2O cluster allowed cores: 4
H2O cluster healthy: TRUE
H2O Connection ip: localhost
H2O Connection port: 54321
H2O Connection proxy: NA
H2O Internal Security: FALSE
H2O API Extensions: Algos, AutoML, Core V3, Core V4
R Version: R version 3.5.1 (2018-07-02)
# 1. 연비 데이터 -----
## 1.1. 데이터 가져오기 -----
mpg_dat <- ggplot2::mpg
## 1.2. 데이터 정제 -----
mpg_df <- mpg_dat %>%
mutate_if(is.character, as.factor) %>%
mutate(manufacturer = fct_lump(manufacturer, 9),
fl = fct_lump(fl, 2),
class = fct_lump(class, 5),
trans = ifelse(str_detect(trans, "auto"), "auto", "manual") %>% as.factor,
year = as.factor(year)) %>%
select(cty, manufacturer, displ, year, cyl, trans, drv, fl, class)
## 1.3. 훈련/시험 데이터 분할 -----
mpg_idx <- createDataPartition(mpg_df$cty, times = 1, p=0.7, list=FALSE)
mpg_train <- mpg_df[mpg_idx, ]
mpg_test <- mpg_df[-mpg_idx, ]explainer 객체\(H_2O\) 기계학습 모형을 개발한다. h2o.glm, h2o.gbm, h2o.automl로 예측모형 객체를 생성시킨다. 그리고 나서 mpg_predict() 함수를 지정하고 이를 통해 explainer 객체를 생성시킨다.
# 2. 예측모형 개발 -----
## 2.1. 데이터프레임 --> H2O 데이터프레임
mpg_train_h2o <- as.h2o(mpg_train)
mpg_test_h2o <- as.h2o(mpg_test)
## 2.2. 예측모형 적합
model_h2o_glm <- h2o.glm(y = "cty", training_frame = mpg_train_h2o)
model_h2o_gbm <- h2o.gbm(y = "cty", training_frame = mpg_train_h2o)
model_h2o_automl <- h2o.automl(y = "cty", training_frame = mpg_train_h2o, max_models = 10)
# 3. 모형 이해와 설명 -----
## 3.1. explainer 객체 생성
mpg_predict <- function(model, newdata) {
newdata_h2o <- as.h2o(newdata)
res <- as.data.frame(h2o.predict(model, newdata_h2o))
return(as.numeric(res$predict))
}
explainer_h2o_glm <- explain(model = model_h2o_glm,
data = mpg_test[,-1],
y = mpg_test$cty,
predict_function = mpg_predict,
label = "h2o GLM")
explainer_h2o_gbm <- explain(model = model_h2o_gbm,
data = mpg_test[,-1],
y = mpg_test$cty,
predict_function = mpg_predict,
label = "h2o GBM")
explainer_h2o_automl <- explain(model = model_h2o_automl,
data = mpg_test[,-1],
y = mpg_test$cty,
predict_function = mpg_predict,
label = "h2o AutoML")\(H_2O\) 예측모형에 대한 이해와 설명을 위해서 모형성능, 변수중요도, 예측모형 변수 반응(연속형, 범주형)과 예측에 대해서 순차적으로 확인한다.
## 3.2. 모형성능 -----
mp_h2o_glm <- model_performance(explainer_h2o_glm)
mp_h2o_gbm <- model_performance(explainer_h2o_gbm)
mp_h2o_automl <- model_performance(explainer_h2o_automl)
plot(mp_h2o_glm, mp_h2o_gbm, mp_h2o_automl)plot(mp_h2o_glm, mp_h2o_gbm, mp_h2o_automl, geom = "boxplot")## 3.3. 변수 중요도 -----
vi_h2o_glm <- variable_importance(explainer_h2o_glm, type="difference")
vi_h2o_gbm <- variable_importance(explainer_h2o_gbm, type="difference")
vi_h2o_automl <- variable_importance(explainer_h2o_automl, type="difference")
plot(vi_h2o_glm, vi_h2o_gbm, vi_h2o_automl)## 3.4. 예측모형 변수 반응(연속형) -----
pdp_h2o_glm <- variable_response(explainer_h2o_glm, variable = "displ")
pdp_h2o_gbm <- variable_response(explainer_h2o_gbm, variable = "displ")
pdp_h2o_automl <- variable_response(explainer_h2o_automl, variable = "displ")
plot(pdp_h2o_glm, pdp_h2o_gbm, pdp_h2o_automl)## 3.4. 예측모형 변수 반응(범주형) -----
# mpp_h2o_glm <- variable_response(explainer_h2o_glm, variable = "class", type = "factor")
mpp_h2o_gbm <- variable_response(explainer_h2o_gbm, variable = "class", type = "factor")
mpp_h2o_automl <- variable_response(explainer_h2o_automl, variable = "class", type = "factor")
plot(mpp_h2o_gbm, mpp_h2o_automl)## 3.5. 예측 이해 -----
new_car <- mpg_test[1,]
pb_h2o_glm <- prediction_breakdown(explainer_h2o_glm, observation = new_car)
pb_h2o_gbm <- prediction_breakdown(explainer_h2o_gbm, observation = new_car)
pb_h2o_automl <- prediction_breakdown(explainer_h2o_automl, observation = new_car)
plot(pb_h2o_glm, pb_h2o_gbm, pb_h2o_automl)attrition 데이터rsample 팩키지에 포함된 attrition 데이터셋을 가져온다. 이번에는 데이터를 전부 \(H_2O\) 데이터프레임으로 변환시켜 예측모형 구축작업을 수행한다.
# 1. 인력 이탈(Job Attrition) 데이터 -----
## 1.1. 데이터 가져오기 -----
attr_df <- rsample::attrition %>%
mutate_if(is.ordered, factor, ordered = FALSE) %>%
mutate(Attrition = recode(Attrition, "Yes" = "1", "No" = "0") %>% factor(levels = c("1", "0")))
## 1.2. 데이터프레임 --> H2O 데이터프레임 -----
attr_h2o <- as.h2o(attr_df)
## 1.3. 데이터 분할 -----
splits <- h2o.splitFrame(attr_h2o, ratios = c(.7, .15), destination_frames = c("train","valid","test"))
names(splits) <- c("train","valid","test")
# 1.4. 모형 변수명 설정
y <- "Attrition"
x <- setdiff(names(attr_df), y) GLM, Random Forest, GBM, AutoML 예측모형을 생성하고 각 모형의 성능을 AUC 기준으로 살펴본다.
# 2. 예측모형 구축 -----
## 2.1. GLM, RF, GBM, autoML -----
attr_glm <- h2o.glm(x = x, y = y,
training_frame = splits$train,
validation_frame = splits$valid,
family = "binomial")
attr_rf <- h2o.randomForest(x = x, y = y,
training_frame = splits$train,
validation_frame = splits$valid,
ntrees = 1000,
stopping_metric = "AUC",
stopping_rounds = 10,
stopping_tolerance = 0.005)
attr_gbm <- h2o.gbm(x = x, y = y,
training_frame = splits$train,
validation_frame = splits$valid,
ntrees = 1000,
stopping_metric = "AUC",
stopping_rounds = 10,
stopping_tolerance = 0.005)
attr_automl <- h2o.automl(x = x, y = y,
training_frame = splits$train,
validation_frame = splits$valid,
max_models = 10)
## 2.2. 모형성능
data.frame("GLM" = h2o.auc(attr_glm, valid = TRUE),
"RF" = h2o.auc(attr_rf, valid = TRUE),
"GBM" = h2o.auc(attr_gbm, valid = TRUE),
"AutoML" = h2o.auc(attr_automl@leader, valid = TRUE)) %>%
gather(모형, AUC값) %>%
arrange(desc(AUC값)) 모형 AUC값
1 RF 0.8518545
2 GLM 0.8232396
3 GBM 0.7994784
4 AutoML 0.7548319
예측모형 설명자를 생성한다. explain() 함수에 예측함수(attr_pred), 검증/시험 데이터, 검증/시험 예측결과가 필요하다. 각 형태에 맞춰 데이터를 준비하고 이를 explain() 함수에 넣어준다.
# 3. 예측모형 이해와 설명 -----
## 3.1. explainer 객체 생성 -----
### 교차검증 데이터프레임 생성
x_valid <- as.data.frame(splits$valid)[, x]
### 예측변수 숫자형 벡터로 변환
y_valid <- as.vector(as.numeric(as.character(splits$valid$Attrition)))
### 직원이탈 예측함수
attr_pred <- function(model, newdata) {
results <- as.data.frame(h2o.predict(model, as.h2o(newdata)))
return(results[[3L]])
}
# attr_pred(attr_rf, x_valid) %>% head()
### GLM 설명자
explainer_glm <- explain(
model = attr_glm,
data = x_valid,
y = y_valid,
predict_function = attr_pred,
label = "h2o GLM"
)
### RF 설명자
explainer_rf <- explain(
model = attr_rf,
data = x_valid,
y = y_valid,
predict_function = attr_pred,
label = "h2o RF"
)
### GBM 설명자
explainer_gbm <- explain(
model = attr_gbm,
data = x_valid,
y = y_valid,
predict_function = attr_pred,
label = "h2o GBM"
)
### AutoML 설명자
explainer_automl <- explain(
model = attr_automl,
data = x_valid,
y = y_valid,
predict_function = attr_pred,
label = "h2o AutoML"
)예측모형 이해와 설명에서 먼저 예측모형 자체에 대한 이해와 설명이 필요하다. 이를 위해서 모형성능, 중요변수, 중요 변수별 예측변수 연관 설명을 순차적으로 진행한다.
## 3.2. 예측모형 성능 -----
resids_glm <- model_performance(explainer_glm)
resids_rf <- model_performance(explainer_rf)
resids_gbm <- model_performance(explainer_gbm)
resids_automl <- model_performance(explainer_automl)
p1 <- plot(resids_glm, resids_rf, resids_gbm, resids_automl) +
theme(legend.position = "top")
p2 <- plot(resids_glm, resids_rf, resids_gbm, resids_automl, geom = "boxplot") +
theme(legend.position = "top")
plot_grid(p1, p2, nrow = 1)## 3.3. 변수중요도 -----
vip_glm <- variable_importance(explainer_glm, n_sample = -1, loss_function = loss_root_mean_square)
vip_rf <- variable_importance(explainer_rf, n_sample = -1, loss_function = loss_root_mean_square)
vip_gbm <- variable_importance(explainer_gbm, n_sample = -1, loss_function = loss_root_mean_square)
vip_automl <- variable_importance(explainer_automl, n_sample = -1, loss_function = loss_root_mean_square)
plot(vip_glm, vip_rf, vip_gbm, vip_automl, max_vars = 10)## 3.4. 중요 변수별 예측변수 연관 설명 -----
### 연속형 변수
pdp_glm <- variable_response(explainer_glm, variable = "Age", type = "pdp")
pdp_rf <- variable_response(explainer_rf, variable = "Age", type = "pdp")
pdp_gbm <- variable_response(explainer_gbm, variable = "Age", type = "pdp")
pdp_automl <- variable_response(explainer_automl, variable = "Age", type = "pdp")
plot(pdp_glm, pdp_rf, pdp_gbm, pdp_automl)### 범주형 변수
cat_glm <- variable_response(explainer_glm, variable = "EnvironmentSatisfaction", type = "factor")
cat_rf <- variable_response(explainer_rf, variable = "EnvironmentSatisfaction", type = "factor")
cat_gbm <- variable_response(explainer_gbm, variable = "EnvironmentSatisfaction", type = "factor")
cat_automl <- variable_response(explainer_automl, variable = "EnvironmentSatisfaction", type = "factor")
plot(cat_glm, cat_rf, cat_gbm, cat_automl)예측 모형 자체에 대한 이해와 설명이 된 후에 이를 통해 나온 예측값에 대한 이해와 설명이 필요하다. 이를 위해서 breakDown 팩키지 prediction_breakdown() 함수에 예측값을 넣어 어떤 변수가 예측에 영향을 주었는지 확인한다.
## 3.5. 예측결과 이해(local interpretation) -----
new_employee <- splits$valid[1, ] %>% as.data.frame()
### Breakdown 계산
new_employee_glm <- prediction_breakdown(explainer_glm, observation = new_employee)
new_employee_rf <- prediction_breakdown(explainer_rf, observation = new_employee)
new_employee_gbm <- prediction_breakdown(explainer_gbm, observation = new_employee)
new_employee_automl <- prediction_breakdown(explainer_automl, observation = new_employee)
new_employee_rf %>% DT::datatable()plot(new_employee_rf)각 예측모형을 상대적으로 비교한다.
list(new_employee_glm,
new_employee_rf,
new_employee_gbm,
new_employee_automl) %>%
purrr::map(~ top_n(., 11, wt = abs(contribution))) %>%
do.call(rbind, .) %>%
mutate(variable = paste0(variable, " (", label, ")")) %>%
ggplot(aes(contribution, reorder(variable, contribution))) +
geom_point() +
geom_vline(xintercept = 0, size = 1, color = "darkgray") +
facet_wrap(~ label, scales = "free_y", ncol = 1) +
ylab(NULL)