A Big Project for Data Science in Banking Course (Part 1)
Nguyen Chi Dung
#=======================================================
# A Big Project for Data Science in Banking Course
#=======================================================
#---------------------------------------------------------------------------------------
# Giải thích 1: Một mô hình có mức độ chính xác toàn cục khi phân loại
# hồ sơ xin vay tín dụng thường không phải là mô hình mà Ngân Hàng lựa chọn
# Data Source: https://archive.ics.uci.edu/ml/datasets/default+of+credit+card+clients
#---------------------------------------------------------------------------------------
# Đọc và xem qua dữ liệu:
rm(list = ls())
library(tidyverse)
library(magrittr)
taiwan_default <- read.csv("D:/Teaching/new_data/taiwan_credit1.csv")
taiwan_default %>% dim()
## [1] 30000 25
taiwan_default %>% str()
## 'data.frame': 30000 obs. of 25 variables:
## $ id : int 1 2 3 4 5 6 7 8 9 10 ...
## $ X1 : int 20000 120000 90000 50000 50000 50000 500000 100000 140000 20000 ...
## $ X2 : int 2 2 2 2 1 1 1 2 2 1 ...
## $ X3 : int 2 2 2 2 2 1 1 2 3 3 ...
## $ X4 : int 1 2 2 1 1 2 2 2 1 2 ...
## $ X5 : int 24 26 34 37 57 37 29 23 28 35 ...
## $ X6 : int 2 -1 0 0 -1 0 0 0 0 -2 ...
## $ X7 : int 2 2 0 0 0 0 0 -1 0 -2 ...
## $ X8 : int -1 0 0 0 -1 0 0 -1 2 -2 ...
## $ X9 : int -1 0 0 0 0 0 0 0 0 -2 ...
## $ X10: int -2 0 0 0 0 0 0 0 0 -1 ...
## $ X11: int -2 2 0 0 0 0 0 -1 0 -1 ...
## $ X12: int 3913 2682 29239 46990 8617 64400 367965 11876 11285 0 ...
## $ X13: int 3102 1725 14027 48233 5670 57069 412023 380 14096 0 ...
## $ X14: int 689 2682 13559 49291 35835 57608 445007 601 12108 0 ...
## $ X15: int 0 3272 14331 28314 20940 19394 542653 221 12211 0 ...
## $ X16: int 0 3455 14948 28959 19146 19619 483003 -159 11793 13007 ...
## $ X17: int 0 3261 15549 29547 19131 20024 473944 567 3719 13912 ...
## $ X18: int 0 0 1518 2000 2000 2500 55000 380 3329 0 ...
## $ X19: int 689 1000 1500 2019 36681 1815 40000 601 0 0 ...
## $ X20: int 0 1000 1000 1200 10000 657 38000 0 432 0 ...
## $ X21: int 0 1000 1000 1100 9000 1000 20239 581 1000 13007 ...
## $ X22: int 0 0 1000 1069 689 1000 13750 1687 1000 1122 ...
## $ X23: int 0 2000 5000 1000 679 800 13770 1542 1000 0 ...
## $ Y : int 1 1 0 0 0 0 0 0 0 0 ...
# Viết hàm dán lại nhãn:
recode_default <- function(x) {
case_when(x == 1 ~ "Default",
x == 0 ~ "NonDefault")
}
# Chỉ lấy một số biến được cho là quan trọng để phân tích và dán lại nhãn:
dung <- taiwan_default %>%
select(X1, X6, X18:X23, -id, Y) %>%
mutate(Y = recode_default(Y),
Y = as.factor(Y))
dung %>% head()
## X1 X6 X18 X19 X20 X21 X22 X23 Y
## 1 20000 2 0 689 0 0 0 0 Default
## 2 120000 -1 0 1000 1000 1000 0 2000 Default
## 3 90000 0 1518 1500 1000 1000 1000 5000 NonDefault
## 4 50000 0 2000 2019 1200 1100 1069 1000 NonDefault
## 5 50000 -1 2000 36681 10000 9000 689 679 NonDefault
## 6 50000 0 2500 1815 657 1000 1000 800 NonDefault
# Chỉ lấy 2000 quan sát bất kì trong bộ số liệu đầu:
set.seed(1709)
dung_small <- dung %>%
sample_n(2000)
# Chia bộ dữ liệu thành hai phần bằng nhau (1000 cho mỗi phần):
library(caret)
set.seed(123)
indxTrain <- createDataPartition(y = dung_small$Y, p = 1 / 2, list = FALSE)
training <- dung_small[indxTrain, ]
testing <- dung_small[-indxTrain, ]
# Mô hình Logistic:
logistic <- train(Y ~.,
data = training,
method = "glm",
family = "binomial")
# Đánh giá mô hình trên test data:
pred1 <- predict(logistic, newdata = testing %>% select(-Y))
pred1 %>% head()
## [1] NonDefault NonDefault NonDefault NonDefault NonDefault NonDefault
## Levels: Default NonDefault
confusionMatrix(data = pred1, testing$Y, positive = "Default")
## Confusion Matrix and Statistics
##
## Reference
## Prediction Default NonDefault
## Default 66 36
## NonDefault 184 714
##
## Accuracy : 0.78
## 95% CI : (0.753, 0.8053)
## No Information Rate : 0.75
## P-Value [Acc > NIR] : 0.0147
##
## Kappa : 0.2691
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.2640
## Specificity : 0.9520
## Pos Pred Value : 0.6471
## Neg Pred Value : 0.7951
## Prevalence : 0.2500
## Detection Rate : 0.0660
## Detection Prevalence : 0.1020
## Balanced Accuracy : 0.6080
##
## 'Positive' Class : Default
##
# Mô hình Probit:
probit <- train(Y ~.,
data = training,
method = "glm",
family = "binomial"(link = "probit"))
# Đánh giá mô hình trên bộ dữ testing:
pred2 <- predict(probit, newdata = testing %>% select(-Y))
confusionMatrix(data = pred2, testing$Y, positive = "Default")
## Confusion Matrix and Statistics
##
## Reference
## Prediction Default NonDefault
## Default 52 32
## NonDefault 198 718
##
## Accuracy : 0.77
## 95% CI : (0.7426, 0.7958)
## No Information Rate : 0.75
## P-Value [Acc > NIR] : 0.07626
##
## Kappa : 0.2123
## Mcnemar's Test P-Value : < 2e-16
##
## Sensitivity : 0.2080
## Specificity : 0.9573
## Pos Pred Value : 0.6190
## Neg Pred Value : 0.7838
## Prevalence : 0.2500
## Detection Rate : 0.0520
## Detection Prevalence : 0.0840
## Balanced Accuracy : 0.5827
##
## 'Positive' Class : Default
##
#---------------------------------------------------------------------------------------
# Giải thích 2: Nếu chọn một tiêu chí nào đó, chẳng hạn, mức chính xác toàn cục để
# lựa chọn mô hình phân loại thì tiêu chí đó phải được đánh giá trên nhiều lần chọn
# mẫu khác nhau chứ không phải chỉ dựa trên một mẫu hay một tình huống cụ thể nào đó.
#---------------------------------------------------------------------------------------
set.seed(29)
indxTrain <- createDataPartition(y = dung_small$Y, p = 1 / 2, list = FALSE)
training <- dung_small[indxTrain, ]
testing <- dung_small[-indxTrain, ]
# Mô hình Logistic:
logistic <- train(Y ~.,
data = training,
method = "glm",
family = "binomial")
# Đánh giá mô hình trên test data:
pred1 <- predict(logistic, newdata = testing %>% select(-Y))
confusionMatrix(data = pred1, testing$Y, positive = "Default")
## Confusion Matrix and Statistics
##
## Reference
## Prediction Default NonDefault
## Default 75 41
## NonDefault 175 709
##
## Accuracy : 0.784
## 95% CI : (0.7572, 0.8091)
## No Information Rate : 0.75
## P-Value [Acc > NIR] : 0.006582
##
## Kappa : 0.2987
## Mcnemar's Test P-Value : < 2.2e-16
##
## Sensitivity : 0.3000
## Specificity : 0.9453
## Pos Pred Value : 0.6466
## Neg Pred Value : 0.8020
## Prevalence : 0.2500
## Detection Rate : 0.0750
## Detection Prevalence : 0.1160
## Balanced Accuracy : 0.6227
##
## 'Positive' Class : Default
##
# Mô hình Probit:
probit <- train(Y ~.,
data = training,
method = "glm",
family = "binomial"(link = "probit"))
# Đánh giá mô hình trên bộ dữ testing:
pred2 <- predict(probit, newdata = testing %>% select(-Y))
confusionMatrix(data = pred2, testing$Y, positive = "Default")
## Confusion Matrix and Statistics
##
## Reference
## Prediction Default NonDefault
## Default 68 40
## NonDefault 182 710
##
## Accuracy : 0.778
## 95% CI : (0.7509, 0.8034)
## No Information Rate : 0.75
## P-Value [Acc > NIR] : 0.02128
##
## Kappa : 0.2697
## Mcnemar's Test P-Value : < 2e-16
##
## Sensitivity : 0.2720
## Specificity : 0.9467
## Pos Pred Value : 0.6296
## Neg Pred Value : 0.7960
## Prevalence : 0.2500
## Detection Rate : 0.0680
## Detection Prevalence : 0.1080
## Balanced Accuracy : 0.6093
##
## 'Positive' Class : Default
##
# Đánh giá hai mô hình trên 100 mẫu khác nhau:
acc_logistic <- c()
acc_probit <- c()
for (i in 1:100) {
set.seed(i)
testing <- dung %>% sample_n(1000)
pred1 <- predict(logistic, newdata = testing %>% select(-Y))
acc1 <- mean(pred1 == testing$Y)
acc_logistic <- c(acc_logistic, acc1)
pred2 <- predict(probit, newdata = testing %>% select(-Y))
acc2 <- mean(pred2 == testing$Y)
acc_probit <- c(acc_probit, acc2)
}
acc_logistic %>% mean()
## [1] 0.81566
acc_probit %>% mean()
## [1] 0.81355
all_df <- data.frame(Accuracy = c(acc_logistic, acc_probit),
Model = c(rep("Logistic", 100), rep("Probit", 100)))
theme_set(theme_minimal())
all_df %>%
ggplot(aes(Model, Accuracy)) +
geom_boxplot()

# Viết hàm so sánh hai mô hình dựa trên tiêu chí Accuracy:
evaluating_fun <- function(so_lan, kich_thuoc_mau, model1, model2) {
acc_m1 <- c()
acc_m2 <- c()
for (i in 1:so_lan) {
set.seed(i)
testing <- dung %>% sample_n(kich_thuoc_mau)
pred1 <- predict(model1, newdata = testing %>% select(-Y))
acc1 <- mean(pred1 == testing$Y)
acc_m1 <- c(acc_m1, acc1)
pred2 <- predict(model2, newdata = testing %>% select(-Y))
acc2 <- mean(pred2 == testing$Y)
acc_m2 <- c(acc_m2, acc2)
}
my_df <- data.frame(Accuracy = c(acc_m1, acc_m2),
Model = c(rep("Model1", so_lan), rep("Model2", so_lan)))
return(my_df)
}
# Sử dụng hàm:
so_sanh <- evaluating_fun(so_lan = 100, kich_thuoc_mau = 1000, logistic, probit)
# Đánh giá sơ bộ bằng công cụ hình ảnh:
so_sanh %>%
ggplot(aes(Model, Accuracy)) +
geom_boxplot()

# Đánh giá sơ bộ bằng các tiêu chí thống kê:
so_sanh %>%
group_by(Model) %>%
summarise_each(funs(mean, median, min, max, sd), Accuracy)
## # A tibble: 2 x 6
## Model Accuracy_mean Accuracy_median Accuracy_min Accuracy_max
## <fct> <dbl> <dbl> <dbl> <dbl>
## 1 Model1 0.816 0.817 0.775 0.851
## 2 Model2 0.814 0.815 0.776 0.848
## # ... with 1 more variable: Accuracy_sd <dbl>
#------------------------------------------------------------------------------------
# Giải thích 3: Lợi nhuận nên là tiêu chí đầu tiên được lựa chọn mô hình phân loại
# và phải dựa vào nhiều mẫu số liệu (nhiều tình huống khác nhau)
# Tham khảo: http://rpubs.com/chidungkt/320301
#------------------------------------------------------------------------------------
# Viết hàm đánh giá lợi nhuận:
df_evaluate_profit <- function(model, so_lan_chon_mau, kich_thuoc) {
ket_qua <- data.frame()
for (j in 1:so_lan_chon_mau) {
set.seed(j)
testing <- dung %>% sample_n(kich_thuoc)
du_bao <- predict(model, testing %>% select(-Y))
u <- confusionMatrix(du_bao, testing$Y, positive = "Default")
v <- u$table %>% as.vector()
ket_qua <- rbind(ket_qua, v)
names(ket_qua) <- c("BB", "GB", "BG", "GG")
}
return(ket_qua)
}
# Sử dụng hàm:
m <- df_evaluate_profit(logistic, so_lan_chon_mau = 1000, kich_thuoc = 3000)
# Tính toán lợi nhuận:
m %<>% mutate(Profit = 0.2*GG - BG)
# Đánh giá các thống kê về lợi nhuận:
m$Profit %>% summary()
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 332.2 361.6 368.4 368.5 375.9 398.2
# Hình ảnh hóa lợi nhuận này:
m %>%
ggplot(aes(Profit)) +
geom_density(fill = "blue", color = "blue", alpha = 0.3) +
geom_histogram(aes(y = ..density..), fill = "red", color = "red", alpha = 0.3)

n <- df_evaluate_profit(probit, so_lan_chon_mau = 1000, kich_thuoc = 3000) %>%
mutate(Profit = 0.2*GG - BG)
df_compare <- bind_rows(m %>% mutate(Model = "Logistic"),
n %>% mutate(Model = "Probit"))
df_compare %<>% mutate(Accuracy = (BB + GG) / (BB + GG + BG + GB))
df_compare %>%
ggplot(aes(Profit)) +
geom_density(fill = "blue", color = "blue", alpha = 0.3) +
geom_histogram(aes(y = ..density..), fill = "red", color = "red", alpha = 0.3) +
facet_wrap(~ Model)

df_compare %>%
group_by(Model) %>%
summarise_each(funs(mean, median, min, max, sd), Profit)
## # A tibble: 2 x 6
## Model Profit_mean Profit_median Profit_min Profit_max Profit_sd
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Logistic 369. 368. 332. 398. 11.1
## 2 Probit 376. 376. 341. 408. 10.7
df_compare %>%
group_by(Model) %>%
summarise_each(funs(mean, median, min, max, sd), Accuracy)
## # A tibble: 2 x 6
## Model Accuracy_mean Accuracy_median Accuracy_min Accuracy_max
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Logistic 0.815 0.815 0.792 0.835
## 2 Probit 0.813 0.813 0.790 0.833
## # ... with 1 more variable: Accuracy_sd <dbl>
# Viết hàm báo cáo các thống kê về lợi nhuận và hình ảnh hóa
# cho một mô hình được lựa chọn:
profit_report <- function(ketqua, rate) {
ketqua %<>% mutate(Profit = rate*GG - BG)
mean_pro <- mean(ketqua$Profit) %>% round(digits = 0)
min_pro <- min(ketqua$Profit) %>% round(digits = 0)
max_pro <- max(ketqua$Profit) %>% round(digits = 0)
sd_pro <- sd(ketqua$Profit) %>% round(digits = 0)
n_samples <- nrow(ketqua)
t1 <- paste("Profit Report: ", paste("Mean = ", mean_pro))
t2 <- paste0(t1, paste(", Min = ", min_pro))
t3 <- paste0(t2, paste(", Max = ", max_pro))
t4 <- paste0(t3, paste0(", SD = ", sd_pro))
s1 <- paste("Notes: ", paste("Number of Samples = ", n_samples))
s1 <- paste0(s1, ", ")
s2 <- paste(s1, paste("Interest Rate = ", rate))
ketqua %>%
ggplot(aes(Profit)) +
geom_vline(xintercept = mean_pro, color = "blue", size = 1.1) +
geom_density(fill = "blue", color = "blue", alpha = 0.2) +
geom_histogram(aes(y = ..density..), fill = "red", color = "red", alpha = 0.2) +
labs(title = t4,
subtitle = s2)
}
# Sử dụng hàm:
profit_report(ketqua = m, rate = 0.2)

profit_report(ketqua = m, rate = 0.1)

# Assignment: Viết hàm hiển thị các thống kê về lợi nhuận + hình ảnh
# cho hai mô hình bất kì được lựa chọn.
# Viết hàm trả lời có hay không một hồ sơ được vay dựa trên thông tin cung cấp:
duyet_vay <- function(X1, X6, X18, X19, X20, X21, X22, X23, model_selected) {
input_df <- data.frame(X1 = X1,
X6 = X6,
X18 = X18,
X19 = X19,
X20 = X20,
X21 = X21,
X22 = X22,
X23 = X23)
ket_qua <- predict(model_selected, input_df)
return(as.character(ket_qua))
}
# Sử dụng hàm:
duyet_vay(X1 = 200000,
X6 = 0,
X18 = 4000,
X19 = 3500,
X20 = 0,
X21 = 500,
X22 = 1000,
X23 = 100,
model_selected = logistic)
## [1] "NonDefault"
duyet_vay(X1 = 200000,
X6 = 0,
X18 = 4000,
X19 = 3500,
X20 = 0,
X21 = 500,
X22 = 1000,
X23 = 100,
model_selected = probit)
## [1] "NonDefault"
#------------------------------------------------------------------------------------
# Giải thích 4: Mức độ chính xác của mô hình phân loại còn phụ thuộc vào ngưỡng
# (Threshold) để phân loại nhóm (hay nhãn) của biến đích và do đó có thể ảnh hưởng
# đến các tiêu chí khác như lợi nhuận.
#------------------------------------------------------------------------------------
# Viết hàm re-convert nhãn:
reconvert <- function(x) {
case_when(x == "Default" ~ 1,
x == "NonDefault" ~ 0)
}
# Áp dụng hàm:
dung10 <- dung %>% mutate(Y = reconvert(Y))
set.seed(1709)
dung_small <- dung10 %>%
sample_n(2000)
# Chia bộ dữ liệu thành hai phần bằng nhau (1000 cho mỗi phần):
set.seed(123)
indxTrain <- createDataPartition(y = dung_small$Y, p = 1 / 2, list = FALSE)
training <- dung_small[indxTrain, ]
testing <- dung_small[-indxTrain, ]
# Mô hình Logistic:
logistic <- train(Y ~.,
data = training,
method = "glm",
family = "binomial")
# Đánh giá mô hình trên test data:
pred1 <- predict(logistic, newdata = testing %>% select(-Y))
pred1 %>% head()
## 8267 27 17126 18156 5700 273
## 0.1200793 0.3761079 0.2411857 0.3834187 0.2220664 0.3915485
# Viết hàm phân loại hồ sơ theo ngưỡng mà chúng ta lựa chọn:
xep_loai <- function(x, nguong) {
case_when(x >= nguong ~ "Default",
x < nguong ~ "NonDefault")
}
# Đánh giá mô hình khi ngưỡng là 0.5:
confusionMatrix(data = pred1 %>% xep_loai(nguong = 0.5),
testing$Y %>% recode_default(), positive = "Default")
## Confusion Matrix and Statistics
##
## Reference
## Prediction Default NonDefault
## Default 74 35
## NonDefault 176 715
##
## Accuracy : 0.789
## 95% CI : (0.7624, 0.8139)
## No Information Rate : 0.75
## P-Value [Acc > NIR] : 0.002135
##
## Kappa : 0.3071
## Mcnemar's Test P-Value : < 2.2e-16
##
## Sensitivity : 0.2960
## Specificity : 0.9533
## Pos Pred Value : 0.6789
## Neg Pred Value : 0.8025
## Prevalence : 0.2500
## Detection Rate : 0.0740
## Detection Prevalence : 0.1090
## Balanced Accuracy : 0.6247
##
## 'Positive' Class : Default
##
# Đánh giá mô hình khi ngưỡng là 0.6:
confusionMatrix(data = pred1 %>% xep_loai(nguong = 0.6),
testing$Y %>% recode_default(), positive = "Default")
## Confusion Matrix and Statistics
##
## Reference
## Prediction Default NonDefault
## Default 12 7
## NonDefault 238 743
##
## Accuracy : 0.755
## 95% CI : (0.7271, 0.7814)
## No Information Rate : 0.75
## P-Value [Acc > NIR] : 0.3733
##
## Kappa : 0.0559
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.0480
## Specificity : 0.9907
## Pos Pred Value : 0.6316
## Neg Pred Value : 0.7574
## Prevalence : 0.2500
## Detection Rate : 0.0120
## Detection Prevalence : 0.0190
## Balanced Accuracy : 0.5193
##
## 'Positive' Class : Default
##
# Viết hàm:
my_fun <- function(nguong, so_lan_lap, n_sample, model) {
ket_qua <- data.frame()
for (i in 1:so_lan_lap) {
set.seed(i)
testing <- dung10 %>%
sample_n(n_sample)
dubao <- predict(model, testing %>% select(-Y))
dubao <- xep_loai(dubao, nguong)
u <- confusionMatrix(dubao, testing$Y %>% recode_default(), positive = "Default")
v <- u$table %>% as.vector()
ket_qua <- rbind(ket_qua, v)
names(ket_qua) <- c("BB", "GB", "BG", "GG")
}
return(ket_qua)
}
# Sử dụng hàm với ngưỡng là 0.5 và 1000 lần chạy mô hình, kích cỡ 3000:
kq5 <- my_fun(0.5, 1000, 3000, logistic)
# Sử dụng hàm với ngưỡng là 0.6 và 1000 lần chạy mô hình, kích cỡ 3000:
kq6 <- my_fun(0.6, 1000, 3000, logistic)
df_nguong <- bind_rows(kq5 %>% mutate(Thr = "T0.5"),
kq6 %>% mutate(Thr = "T0.6"))
df_nguong %<>%
mutate(Profit = 0.2*GG - BG,
Accuracy = (BB + GG) / (BB + GG + BG + GB))
df_nguong %>%
group_by(Thr) %>%
summarise_each(funs(mean, median, min, max, sd, n()), Profit)
## # A tibble: 2 x 7
## Thr Profit_mean Profit_median Profit_min Profit_max Profit_sd Profit_n
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
## 1 T0.5 353. 353. 309. 385. 11.5 1000
## 2 T0.6 448. 448. 428. 465. 5.89 1000
df_nguong %>%
group_by(Thr) %>%
summarise_each(funs(mean, median, min, max, sd, n()), Accuracy)
## # A tibble: 2 x 7
## Thr Accuracy_mean Accuracy_median Accuracy_min Accuracy_max
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 T0.5 0.816 0.816 0.796 0.837
## 2 T0.6 0.785 0.785 0.758 0.803
## # ... with 2 more variables: Accuracy_sd <dbl>, Accuracy_n <int>
#---------------------------------------------------------------------------------
# Giải thích 5:
# Feature Engineering - bỏ / thêm / chuyển hóa biến đầu vào có thể cải thiện
# mức độ chính xác của mô hình phân loại đối với nhiều mô hình phân loại.
# References:
# - Mastering Feature Engineering Principles and Techniques for Data Scientists
# - ds_breast_cancer_cancer.r
#----------------------------------------------------------------------------------
#------ Case 1: Bỏ biến tương quan cao và phương sai không ---------#
data("GermanCredit")
df_ori <- GermanCredit
Class <- GermanCredit$Class
feature_df <- GermanCredit %>% select(-Class)
# Vị trí cột biến có phương sai zero và loại bỏ:
zero_pos <- nearZeroVar(feature_df)
zero_va <- names(feature_df)[zero_pos]
feature_df %<>% select(-zero_va)
# Loại tương quan trên 0.75:
tuong_quan <- cor(feature_df)
highCorr <- findCorrelation(tuong_quan, cutoff = .75)
var_name <- names(feature_df)[highCorr]
final_df <- feature_df %>%
select(-var_name) %>%
mutate(Class = Class)
# Model thứ nhất:
set.seed(1)
ctrl <- trainControl(method = "repeatedcv",
repeats = 20,
number = 10)
logistic1 <- train(Class ~ .,
data = final_df,
method = "glm",
trControl = ctrl)
# Model thứ 2:
logistic2 <- train(Class ~ .,
data = GermanCredit,
method = "glm",
trControl = ctrl)
# Đánh giá nhanh:
logistic1$resample %>% summary()
## Accuracy Kappa Resample
## Min. :0.670 Min. :0.1579 Length:200
## 1st Qu.:0.730 1st Qu.:0.3112 Class :character
## Median :0.750 Median :0.3750 Mode :character
## Mean :0.755 Mean :0.3800
## 3rd Qu.:0.780 3rd Qu.:0.4471
## Max. :0.850 Max. :0.6250
logistic2$resample %>% summary()
## Accuracy Kappa Resample
## Min. :0.620 Min. :0.05941 Length:200
## 1st Qu.:0.720 1st Qu.:0.30003 Class :character
## Median :0.750 Median :0.37500 Mode :character
## Mean :0.751 Mean :0.37171
## 3rd Qu.:0.780 3rd Qu.:0.45312
## Max. :0.850 Max. :0.61165
# Đánh giá hình bằng hình ảnh:
comp_df <- bind_rows(logistic1$resample %>% mutate(Model = "Logistic1"),
logistic2$resample %>% mutate(Model = "Logistic2"))
comp_df %>%
ggplot(aes(Model, Accuracy)) + geom_boxplot()

# Đánh giá bằng các tiêu chí thống kê:
comp_df %>%
group_by(Model) %>%
summarise_each(funs(mean, median, min, max, n()), Accuracy)
## # A tibble: 2 x 6
## Model Accuracy_mean Accuracy_median Accuracy_min Accuracy_max Accuracy_n
## <chr> <dbl> <dbl> <dbl> <dbl> <int>
## 1 Logi~ 0.755 0.750 0.670 0.850 200
## 2 Logi~ 0.751 0.750 0.620 0.850 200
#------ Case 2: Chuẩn hóa dữ liệu (ds_breast_cancer_cancer) ---------#
#---------------------------------------------------------------
# Main Project: hmeq.csv (to be continued in part 2)
#---------------------------------------------------------------