Việc xây dựng các mô hình Machine Learning là một quá trình và hầu hết nguồn lực được tập trung vào hai giai đoạn là Feature Engineering và Turning Hyperparameters. Nhưng hai khâu này có thể là một thách thức với những người mà không thành thạo Machine Learning (xem thêm ở đây). Trong những tình huống như thế thì Automated Machine Learning có thể là một giải pháp hiệu quả nhất là trong những tình huống mà nguồn lực thời gian không còn nhiều như deadline đã sắp đến.
trong bài này chúng ta sẽ so sánh hiệu quả của sử dụng Automated Machine Learning để giải quyết một bài toán cụ thể, một vấn đề cụ thể là Credit Scoring / Credit Classification với bộ số liệu hmeq.csv đã được sử dụng trong post trước. Cụ thể hơn với Xgboost mặc định thì AUC trên test data là 0.9507 còn nếu áp dụng Bayesian Optimization để tinh chỉnh các tham số thì chúng ta có thể đạt được một kết quả tốt hơn với AUC cao hơn là 0.95489. Câu hỏi là: nếu vẫn sử dụng AUC làm tiêu chuẩn đánh giá và so sánh thì Automated Machine Learning có tốt hơn Xgboost tinh chỉnh hay không?.
Automated Machine Learning có thể được thực hiện bằng h2o là một open-source tool cho Machine Learning/Big Data được có thể chạy trên cả R lẫn Python với cú phát như nhau và cho nhiều thuật toán cả unsupervised lẫn supervised algorithms và dữ liệu đầu vào cho các thuật toán thì h2o nhận cả biến numeric, categorical lẫn ordinal. Đây là một điểm thuận lợi vì chúng ta không cần phải thực hiện, ví dụ, cái gọi là thủ tục one-hot encoding.
Trước hết đọc dữ liệu và xử lí missing data bằng Random Forest như đã trình bày trong post trước:
#=================================
# Data Pre-processing
#=================================
# Clear workspace:
rm(list = ls())
# Import data:
library(tidyverse)
hmeq <- read_csv("http://www.creditriskanalytics.net/uploads/1/9/5/1/19511601/hmeq.csv")
# Stage 1 - Impute missing data:
library(missRanger)
missRanger(hmeq, seed = 29) -> hmeq_imputed
##
## Missing value imputation by random forests
##
## Variables to impute: MORTDUE, VALUE, REASON, JOB, YOJ, DEROG, DELINQ, CLAGE, NINQ, CLNO, DEBTINC
## Variables used to impute: BAD, LOAN, MORTDUE, VALUE, REASON, JOB, YOJ, DEROG, DELINQ, CLAGE, NINQ, CLNO, DEBTINC
## iter 1: ...........
## iter 2: ...........
## iter 3: ...........
# Stage 2 - Normalize 0-1 features:
hmeq_imputed %>%
mutate(BAD = case_when(BAD == 1 ~ "Bad", TRUE ~ "Good")) %>%
mutate_if(is.character, as.factor) %>%
mutate_if(is.numeric, function(x) {(x - min(x)) / (max(x) - min(x))}) -> df_final
Với dữ liệu sau khi đã xử lí missing chúng ta phân chia thành Training, Validation và Testing data theo tỉ lệ 50% - 20% - 30%:
# Stage - Split data for training, validation and testing:
library(h2o)
h2o.init(nthreads = 40, max_mem_size = "32g")
##
## H2O is not running yet, starting it now...
##
## Note: In case of errors look at the following log files:
## /tmp/RtmpwprFz2/h2o_chidung_started_from_r.out
## /tmp/RtmpwprFz2/h2o_chidung_started_from_r.err
##
##
## Starting H2O JVM and connecting: . Connection successful!
##
## R is connected to the H2O cluster:
## H2O cluster uptime: 1 seconds 846 milliseconds
## H2O cluster timezone: Asia/Ho_Chi_Minh
## H2O data parsing timezone: UTC
## H2O cluster version: 3.28.0.4
## H2O cluster version age: 6 days
## H2O cluster name: H2O_started_from_R_chidung_dkb320
## H2O cluster total nodes: 1
## H2O cluster total memory: 32.00 GB
## H2O cluster total cores: 40
## H2O cluster allowed cores: 40
## H2O cluster healthy: TRUE
## H2O Connection ip: localhost
## H2O Connection port: 54321
## H2O Connection proxy: NA
## H2O Internal Security: FALSE
## H2O API Extensions: Amazon S3, XGBoost, Algos, AutoML, Core V3, TargetEncoder, Core V4
## R Version: R version 3.6.2 (2019-12-12)
h2o.no_progress()
as.h2o(df_final) -> h2o_frame
splits <- h2o.splitFrame(h2o_frame, ratios = c(0.5, 0.2), seed = 29)
train <- splits[[1]]
valid <- splits[[2]]
test <- splits[[3]]
# Define predictors and target:
y <- "BAD"
x <- setdiff(names(train), y)
Với dữ liệu đã chuẩn bị chúng ta có thể thực hiện huấn luyện Automated Machine Learning bằng hàm h2o.automl() (nếu cần có thể tham khảo thêm ở đây) như sau:
#===================================
# Training Auto Machine Learning
#===================================
# Train Auto Machine Learning:
autoML <- h2o.automl(x = x,
y = y,
training_frame = train,
leaderboard_frame = valid,
stopping_metric = "AUC",
stopping_rounds = 10,
stopping_tolerance = 0.01,
max_models = 50,
max_runtime_secs = 60*60,
seed = 1,
sort_metric = "AUC")
##
## 00:01:22.973: Stopping tolerance set by the user is < 70% of the recommended default of 0.01830630064845531, so models may take a long time to converge or may not converge at all.
Trong số 45 mô hình thì StackedEnsemble_AllModels_AutoML_20200229_142838 có AUC trên Validation Data là cao nhất và nó xếp ở đầu bảng như ta có thể thấy:
# Model performance by AUC:
autoML@leaderboard %>%
as.data.frame() %>%
select(model_id, auc) %>%
mutate(Rank = 1:nrow(.), auc = round(auc, 4)) %>%
rename(AUC_Val = auc) -> df_results
df_results %>%
knitr::kable(caption = "Table 1: AUC on Validation Data")
model_id | AUC_Val | Rank |
---|---|---|
StackedEnsemble_AllModels_AutoML_20200301_000122 | 0.9720 | 1 |
StackedEnsemble_BestOfFamily_AutoML_20200301_000122 | 0.9713 | 2 |
GBM_grid__1_AutoML_20200301_000122_model_2 | 0.9712 | 3 |
DeepLearning_grid__2_AutoML_20200301_000122_model_2 | 0.9639 | 4 |
GBM_4_AutoML_20200301_000122 | 0.9636 | 5 |
GBM_grid__1_AutoML_20200301_000122_model_8 | 0.9606 | 6 |
GBM_grid__1_AutoML_20200301_000122_model_9 | 0.9590 | 7 |
DRF_1_AutoML_20200301_000122 | 0.9589 | 8 |
DeepLearning_grid__1_AutoML_20200301_000122_model_1 | 0.9578 | 9 |
GBM_3_AutoML_20200301_000122 | 0.9572 | 10 |
GBM_1_AutoML_20200301_000122 | 0.9570 | 11 |
DeepLearning_grid__3_AutoML_20200301_000122_model_2 | 0.9541 | 12 |
XRT_1_AutoML_20200301_000122 | 0.9539 | 13 |
GBM_2_AutoML_20200301_000122 | 0.9530 | 14 |
XGBoost_grid__1_AutoML_20200301_000122_model_13 | 0.9468 | 15 |
XGBoost_grid__1_AutoML_20200301_000122_model_7 | 0.9451 | 16 |
GBM_grid__1_AutoML_20200301_000122_model_4 | 0.9439 | 17 |
DeepLearning_grid__2_AutoML_20200301_000122_model_1 | 0.9404 | 18 |
XGBoost_grid__1_AutoML_20200301_000122_model_15 | 0.9395 | 19 |
DeepLearning_grid__1_AutoML_20200301_000122_model_2 | 0.9388 | 20 |
XGBoost_grid__1_AutoML_20200301_000122_model_9 | 0.9383 | 21 |
XGBoost_grid__1_AutoML_20200301_000122_model_18 | 0.9381 | 22 |
GBM_5_AutoML_20200301_000122 | 0.9360 | 23 |
GBM_grid__1_AutoML_20200301_000122_model_6 | 0.9359 | 24 |
GBM_grid__1_AutoML_20200301_000122_model_3 | 0.9355 | 25 |
GBM_grid__1_AutoML_20200301_000122_model_7 | 0.9342 | 26 |
XGBoost_grid__1_AutoML_20200301_000122_model_11 | 0.9320 | 27 |
DeepLearning_grid__1_AutoML_20200301_000122_model_3 | 0.9285 | 28 |
XGBoost_grid__1_AutoML_20200301_000122_model_4 | 0.9264 | 29 |
XGBoost_grid__1_AutoML_20200301_000122_model_6 | 0.9247 | 30 |
XGBoost_grid__1_AutoML_20200301_000122_model_12 | 0.9247 | 31 |
DeepLearning_grid__3_AutoML_20200301_000122_model_1 | 0.9234 | 32 |
XGBoost_grid__1_AutoML_20200301_000122_model_8 | 0.9219 | 33 |
XGBoost_1_AutoML_20200301_000122 | 0.9157 | 34 |
XGBoost_3_AutoML_20200301_000122 | 0.9135 | 35 |
XGBoost_grid__1_AutoML_20200301_000122_model_16 | 0.9124 | 36 |
XGBoost_2_AutoML_20200301_000122 | 0.9051 | 37 |
XGBoost_grid__1_AutoML_20200301_000122_model_3 | 0.8966 | 38 |
XGBoost_grid__1_AutoML_20200301_000122_model_17 | 0.8911 | 39 |
XGBoost_grid__1_AutoML_20200301_000122_model_14 | 0.8909 | 40 |
XGBoost_grid__1_AutoML_20200301_000122_model_1 | 0.8907 | 41 |
XGBoost_grid__1_AutoML_20200301_000122_model_2 | 0.8880 | 42 |
DeepLearning_grid__2_AutoML_20200301_000122_model_3 | 0.8816 | 43 |
XGBoost_grid__1_AutoML_20200301_000122_model_5 | 0.8813 | 44 |
DeepLearning_grid__1_AutoML_20200301_000122_model_4 | 0.8809 | 45 |
XGBoost_grid__1_AutoML_20200301_000122_model_10 | 0.8791 | 46 |
GBM_grid__1_AutoML_20200301_000122_model_1 | 0.8772 | 47 |
DeepLearning_1_AutoML_20200301_000122 | 0.8749 | 48 |
GBM_grid__1_AutoML_20200301_000122_model_5 | 0.8651 | 49 |
GBM_grid__1_AutoML_20200301_000122_model_10 | 0.8558 | 50 |
GLM_1_AutoML_20200301_000122 | 0.8484 | 51 |
DeepLearning_grid__3_AutoML_20200301_000122_model_3 | 0.8465 | 52 |
Còn AUC trên Test Data của tất cả các mô hình này:
# AUC on test data by i-th model:
getAUC_onTestData <- function(i) {
# Extract i-th model:
h2o.getModel(autoML@leaderboard[i, 1]) -> best_ith
# Model performance by ith model by AUC on Test data:
h2o.performance(model = best_ith, newdata = test) -> metrics_ith
# Return output:
return(data.frame(AUC_Test = metrics_ith@metrics$AUC, model_id = best_ith@model_id))
}
# Calculate AUC for all models:
lapply(1:nrow(df_results), getAUC_onTestData) -> auc_on_testData
do.call("bind_rows", auc_on_testData) -> auc_on_testData
# AUC by all models on test data:
auc_on_testData %>%
select(model_id, AUC_Test) %>%
knitr::kable(caption = "Table 2: AUC on Test Data")
model_id | AUC_Test |
---|---|
StackedEnsemble_AllModels_AutoML_20200301_000122 | 0.9843819 |
StackedEnsemble_BestOfFamily_AutoML_20200301_000122 | 0.9831996 |
GBM_grid__1_AutoML_20200301_000122_model_2 | 0.9743221 |
DeepLearning_grid__2_AutoML_20200301_000122_model_2 | 0.9585590 |
GBM_4_AutoML_20200301_000122 | 0.9744070 |
GBM_grid__1_AutoML_20200301_000122_model_8 | 0.9683310 |
GBM_grid__1_AutoML_20200301_000122_model_9 | 0.9598262 |
DRF_1_AutoML_20200301_000122 | 0.9703508 |
DeepLearning_grid__1_AutoML_20200301_000122_model_1 | 0.9477725 |
GBM_3_AutoML_20200301_000122 | 0.9681218 |
GBM_1_AutoML_20200301_000122 | 0.9606316 |
DeepLearning_grid__3_AutoML_20200301_000122_model_2 | 0.9500418 |
XRT_1_AutoML_20200301_000122 | 0.9621121 |
GBM_2_AutoML_20200301_000122 | 0.9586605 |
XGBoost_grid__1_AutoML_20200301_000122_model_13 | 0.9522407 |
XGBoost_grid__1_AutoML_20200301_000122_model_7 | 0.9508245 |
GBM_grid__1_AutoML_20200301_000122_model_4 | 0.9550401 |
DeepLearning_grid__2_AutoML_20200301_000122_model_1 | 0.9492209 |
XGBoost_grid__1_AutoML_20200301_000122_model_15 | 0.9461947 |
DeepLearning_grid__1_AutoML_20200301_000122_model_2 | 0.9261560 |
XGBoost_grid__1_AutoML_20200301_000122_model_9 | 0.9480613 |
XGBoost_grid__1_AutoML_20200301_000122_model_18 | 0.9381486 |
GBM_5_AutoML_20200301_000122 | 0.9505036 |
GBM_grid__1_AutoML_20200301_000122_model_6 | 0.9431935 |
GBM_grid__1_AutoML_20200301_000122_model_3 | 0.9393982 |
GBM_grid__1_AutoML_20200301_000122_model_7 | 0.9440331 |
XGBoost_grid__1_AutoML_20200301_000122_model_11 | 0.9400173 |
DeepLearning_grid__1_AutoML_20200301_000122_model_3 | 0.9331990 |
XGBoost_grid__1_AutoML_20200301_000122_model_4 | 0.9318624 |
XGBoost_grid__1_AutoML_20200301_000122_model_6 | 0.9291490 |
XGBoost_grid__1_AutoML_20200301_000122_model_12 | 0.9317692 |
DeepLearning_grid__3_AutoML_20200301_000122_model_1 | 0.9206711 |
XGBoost_grid__1_AutoML_20200301_000122_model_8 | 0.9283684 |
XGBoost_1_AutoML_20200301_000122 | 0.9223824 |
XGBoost_3_AutoML_20200301_000122 | 0.9100295 |
XGBoost_grid__1_AutoML_20200301_000122_model_16 | 0.9133942 |
XGBoost_2_AutoML_20200301_000122 | 0.9089114 |
XGBoost_grid__1_AutoML_20200301_000122_model_3 | 0.8961714 |
XGBoost_grid__1_AutoML_20200301_000122_model_17 | 0.8964457 |
XGBoost_grid__1_AutoML_20200301_000122_model_14 | 0.8946526 |
XGBoost_grid__1_AutoML_20200301_000122_model_1 | 0.8934155 |
XGBoost_grid__1_AutoML_20200301_000122_model_2 | 0.8902082 |
DeepLearning_grid__2_AutoML_20200301_000122_model_3 | 0.8762030 |
XGBoost_grid__1_AutoML_20200301_000122_model_5 | 0.8845752 |
DeepLearning_grid__1_AutoML_20200301_000122_model_4 | 0.8625094 |
XGBoost_grid__1_AutoML_20200301_000122_model_10 | 0.8779112 |
GBM_grid__1_AutoML_20200301_000122_model_1 | 0.8753623 |
DeepLearning_1_AutoML_20200301_000122 | 0.8727773 |
GBM_grid__1_AutoML_20200301_000122_model_5 | 0.8642746 |
GBM_grid__1_AutoML_20200301_000122_model_10 | 0.8590785 |
GLM_1_AutoML_20200301_000122 | 0.8286777 |
DeepLearning_grid__3_AutoML_20200301_000122_model_3 | 0.8412118 |
Chúng ta kì vọng rằng AUC trên Validation Data cao thì sẽ dẫn đến AUC trên Test Data cũng cao. Tuy nhiên thực tế thì vẫn có ngoại lệ, mô hình có AUC cao thứ hai trên Validation Data nhưng AUC trên Test Data lại thua kém mô hình xếp thứ 2 (so sánh Table 1 và Table 2) nhưng xu hướng chung thì AUC trên Validation và Test data là tương quan dương rất cao và tương quan này có ý nghĩa thống kê:
# Correlation between Validatation and test AUC:
cor.test(df_results$AUC_Val, auc_on_testData$AUC_Test)
##
## Pearson's product-moment correlation
##
## data: df_results$AUC_Val and auc_on_testData$AUC_Test
## t = 42.297, df = 50, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.9761603 0.9921584
## sample estimates:
## cor
## 0.9863124
Chốt lại chúng ta sẽ sử dụng StackedEnsemble_AllModels_AutoML_20200229_142838 - là mô hình tốt nhất và sử dụng mô hình này chúng ta có AUC là 0.9843819 trên Test Data. Sử dụng mô hình này để tính PD (Probability of Default) như sau:
# Use best model for predicting PD:
pd_best <- h2o.predict(autoML@leader, test) %>%
as.data.frame() %>%
pull(Bad)
Để so sánh chúng ta huấn luyện Xgboost rồi đánh giá chất lượng phân loại của mô hình này trên Test Data. Kết quả cho thấy AUC trên Test Data là thấp hơn (Table 3):
#=========================
# Compare with Xgboost
#=========================
# Convert to data frame:
bind_rows(as.data.frame(train), as.data.frame(valid)) -> df_train
as.data.frame(test) -> df_test
# Function conducts one-hot encoding:
library(caret)
one_hotEncoding <- function(df) {
dummies <- dummyVars("~.", data = df)
predict(dummies, df) %>% as.data.frame() -> df_oneHot
df_oneHot %>%
select(-BAD.Good) %>%
rename(BAD = BAD.Bad) %>%
return()
}
# Use function:
df_train %>% one_hotEncoding() -> df_train
df_test %>% one_hotEncoding() -> df_test
# Convert features to DMatrix form:
X_train <- df_train %>%
select(-BAD) %>%
as.matrix()
Y_train <- df_train %>%
pull(BAD)
X_test <- df_test %>%
select(-BAD) %>%
as.matrix()
Y_test <- df_test %>%
pull(BAD)
#------------------------------------------
# Train XGBoost with default parameters
#------------------------------------------
library(xgboost)
# Convert to DMatrix form for train data:
dtrain <- xgb.DMatrix(data = X_train, label = Y_train)
# Train a default XGBoost:
set.seed(29)
xgb1 <- xgboost(data = dtrain,
objective = "binary:logistic",
eval_metric = "auc",
verbose = 0,
nround = 30)
# Use Xgboost for predicting PD:
pd_xgb <- predict(xgb1, X_test)
# AUC on test data by Xgboost:
library(pROC)
auc_xgb <- roc(Y_test, pd_xgb)$auc %>% as.numeric()
# AUC on test data by 1-th model:
auc_best <- auc_on_testData$AUC_Test[1]
# Compare AUC by the two approaches:
data.frame(Model = c("BestAutoML", "Xgboost"), AUC = c(auc_best, auc_xgb)) %>%
knitr::kable(caption = "Table 3: AUC on Test Data")
Model | AUC |
---|---|
BestAutoML | 0.9843819 |
Xgboost | 0.9526290 |
Đến đây chúng ta có bằng chứng để tin rằng BestAutoML nên được sử dụng. Tuy nhiên để đánh giá chi tiết hơn nữa chúng ta có thể khảo sát và so sánh khả năng phân loại của hai mô hình này tương ứng với một loạt các ngưỡng phân loại (cutoff đã trình bày trong post trước). Trước hết chúng ta viết hai hàm tính ra các chỉ tiêu đánh giá mô hình phân loại tương ứng với một ngưỡng lựa chọn cho cả hai mô hình:
# Calculate model performance by cutoff selected for Xgboost:
byCutoff_xgb <- function(cutoff) {
pred <- case_when(pd_xgb >= cutoff ~ "Bad", TRUE ~ "Good") %>% as.factor()
thuc_te <- case_when(Y_test == 1 ~ "Bad", Y_test == 0 ~ "Good") %>% as.factor()
confusionMatrix(pred, thuc_te, positive = "Bad") -> cm
cm$table %>% as.vector() -> bg
cm$overall %>% as.vector() -> acc
cm$byClass %>% as.vector() -> sen
data.frame(BB = bg[1], BG = bg[2], GB = bg[3], GG = bg[4], Accuracy = acc[1],
Kappa = acc[2], Recall = sen[1], Specificity = sen[2], Cutoff = cutoff) -> model_perCutoff
return(model_perCutoff)
}
# Calculate model performance by cutoff selected for best Auto ML:
byCutoff_best <- function(cutoff) {
pred <- case_when(pd_best >= cutoff ~ "Bad", TRUE ~ "Good") %>% as.factor()
thuc_te <- case_when(Y_test == 1 ~ "Bad", Y_test == 0 ~ "Good") %>% as.factor()
confusionMatrix(pred, thuc_te, positive = "Bad") -> cm
cm$table %>% as.vector() -> bg
cm$overall %>% as.vector() -> acc
cm$byClass %>% as.vector() -> sen
data.frame(BB = bg[1], BG = bg[2], GB = bg[3], GG = bg[4], Accuracy = acc[1],
Kappa = acc[2], Recall = sen[1], Specificity = sen[2], Cutoff = cutoff) -> model_perCutoff
return(model_perCutoff)
}
Rồi sử dụng hai hàm này để tính Model Performance trên một loạt giá trị của Cutoff cho cả hai mô hình:
# A range of cutoffs:
cutoffs <- seq(0.05, 0.95, 0.05)
# Model performance by cutoff for the two models:
lapply(cutoffs, byCutoff_xgb) -> performance_cutoff_xgb
lapply(cutoffs, byCutoff_best) -> performance_cutoff_best
# Convert to DF and combine results:
do.call("bind_rows", performance_cutoff_xgb) -> performance_cutoff_xgb
do.call("bind_rows", performance_cutoff_best) -> performance_cutoff_best
bind_rows(performance_cutoff_best %>% mutate(Model = "BestAutoML"),
performance_cutoff_xgb %>% mutate(Model = "Xgboost")) -> df_comparision
# Compare model performance by plot:
my_colors <- c("#e41a1c", "#377eb8")
theme_set(theme_gray())
df_comparision %>%
select(5:10) %>%
gather(Metric, Value, -Cutoff, -Model) %>%
ggplot(aes(Cutoff, Value, color = Model)) +
geom_line() +
geom_point() +
scale_color_manual(values = my_colors) +
facet_wrap(~ Metric, scales = "free") +
theme(legend.position = "top") +
scale_y_continuous(labels = scales::percent) +
labs(x = NULL, y = NULL,
title = "Figure 1: Model Performance between AutoML and Xgboost by Cutoff",
subtitle = "Data Source: http://www.creditriskanalytics.net") -> f1
library(plotly)
ggplotly(f1)
Qua Figure 1 chúng ta thấy rằng ở cả 4 tiêu chí thì BestAutoML cao hơn Xgboost. Ngoài ra có hai kết quả đáng chú ý là:
Ở các ngưỡng thấp hơn 0.2 thì Recall - tức là khả năng mô hình dự báo chính xác các trường hợp xấu (Bad, hay kí hiệu là B với hàm ý rằng khách hàng sẽ default) thì hai mô hình không có sự khác biệt đáng kể nhưng từ sau ngưỡng này thì sự chênh lệch là đáng kể và càng nới rộng. Điều này là bằng chứng chắc chắn rằng BestAutoML nếu được sử dụng cho mục đích phân loại thì sẽ là mô hình mang lại lợi nhuận cao hơn.
Accuracy là có hình chữ U ngược hàm ý rằng với cả hai mô hình thì sẽ tồn tại một ngưỡng phân loại mà tối đa hóa chỉ tiêu này. Điều này là nhất quán với nguyên lí sự đánh đổi của các chỉ tiêu. Cụ thể hơn chúng ta có thể thấy rằng Recall và Specificity có xu hướng biến đổi ngược nhau khi thay đổi ngưỡng phân loại.
Chúng ta có thể diễn đạt bằng một cách truyền tải khác dễ hiểu hơn với những người không chuyên về dữ liệu và thống kê (thường họ là bậc quản lí - boss và thường họ thường có tiếng nói quyết định trong việc sử dụng / lựa chọn) bằng công cụ hình ảnh sau (Figure 2):
df_comparision %>%
select(-c(5:8)) %>%
gather(Metric, Value, -Cutoff, -Model) %>%
ggplot(aes(Cutoff, Value, color = Model)) +
geom_line() +
geom_point() +
scale_color_manual(values = my_colors) +
facet_wrap(~ Metric, scales = "free") +
theme(legend.position = "top") +
labs(x = NULL, y = NULL,
title = "Figure 2: Model Performance between AutoML and Xgboost by Cutoff",
subtitle = "Data Source: http://www.creditriskanalytics.net") -> f2
ggplotly(f2)
Ở đây, ví dụ, BB hàm ý là các khách hàng xấu (Bad) được phân loại đúng thành khách hàng xấu (Bad). Các kí hiệu khác như BG, GB, và GG được diễn giải tương tự. Rõ ràng từ Figure 2 chúng ta thấy BestAutoML phân loại và dự báo nhóm khách hàng xấu chính xác hơn ở mọi ngưỡng so với Xgboost.
Ở trên chúng sử dụng thư viện xgboost để thực hiện huận luyện Xgboost. Có thể thấy hàm xgboost() đòi hỏi rằng dữ liệu bắt buộc phải ở dạng numeric. Đó là lí do mà chúng ta cần phải thực hiện thêm thủ tục one-hot encoding. Chúng ta có thể sử dụng hàm h2o.xgboost() để thực hiện thuật toán này mà không cần phải cần đến one-hot encoding. Hướng dẫn chi tiết về việc thực hiện thuật toán này có thể tham khảo ở đây cho R và ở đây cho Python.
## R version 3.6.2 (2019-12-12)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.4 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=vi_VN LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=vi_VN LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=vi_VN LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=vi_VN LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] plotly_4.9.1 pROC_1.14.0 xgboost_0.90.0.2 caret_6.0-84
## [5] lattice_0.20-40 h2o_3.28.0.4 missRanger_2.1.0 forcats_0.4.0
## [9] stringr_1.4.0 dplyr_0.8.0.1 purrr_0.3.3 readr_1.3.1
## [13] tidyr_0.8.3 tibble_2.1.3 ggplot2_3.2.1 tidyverse_1.2.1
##
## loaded via a namespace (and not attached):
## [1] nlme_3.1-144 bitops_1.0-6 lubridate_1.7.4
## [4] httr_1.4.0 tools_3.6.2 backports_1.1.5
## [7] R6_2.4.1 rpart_4.1-15 lazyeval_0.2.2
## [10] colorspace_1.4-1 nnet_7.3-12 withr_2.1.2
## [13] tidyselect_0.2.5 curl_3.3 compiler_3.6.2
## [16] cli_2.0.0 rvest_0.3.3 xml2_1.2.0
## [19] labeling_0.3 scales_1.1.0 digest_0.6.23
## [22] rmarkdown_1.12 base64enc_0.1-3 pkgconfig_2.0.3
## [25] htmltools_0.3.6 highr_0.8 htmlwidgets_1.3
## [28] rlang_0.4.2 readxl_1.3.1 rstudioapi_0.10
## [31] FNN_1.1.3 shiny_1.3.2 generics_0.0.2
## [34] jsonlite_1.6 crosstalk_1.0.0 ModelMetrics_1.2.2
## [37] RCurl_1.95-4.12 magrittr_1.5 Matrix_1.2-18
## [40] Rcpp_1.0.3 munsell_0.5.0 fansi_0.4.0
## [43] lifecycle_0.1.0 stringi_1.4.3 yaml_2.2.0
## [46] MASS_7.3-51.5 plyr_1.8.5 recipes_0.1.5
## [49] grid_3.6.2 promises_1.0.1 crayon_1.3.4
## [52] haven_2.1.0 splines_3.6.2 hms_0.4.2
## [55] knitr_1.22 pillar_1.4.3 ranger_0.11.2
## [58] reshape2_1.4.3 codetools_0.2-16 stats4_3.6.2
## [61] glue_1.3.1 evaluate_0.13 data.table_1.12.2
## [64] modelr_0.1.4 httpuv_1.5.1 foreach_1.4.4
## [67] cellranger_1.1.0 gtable_0.3.0 assertthat_0.2.1
## [70] xfun_0.6 gower_0.2.0 mime_0.6
## [73] prodlim_2018.04.18 xtable_1.8-4 broom_0.5.2
## [76] e1071_1.7-1 later_0.8.0 class_7.3-15
## [79] survival_3.1-8 viridisLite_0.3.0 timeDate_3043.102
## [82] iterators_1.0.10 lava_1.6.5 ipred_0.9-9