R2D3 웹사이트에 기계학습에 대한 시각적 소개가 잘 정리되어 있다. 뉴욕과 샌프란시스코 두 도시의 부동산을 분류하는 데이터를 바탕으로 의사결정나무(Decision Tree) 기계학습 알고리즘이 동작하는 방식을 마우스 스크롤을 아래로 내리게 되면 시각적으로 확인할 수 있다.
FAQ 웹사이트에서 CSV 파일을 다운로드 받아 직접 기계학습 예측모형을 제작해보자.
caret
+ DALEX 예측모형A Short Introduction to the caret Package 팩키지를 주된 예측모형 엔진으로 사용하고 블랙박스 예측모형을 이해하고 해석하는데 DALEX: Descriptive mAchine Learning EXplanations를 사용한다. 즉, 데이터프레임을 받아 caret
예측모형을 생성하고 이를 DALEX
를 통해 블랙박스 모형을 해석하고 이해하는 작업방식이 된다.
R2D3 뉴욕, 샌프란시스코 부동산 분류 데이터를 다운로드 받아 예측모형 적합을 위한 형태로 가공한다.
# 0. 환경설정 -----
library(tidyverse)
library(caret)
library(recipes)
library(skimr)
library(DALEX)
library(randomForest)
library(e1071)
library(xgboost)
library(cowplot)
# 1. 데이터 -----
## 1.1. 데이터 가져오기
r2d3_df <- read_csv("https://raw.githubusercontent.com/jadeyee/r2d3-part-1-data/master/part_1_data.csv", skip=2)
## 1.2. X/Y 데이터 분할
x_train_tbl <- r2d3_df %>% select(-in_sf)
y_train_tbl <- r2d3_df %>% select(in_sf)
## 1.3. X/Y 데이터 요리
rec_obj <- recipe(~ ., data = x_train_tbl) %>%
# step_scale(all_numeric()) %>%
prep(stringsAsFactors = FALSE)
x_train_processed_tbl <- bake(rec_obj, x_train_tbl)
y_train_processed_tbl <- y_train_tbl
xy_train <- bind_cols(y_train_processed_tbl, x_train_processed_tbl) %>%
mutate(in_sf = as.factor(in_sf))
## 1.4. 훈련/시험 데이터 분할
train_idx <- createDataPartition(xy_train$in_sf, p = 0.7, list = FALSE, times = 1)
xy_train_df <- xy_train[ train_idx,]
xy_test_df <- xy_train[-train_idx,]
GLM, RandomForest, SVM, xgBoost 예측모형으로 부동산을 예측해본다.
# 2. 예측 모형 -----
tune_grid <- expand.grid(nrounds = 200,
max_depth = 5,
eta = 0.05,
gamma = 0.01,
colsample_bytree = 0.75,
min_child_weight = 0,
subsample = 0.5)
## 2.1. 모형 3종 세트 (GLM, Random Forest, SVM)
model_glm <- train(in_sf ~., data = xy_train_df,
method="glm", family="binomial")
model_rf <- train(in_sf ~., data = xy_train_df,
method="rf", ntree = 100, tuneLength = 1)
model_svm <- train(in_sf ~., data = xy_train_df,
method="svmRadial", prob.model = TRUE, tuneLength = 1)
model_xgb <- train(in_sf ~., data = xy_train_df,
method="xgbTree", tuneGrid = tune_grid)
explainer
객체 생성모형 이해와 해석을 위해서 DALEX
팩키지 explain()
함수를 통해 explainer
객체를 생성한다. 다음 그림에 정리된 것처럼 예측함수(predict_function
), 라벨(label
), 경우에 따라서 연결함수(link_function
)을 적시해야 한다.
# 3. DALEX 설정 -----
## 3.1. explainer 사전 설정
prob_fun <- function(object, newdata) {
predict(object, newdata=newdata, type="prob")[,2]
}
y_test_v <- as.numeric(as.character(xy_test_df$in_sf))
## 3.2. explainer 실행
explainer_glm <- DALEX::explain(model_glm, label = "GLM",
data = xy_test_df, y = y_test_v,
predict_function = prob_fun)
explainer_rf <- DALEX::explain(model_rf, label = "RF",
data = xy_test_df, y = y_test_v,
predict_function = prob_fun)
explainer_svm <- DALEX::explain(model_svm, label = "SVM",
data = xy_test_df, y = y_test_v,
predict_function = prob_fun)
explainer_xgb <- DALEX::explain(model_xgb, label = "xgBoost",
data = xy_test_df, y = y_test_v,
predict_function = prob_fun)
GLM, RandomForest, SVM, xgBoost 예측모형의 성능 비교를 위해서 model_performance()
함수를 사용한다. ECDF와 Boxplot을 활용하여 상대적인 모형의 성능을 비교할 수 있다.
# 4. 예측 모형 이해와 설명 -----
## 4.1. 모형 성능
mp_glm <- model_performance(explainer_glm)
mp_rf <- model_performance(explainer_rf)
mp_svm <- model_performance(explainer_svm)
mp_xgb <- model_performance(explainer_xgb)
ecdf_g <- plot(mp_rf, mp_glm, mp_svm, mp_xgb) +
theme(legend.position = "top")
boxplot_g <- plot(mp_rf, mp_glm, mp_svm, mp_xgb, geom = "boxplot", show_outliers = 3) +
theme(legend.position = "none")
plot_grid(ecdf_g, boxplot_g)
각 예측모형에서 중요한 역할을 수행하는 변수를 5개 뽑아 비교한다. n_sample = -1
은 모든 관측점을 사용한다는 의미가 된다.
## 4.2. 중요 변수
vi_glm <- variable_importance(explainer_glm, n_sample = -1, loss_function = loss_root_mean_square, type = "raw")
vi_rf <- variable_importance(explainer_rf, n_sample = -1, loss_function = loss_root_mean_square, type = "raw")
vi_svm <- variable_importance(explainer_svm, n_sample = -1, loss_function = loss_root_mean_square, type = "raw")
vi_xgb <- variable_importance(explainer_xgb, n_sample = -1, loss_function = loss_root_mean_square, type = "raw")
plot(vi_glm, vi_rf, vi_svm, vi_xgb, max_vars = 6)
특정변수(elevation
)가 각 예측모형에서 중요한 변수로 식별되어서 이변수가 부동산 분류에 어떤 관련이 있는 pdp
로 살펴본다.
## 4.3. 변수 반응도
pdp_glm <- variable_response(explainer_glm, variable = "elevation", type = "pdp")
pdp_rf <- variable_response(explainer_rf, variable = "elevation", type = "pdp")
pdp_svm <- variable_response(explainer_svm, variable = "elevation", type = "pdp")
pdp_xgb <- variable_response(explainer_xgb, variable = "elevation", type = "pdp")
plot(pdp_glm, pdp_rf, pdp_svm, pdp_xgb) +
scale_x_log10(labels=scales::comma) +
scale_y_continuous(labels = scales::percent)