Mục tiêu của mô hình lần này đó là xây dựng một mô hình phân loại mà hiệu quả hướng tới là xác định chính xác được các giao dịch bị gian lận. Bộ dữ liệu mà chúng ta sử dụng trong bài viết này được lấy từ kaggle ở đường link bên dưới:
https://www.kaggle.com/mlg-ulb/creditcardfraud
library(data.table)
CreditCard <- fread('creditcard.csv')
str(CreditCard)
## Classes 'data.table' and 'data.frame': 284807 obs. of 31 variables:
## $ Time : num 0 0 1 1 2 2 4 7 7 9 ...
## $ V1 : num -1.36 1.192 -1.358 -0.966 -1.158 ...
## $ V2 : num -0.0728 0.2662 -1.3402 -0.1852 0.8777 ...
## $ V3 : num 2.536 0.166 1.773 1.793 1.549 ...
## $ V4 : num 1.378 0.448 0.38 -0.863 0.403 ...
## $ V5 : num -0.3383 0.06 -0.5032 -0.0103 -0.4072 ...
## $ V6 : num 0.4624 -0.0824 1.8005 1.2472 0.0959 ...
## $ V7 : num 0.2396 -0.0788 0.7915 0.2376 0.5929 ...
## $ V8 : num 0.0987 0.0851 0.2477 0.3774 -0.2705 ...
## $ V9 : num 0.364 -0.255 -1.515 -1.387 0.818 ...
## $ V10 : num 0.0908 -0.167 0.2076 -0.055 0.7531 ...
## $ V11 : num -0.552 1.613 0.625 -0.226 -0.823 ...
## $ V12 : num -0.6178 1.0652 0.0661 0.1782 0.5382 ...
## $ V13 : num -0.991 0.489 0.717 0.508 1.346 ...
## $ V14 : num -0.311 -0.144 -0.166 -0.288 -1.12 ...
## $ V15 : num 1.468 0.636 2.346 -0.631 0.175 ...
## $ V16 : num -0.47 0.464 -2.89 -1.06 -0.451 ...
## $ V17 : num 0.208 -0.115 1.11 -0.684 -0.237 ...
## $ V18 : num 0.0258 -0.1834 -0.1214 1.9658 -0.0382 ...
## $ V19 : num 0.404 -0.146 -2.262 -1.233 0.803 ...
## $ V20 : num 0.2514 -0.0691 0.525 -0.208 0.4085 ...
## $ V21 : num -0.01831 -0.22578 0.248 -0.1083 -0.00943 ...
## $ V22 : num 0.27784 -0.63867 0.77168 0.00527 0.79828 ...
## $ V23 : num -0.11 0.101 0.909 -0.19 -0.137 ...
## $ V24 : num 0.0669 -0.3398 -0.6893 -1.1756 0.1413 ...
## $ V25 : num 0.129 0.167 -0.328 0.647 -0.206 ...
## $ V26 : num -0.189 0.126 -0.139 -0.222 0.502 ...
## $ V27 : num 0.13356 -0.00898 -0.05535 0.06272 0.21942 ...
## $ V28 : num -0.0211 0.0147 -0.0598 0.0615 0.2152 ...
## $ Amount: num 149.62 2.69 378.66 123.5 69.99 ...
## $ Class : int 0 0 0 0 0 0 0 0 0 0 ...
## - attr(*, ".internal.selfref")=<externalptr>
Bộ dữ liệu bao gồm 30 biến trong đó biến Class là biến target có giá trị bằng 1 nếu giao dịch không gian lận, bằng 0 nếu giao dịch bình thường. Các biến predictor gồm các biến gốc và các biến đã được biến đổi nhằm bảo mật thông tin. 2 biến gốc bao gồm:
Các biến còn lại từ V1 đến V28 là những biến nhân tố đã được tạo ra từ những biến gốc. Trong khuôn khổ bài viết chúng ta chấp nhận hạn chế dữ liệu đã bị biến đổi và xây dựng model dựa trên tập dữ liệu đó.
Số lượng giao dịch thu thập trong bộ dữ liệu là 284807 giao dịchg. Chúng ta cùng kiểm tra tỷ lệ các giao dịch bình thường và giao dịch gian lận trong số các giao dịch này.
library(dplyr)
library(ggplot2)
CreditCard %>% select(Class) %>%
ggplot(aes(x = Class)) +
geom_bar(stat = 'count')
CreditCard %>% group_by(Class) %>%
summarise(freq = n())
CreditCard %>% group_by(Class) %>%
summarise(freq = n()/nrow(CreditCard)*100)
Ta có thể thấy dữ liệu có hiện tượng unbalance vì tỷ lệ các giao dịch gian lận chỉ chưa đầy 0.2% và có 492 giao dịch gian lận trên tổng số 284807 giao dịch. Do đó ta có thể sử dụng kĩ thuật undersampling để tạo ra mẫu dữ liệu mới bao gồm toàn bộ những giao dịch gian lận và số lượng tương ứng những giao dịch bình thường được rút ra từ mẫu gốc. Cách làm này sẽ khắc phục được hiện tượng unbalance và cải thiện tỷ lệ dự báo chính xác ở các class thiểu số.
Nhắc lại một số chỉ tiêu đánh giá model:
TP: True positive là số lượng những giao dịch được dự báo là gian lận trong khi trên thực tế giao dịch đó là gian lận.
TN: True negative là số lượng những giao dịch được dự báo là bình thường trong khi trên thực tế giao dịch đó là bình thường.
FP: False positive là số lượng những trường hợp được dự báo là gian lận nhưng bản chất của giao dịch là bình thường. Đây còn gọi là mắc sai lầm loại I trong thống kê.
FN: False positive là số lượng những trường hợp được dự báo là bình thường nhưng bản chất của giao dịch là gian lận. Đây còn gọi là mắc sai lầm loại II.
Chú ý rằng do ở đây chúng ta gán Class = 1 đối với những giao dịch gian lận nên gian lận được coi như là positive và bình thường là negative. Không nên hiểu positive và negative theo nghĩa đen của nó (tức là positive là giao dịch tốt, negative là giao dịch gian lận).
Trong trường hợp mẫu quá ít các giao dịch gian lận và ta quan tâm việc dự báo đúng các giao dịch gian lận hơn thì Precision và Recall là 2 chỉ số phù hợp hơn để đánh giá độ chính xác của model so với Accuracy và Specificity. Điều này là dễ hiểu bởi trong trường hợp model đưa ra một tỷ lệ Accuracy hay Specificity cao thì cũng không có nhiều ý nghĩa vì khi lựa chọn 100% các giao dịch là bình thường thì ta cũng thu được hai tỷ lệ này rất cao.
Ta nhận thấy biến Time và biến Amount là những biến gốc. Chúng ta sẽ rescaling những biến này theo công thức chuẩn hóa để thu được các biến mới tuân theo phân phối chuẩn hóa.
f_norm_rescale <- function(X){
(X-mean(X))/sd(X)
}
CreditCard$Amount <- f_norm_rescale(CreditCard$Amount)
CreditCard$Time <- f_norm_rescale(CreditCard$Time)
Xây dựng mẫu training bằng phương pháp undersampling
library(e1071)
set.seed(1)
#Lấy số lượng giao dịch gian lận
n_neg_train <- nrow(CreditCard[CreditCard$Class == 1, ])
#Lấy ngẫu nhiên các chỉ số của giao dịch thông thường với số lượng bằng giao dịch gian lận.
index_pos <- sample(which(CreditCard$Class == 0), n_neg_train, replace = FALSE)
#Tạo mẫu dữ liệu training
Data_undersample <- rbind(CreditCard[CreditCard$Class == 1, ], CreditCard[index_pos, ])
#Kiểm tra tỷ lệ giao dịch gian lận và thông thường trong mẫu vừa tạo
Data_undersample %>% group_by(Class) %>%
summarise(freq = n())
Có nhiều phương pháp để lựa chọn biến predictor. Trong bài viết này mình sẽ sử dụng visualization phân phối của các biến predictor theo từng class để đánh giá mức độ khác biệt giữa các đường curve ứng với mỗi class. Các đường curve này càng khác biệt càng chứng tỏ biến predictor phân loại mạnh biến target.
library(ggplot2)
library(reshape2)
f_vis <- function(df){
df %>% melt(id = 'Class') %>%
ggplot(aes(value, color = Class %>% as.character(),
fill = Class %>% as.character())) +
geom_density(alpha = 0.5, show.legend = FALSE) +
facet_wrap(~variable, ncol = 3, scales = 'free')
}
f_vis(Data_undersample[,c(1:9, 31)])
f_vis(Data_undersample[,c(10:18, 31)])
f_vis(Data_undersample[,c(19:27, 31)])
f_vis(Data_undersample[,c(28:31)])
Ta thấy các biến Time, V13, V15, V22, V24, V25, V26 và Amount không có sự khác biệt trong phân phối giữa 2 nhóm nên chúng ta sẽ chỉ lựa chọn các biến predictor là những biến còn lại
Data_undersample <- Data_undersample %>% select(-Time, -V13, -V15, -V22, -V24, -V25, -V26, -Amount)
Chúng ta sẽ sử dụng phương pháp cross validation với tập dữ liệu vừa undersampling với số lần k-Fold=10. Mục đích của cross validation là để đánh giá toàn diện khả năng dự báo chính xác của model logistic thông qua nhiều lần chia mẫu train/test. Hồi qui model trên tập train và sử dụng model để dự báo trên tập test. Kết quả thu được sẽ gồm nhiều chỉ số ứng với nhiều lần chia mẫu. Để đơn giản hóa chúng ta chấp nhận quan sát tại các fold trùng nhau tức là chúng ta sẽ có 10 lần chia mẫu mà không quan tâm các quan sát trên tập test có lặp lại hay không.
#Tạo ID cho mẫu
Data_undersample$ID <- 1:nrow(Data_undersample)
logistic_regression <- function(i, thresh){
#Chia mẫu train và test theo tỷ lệ 70:30 sao cho tỷ lệ giao dịch gian lận/thông thường là cân bằng giữa 2 mẫu.
train_undersample <- Data_undersample %>% group_by(Class) %>%
sample_frac(0.7) %>% ungroup()
test_undersample <- setdiff(Data_undersample, train_undersample)
#Kiểm tra mức độ cân bằng giữa 1 class trên train và test
train_undersample %>% group_by(Class) %>%
summarise(freq = n())
test_undersample %>% group_by(Class) %>%
summarise(freq = n())
#Remove ID
train_undersample <- train_undersample %>% select(-ID)
test_undersample <- test_undersample %>% select(-ID)
#Hồi qui logistic model
glm.fit = suppressWarnings(glm(Class ~ V1+V2+V3+V4+V5+V6+V7+V8+V9+V10+V11+V12+V14+V16+V17+V18+V19+V20+V21+V23+V27+V28, family = binomial, data = train_undersample))
#summary(glm.fit)
glm.probs <- predict(glm.fit, test_undersample, type = 'response')
glm.pred <- rep(1, length(glm.probs))
glm.pred[glm.probs < thresh] <- 0
cf_matrix <- table(test_undersample$Class, glm.pred)
TP <- cf_matrix[2, 2]
FP <- cf_matrix[1, 2]
FN <- cf_matrix[2, 1]
TN <- cf_matrix[1, 1]
precision <- TP/(TP+FP)
recall <- TP/(TP+FN)
print("-------------------------")
print(paste0("Time = ", i))
print(paste0("precision = ", precision))
print(paste0("recall = ", recall))
data.frame(split_time = i,precision = precision, recall = recall)
}
cross_validation <- function(time, thresh){
result <- data.frame()
for (i in 1:time){
df <- logistic_regression(i, thresh)
result <- rbind(result, df)
}
result
}
accuracy_tbl <- cross_validation(10, 0.5)
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.964028776978417"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.957142857142857"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.945205479452055"
## [1] "recall = 0.932432432432432"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.99236641221374"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.963235294117647"
## [1] "recall = 0.885135135135135"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.918918918918919"
## [1] "recall = 0.918918918918919"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.943262411347518"
## [1] "recall = 0.898648648648649"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.985074626865672"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.971014492753623"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.937062937062937"
## [1] "recall = 0.905405405405405"
accuracy_tbl %>% summarise(avg_precision = mean(precision),
avg_recall = mean(recall))
Như vậy kết quả cho thấy quan 10 lần chia mẫu thì mô hình có tỷ lệ precision khá cao ở mức 96% và tỷ lệ recall ở mức 90%. Điều đó có nghĩa rằng cứ 10 giao dịch gian lận thì 9 giao dịch được dự báo chính xác. Và cứ 100 giao dịch được dự báo là gian lận thì có 96 giao dịch dự báo đúng.
Đường Precision-Recall curve được sử dụng để đánh giá sự đánh đổi giữa precision và recall khi thay đổi ngường threshold. Precision-Recall curve cho chúng ta biết sức mạnh phân loại của mô hình như thế nào bằng việc đo phần diện tích nằm phái dưới đường này hay còn gọi là chỉ số AUC (area under curve).
set.seed(123)
precision_recall_tbl <- data.frame()
for (thresh in c(seq(0.01, 0.09, by = 0.01), seq(0.1, 0.9, by = 0.1), seq(0.91, 0.99, by = 0.01))){
print("========================================================")
print(paste0("threshold = ", thresh))
df <- cross_validation(10, thresh)
df$threshold <- thresh
precision_recall_tbl <- rbind(precision_recall_tbl, df)
}
## [1] "========================================================"
## [1] "threshold = 0.01"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.564885496183206"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.522968197879859"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.623931623931624"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.561068702290076"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.530685920577617"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.62719298245614"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.542435424354244"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.532608695652174"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.519434628975265"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.576470588235294"
## [1] "recall = 0.993243243243243"
## [1] "========================================================"
## [1] "threshold = 0.02"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.605809128630705"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.559386973180077"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.597560975609756"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.647321428571429"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.578125"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.565384615384615"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.671361502347418"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.626609442060086"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.63519313304721"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.622317596566524"
## [1] "recall = 0.97972972972973"
## [1] "========================================================"
## [1] "threshold = 0.03"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.651785714285714"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.648648648648649"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.698564593301435"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.653153153153153"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.653333333333333"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.654708520179372"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.640692640692641"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.70873786407767"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.582677165354331"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.58102766798419"
## [1] "recall = 0.993243243243243"
## [1] "========================================================"
## [1] "threshold = 0.04"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.685446009389671"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.71356783919598"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.651982378854626"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.683962264150943"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.677570093457944"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.718592964824121"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.682027649769585"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.722772277227723"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.701421800947867"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.65625"
## [1] "recall = 0.993243243243243"
## [1] "========================================================"
## [1] "threshold = 0.05"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.783783783783784"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.686915887850467"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.736040609137056"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.763440860215054"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.690140845070423"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.68075117370892"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.685446009389671"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.712195121951219"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.741116751269036"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.746113989637306"
## [1] "recall = 0.972972972972973"
## [1] "========================================================"
## [1] "threshold = 0.06"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.798882681564246"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.757894736842105"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.78804347826087"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.772972972972973"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.718446601941748"
## [1] "recall = 1"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.771739130434783"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.75"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.792134831460674"
## [1] "recall = 0.952702702702703"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.744791666666667"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.775401069518717"
## [1] "recall = 0.97972972972973"
## [1] "========================================================"
## [1] "threshold = 0.07"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.831395348837209"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.782608695652174"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.765957446808511"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.744897959183674"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.764397905759162"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.817142857142857"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.803370786516854"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.720588235294118"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.783783783783784"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.771739130434783"
## [1] "recall = 0.959459459459459"
## [1] "========================================================"
## [1] "threshold = 0.08"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.801104972375691"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.825581395348837"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.8125"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.840236686390533"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.811428571428571"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.753926701570681"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.812154696132597"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.794444444444444"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.805555555555556"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.819209039548023"
## [1] "recall = 0.97972972972973"
## [1] "========================================================"
## [1] "threshold = 0.09"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.82183908045977"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.827586206896552"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.802197802197802"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.857142857142857"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.832369942196532"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.813953488372093"
## [1] "recall = 0.945945945945946"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.837209302325581"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.821428571428571"
## [1] "recall = 0.932432432432432"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.817142857142857"
## [1] "recall = 0.966216216216216"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.806629834254144"
## [1] "recall = 0.986486486486487"
## [1] "========================================================"
## [1] "threshold = 0.1"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.794285714285714"
## [1] "recall = 0.939189189189189"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.855421686746988"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.826347305389222"
## [1] "recall = 0.932432432432432"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.796703296703297"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.786096256684492"
## [1] "recall = 0.993243243243243"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.852941176470588"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.801104972375691"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.8"
## [1] "recall = 0.972972972972973"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.849397590361446"
## [1] "recall = 0.952702702702703"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.822857142857143"
## [1] "recall = 0.972972972972973"
## [1] "========================================================"
## [1] "threshold = 0.2"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.891025641025641"
## [1] "recall = 0.939189189189189"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.900621118012422"
## [1] "recall = 0.97972972972973"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.897959183673469"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.896774193548387"
## [1] "recall = 0.939189189189189"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.874251497005988"
## [1] "recall = 0.986486486486487"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.89171974522293"
## [1] "recall = 0.945945945945946"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.885350318471338"
## [1] "recall = 0.939189189189189"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.879746835443038"
## [1] "recall = 0.939189189189189"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.922077922077922"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.902597402597403"
## [1] "recall = 0.939189189189189"
## [1] "========================================================"
## [1] "threshold = 0.3"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.957142857142857"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.938356164383562"
## [1] "recall = 0.925675675675676"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.950354609929078"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.952702702702703"
## [1] "recall = 0.952702702702703"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.951048951048951"
## [1] "recall = 0.918918918918919"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.937931034482759"
## [1] "recall = 0.918918918918919"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.932432432432432"
## [1] "recall = 0.932432432432432"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.940740740740741"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.946666666666667"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.924657534246575"
## [1] "recall = 0.912162162162162"
## [1] "========================================================"
## [1] "threshold = 0.4"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.939597315436242"
## [1] "recall = 0.945945945945946"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.926666666666667"
## [1] "recall = 0.939189189189189"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.9375"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.930555555555556"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.955223880597015"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.944055944055944"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.965034965034965"
## [1] "recall = 0.932432432432432"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.916666666666667"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.949640287769784"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.956834532374101"
## [1] "recall = 0.898648648648649"
## [1] "========================================================"
## [1] "threshold = 0.5"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.931034482758621"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.992647058823529"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.969924812030075"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.940397350993378"
## [1] "recall = 0.959459459459459"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.979020979020979"
## [1] "recall = 0.945945945945946"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.944055944055944"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.950704225352113"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.944827586206897"
## [1] "recall = 0.925675675675676"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.992424242424242"
## [1] "recall = 0.885135135135135"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.948529411764706"
## [1] "recall = 0.871621621621622"
## [1] "========================================================"
## [1] "threshold = 0.6"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.977941176470588"
## [1] "recall = 0.898648648648649"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.978723404255319"
## [1] "recall = 0.932432432432432"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.937931034482759"
## [1] "recall = 0.918918918918919"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.977611940298508"
## [1] "recall = 0.885135135135135"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.970149253731343"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.978260869565217"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.971428571428571"
## [1] "recall = 0.918918918918919"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.930555555555556"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.978260869565217"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.943262411347518"
## [1] "recall = 0.898648648648649"
## [1] "========================================================"
## [1] "threshold = 0.7"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.985294117647059"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.958333333333333"
## [1] "recall = 0.932432432432432"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.977272727272727"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.971014492753623"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.985294117647059"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.977443609022556"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.96969696969697"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.962686567164179"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.956521739130435"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.965034965034965"
## [1] "recall = 0.932432432432432"
## [1] "========================================================"
## [1] "threshold = 0.8"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.944827586206897"
## [1] "recall = 0.925675675675676"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.938356164383562"
## [1] "recall = 0.925675675675676"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.971014492753623"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.985294117647059"
## [1] "recall = 0.905405405405405"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.956521739130435"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.984848484848485"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.962121212121212"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.992481203007519"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.984732824427481"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.977611940298508"
## [1] "recall = 0.885135135135135"
## [1] "========================================================"
## [1] "threshold = 0.9"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.984615384615385"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.976744186046512"
## [1] "recall = 0.851351351351351"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.984496124031008"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.96969696969697"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.992481203007519"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.977443609022556"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 1"
## [1] "recall = 0.824324324324324"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.947368421052632"
## [1] "recall = 0.851351351351351"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.969230769230769"
## [1] "recall = 0.851351351351351"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.96969696969697"
## [1] "recall = 0.864864864864865"
## [1] "========================================================"
## [1] "threshold = 0.91"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.984251968503937"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.9765625"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.984732824427481"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.992248062015504"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 1"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 1"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.963768115942029"
## [1] "recall = 0.898648648648649"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.9765625"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.977272727272727"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.992248062015504"
## [1] "recall = 0.864864864864865"
## [1] "========================================================"
## [1] "threshold = 0.92"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.983606557377049"
## [1] "recall = 0.810810810810811"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.978260869565217"
## [1] "recall = 0.912162162162162"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.984848484848485"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.975206611570248"
## [1] "recall = 0.797297297297297"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.992481203007519"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.991935483870968"
## [1] "recall = 0.831081081081081"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 1"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.992125984251969"
## [1] "recall = 0.851351351351351"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 1"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 1"
## [1] "recall = 0.878378378378378"
## [1] "========================================================"
## [1] "threshold = 0.93"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.977777777777778"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.9921875"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.968503937007874"
## [1] "recall = 0.831081081081081"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.992248062015504"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.977099236641221"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.992248062015504"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.984251968503937"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.977777777777778"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.992424242424242"
## [1] "recall = 0.885135135135135"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.9921875"
## [1] "recall = 0.858108108108108"
## [1] "========================================================"
## [1] "threshold = 0.94"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.976923076923077"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.977272727272727"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.976923076923077"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.985074626865672"
## [1] "recall = 0.891891891891892"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.9921875"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.992125984251969"
## [1] "recall = 0.851351351351351"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 1"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.984732824427481"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.984496124031008"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.992125984251969"
## [1] "recall = 0.851351351351351"
## [1] "========================================================"
## [1] "threshold = 0.95"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.984126984126984"
## [1] "recall = 0.837837837837838"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.968992248062015"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.977941176470588"
## [1] "recall = 0.898648648648649"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.991935483870968"
## [1] "recall = 0.831081081081081"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.992248062015504"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.977941176470588"
## [1] "recall = 0.898648648648649"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.992"
## [1] "recall = 0.837837837837838"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.977272727272727"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.992424242424242"
## [1] "recall = 0.885135135135135"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.991935483870968"
## [1] "recall = 0.831081081081081"
## [1] "========================================================"
## [1] "threshold = 0.96"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 1"
## [1] "recall = 0.817567567567568"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 1"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.977272727272727"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 1"
## [1] "recall = 0.898648648648649"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 1"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 1"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.992"
## [1] "recall = 0.837837837837838"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.979166666666667"
## [1] "recall = 0.952702702702703"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 1"
## [1] "recall = 0.790540540540541"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 1"
## [1] "recall = 0.817567567567568"
## [1] "========================================================"
## [1] "threshold = 0.97"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.976744186046512"
## [1] "recall = 0.851351351351351"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 0.969230769230769"
## [1] "recall = 0.851351351351351"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.975206611570248"
## [1] "recall = 0.797297297297297"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.991525423728814"
## [1] "recall = 0.790540540540541"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 1"
## [1] "recall = 0.871621621621622"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.992424242424242"
## [1] "recall = 0.885135135135135"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 0.984496124031008"
## [1] "recall = 0.858108108108108"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 1"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.976377952755906"
## [1] "recall = 0.837837837837838"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 1"
## [1] "recall = 0.817567567567568"
## [1] "========================================================"
## [1] "threshold = 0.98"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.992063492063492"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 1"
## [1] "recall = 0.797297297297297"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 0.984251968503937"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 1"
## [1] "recall = 0.790540540540541"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 1"
## [1] "recall = 0.824324324324324"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.991935483870968"
## [1] "recall = 0.831081081081081"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 1"
## [1] "recall = 0.804054054054054"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 1"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 1"
## [1] "recall = 0.790540540540541"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 0.982142857142857"
## [1] "recall = 0.743243243243243"
## [1] "========================================================"
## [1] "threshold = 0.99"
## [1] "-------------------------"
## [1] "Time = 1"
## [1] "precision = 0.991452991452991"
## [1] "recall = 0.783783783783784"
## [1] "-------------------------"
## [1] "Time = 2"
## [1] "precision = 1"
## [1] "recall = 0.783783783783784"
## [1] "-------------------------"
## [1] "Time = 3"
## [1] "precision = 1"
## [1] "recall = 0.72972972972973"
## [1] "-------------------------"
## [1] "Time = 4"
## [1] "precision = 0.983870967741935"
## [1] "recall = 0.824324324324324"
## [1] "-------------------------"
## [1] "Time = 5"
## [1] "precision = 0.991735537190083"
## [1] "recall = 0.810810810810811"
## [1] "-------------------------"
## [1] "Time = 6"
## [1] "precision = 0.984251968503937"
## [1] "recall = 0.844594594594595"
## [1] "-------------------------"
## [1] "Time = 7"
## [1] "precision = 1"
## [1] "recall = 0.831081081081081"
## [1] "-------------------------"
## [1] "Time = 8"
## [1] "precision = 0.99236641221374"
## [1] "recall = 0.878378378378378"
## [1] "-------------------------"
## [1] "Time = 9"
## [1] "precision = 0.96969696969697"
## [1] "recall = 0.864864864864865"
## [1] "-------------------------"
## [1] "Time = 10"
## [1] "precision = 1"
## [1] "recall = 0.844594594594595"
precision_recall_tbl %>% group_by(threshold) %>%
summarise(avg_precision = mean(precision), avg_recall = mean(recall)) %>%
ggplot(aes(x = avg_recall, y = avg_precision)) +
geom_line() +
xlim(c(0.85,1)) +
ylim(c(0.55,1))
Đồ thị cho thấy đường Precision-recall curve có xu hướng lồi về phía trên bên phải làm cho diện tích AUC lớn. Điều đó chứng tỏ phương pháp logistic là mạnh trong phân loại các loại hình giao dịch.
Chúng ta tạm hài lòng với kết quả này. Tiếp theo cần kiểm tra mức độ dự báo chính xác của mô hình trên toàn bộ tập dữ liệu.
Ở trên chúng ta mới chỉ kiểm tra mức độ dự báo chính xác trên dữ liệu đã được undersampling. Để khẳng định rằng model logistic được xây dựng trên mẫu undersampling là rất chính xác trong phân loại các giao dịch lỗi ta sẽ so sánh kết quả dự báo khi được training trên chỉ tập train_undersample với kết quả dự báo khi training trên tập train được trích xuất từ toàn bộ mẫu. Chú ý rằng về mặt nguyên tắc chúng ta luôn phải dành riêng một tập test để đánh giá và không bao giờ được sử dụng kết quả mô hình trên chính các tập train để so sánh. Đề khách quan chúng ta sẽ cùng chọn tập test cho cả 2 mô hình là tập test được trích xuất từ toàn bộ mẫu.
Chia mẫu train và test theo tỷ lệ 70/30 cho toàn bộ mẫu:
set.seed(123)
#Thêm ID các giao dịch
CreditCard$ID <- 1:nrow(CreditCard)
train <- CreditCard %>% group_by(Class) %>%
sample_frac(0.7)
test <- setdiff(CreditCard, train)
Sử dụng model được train từ tập undersample để dự báo cho tập test.
#Hồi qui logistic model
glm.fit = suppressWarnings(glm(Class ~ V1+V2+V3+V4+V5+V6+V7+V8+V9+V10+V11+V12+V14+V16+V17+V18+V19+V20+V21+V23+V27+V28, family = binomial, data = Data_undersample))
glm.probs <- predict(glm.fit, test, type = 'response')
glm.pred <- rep(1, length(glm.probs))
glm.pred[glm.probs < 0.5] <- 0
cf_matrix <- table(test$Class, glm.pred)
cf_matrix
## glm.pred
## 0 1
## 0 82492 2803
## 1 10 138
TP <- cf_matrix[2, 2]
FP <- cf_matrix[1, 2]
FN <- cf_matrix[2, 1]
TN <- cf_matrix[1, 1]
recall <- TP/(TP+FN)
print(paste0("recall = ", recall))
## [1] "recall = 0.932432432432432"
Ta thấy rằng xét trên toàn bộ những giao dịch bất thường được dự báo chính xác thì tỷ lệ này lên tới 93% (tức recall = 93%). Đây là một mức phát hiện các giao dịch gian lận khá cao và tỷ lệ này cũng gần khớp với dự báo trên tập test_undersampling ở mức 90% nên ta có thể khẳng định không có hiện tượng overfiting. Mô hình có thể được áp dụng vào thực tiễn mà không cần hoài nghi.
Sử dụng model được train từ tập train để dự báo cho tập test.
#Hồi qui logistic model
glm.fit = suppressWarnings(glm(Class ~ V1+V2+V3+V4+V5+V6+V7+V8+V9+V10+V11+V12+V14+V16+V17+V18+V19+V20+V21+V23+V27+V28, family = binomial, data = train))
#summary(glm.fit)
glm.probs <- predict(glm.fit, test, type = 'response')
glm.pred <- rep(1, length(glm.probs))
glm.pred[glm.probs < 0.5] <- 0
cf_matrix <- table(test$Class, glm.pred)
cf_matrix
## glm.pred
## 0 1
## 0 85275 20
## 1 58 90
TP <- cf_matrix[2, 2]
FP <- cf_matrix[1, 2]
FN <- cf_matrix[2, 1]
TN <- cf_matrix[1, 1]
recall <- TP/(TP+FN)
print(paste0("recall = ", recall))
## [1] "recall = 0.608108108108108"
Ta thấy với cùng một ngưỡng threshold là 0.5 thì tỷ lệ các giao dịch được dự báo chuẩn xác là gian lận thấp sơn so với khi sử dụng undersampling khi chỉ có 60% các giao dịch gian lận được phát hiện. Điều đó cho thấy phương pháp undersampling đã cải thiện được rất lớn kết quả dự báo của mô hình.
Trong bài viết này mới chỉ ứng dụng phương pháp đơn giản nhất là hồi qui logistic. Ngoài logistic chúng ta cũng có thể thử những phương pháp khác như model random forest, SVM, neural network, KNN với cùng một ý tưởng undersampling mẫu như trên. Phần này xin dành cho bạn đọc.