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)