Cuộc thi VinBigData Chest X-ray Abnormalities Detection của Vingroup Big Data Institute với dữ liệu scan có dung lượng (đã nén) là hơn 200 GB. Khối dữ liệu này nằm ngoài khả năng của con máy Dell Precision T5610 chỉ với 64 GB RAM. Do vậy trong post này sử dụng bộ dữ liệu tương tự nhưng nhỏ hơn nhiều từ cuộc thi SARS-COV-2 Ct-Scan Dataset. Thách thức đầu tiên là xử lí bộ dữ liệu này về dạng phù hợp cho các mô hình Machine Learning/Deep Learning. Hàm process_image_data dưới đây được viết dựa trên tham khảo từ Spencer Palladino để xử lí sơ bộ dữ liệu ảnh:
# Clear R environmet:
rm(list = ls())
library(magrittr)
library(keras)
# Function for pre-processing image data:
<- function(image_path, n_dim) {
process_image_data
# Load image data:
<- lapply(image_path, image_load, grayscale = TRUE)
img_data
# Convert to N-dimensional array:
<- lapply(img_data, image_to_array)
array_data
# Resize and normalize array:
<- lapply(array_data, image_array_resize, height = n_dim, width = n_dim)
array_resized <- normalize(array_resized, axis = 1)
array_normalized
# Return final outputs:
return(array_normalized)
}
Sử dụng hàm này để load và xử lí 4 cases (2 cases là CT image của 2 bệnh nhân nhiễm Covid 19 và 2 cases là CT scan của 2 người không bị nhiễm Covid 19):
# Paths to image files:
<- dir("F:/archive/COVID/", full.names = TRUE)
covid_path
<- dir("F:/archive/non-COVID/", full.names = TRUE)
non_covid_path
# Select some cases:
<- 500
n_dim
<- process_image_data(image_path = c(covid_path[1:2], non_covid_path[1:2]), n_dim = n_dim)
data_4
<- data_4[, , , 1] # Extract the first channel. data_4
Xem qua ảnh CT scan của 4 cases này:
# CT scan image for 4 patients:
library(reshape2)
library(dplyr)
lapply(1:4, function(x) {melt(data_4[x, , ])}) -> list_covid
do.call("bind_rows", list_covid) -> df_sample
library(ggplot2)
%>%
df_sample mutate(type = rep(c("Covid_Case1", "Covid_Case2", "NonCovid_Case1", "NonCovid_Case2"), each = n_dim*n_dim, time = 1)) %>%
ggplot(aes(Var1, Var2, fill = value)) +
geom_raster() +
facet_wrap(~ type) +
theme_minimal() +
theme(legend.position = "none") +
theme(panel.grid = element_blank()) +
theme(axis.title = element_blank()) +
theme(axis.text = element_blank()) +
labs(x = NULL, y = NULL, title = "Figure 1: Covid and Non-Covid CT scan image") +
scale_fill_viridis_c()
Load và xử lí sơ bộ toàn bộ ảnh CT scan, lấy ngẫu nhiên 70% cho training và 30% còn lại cho testing:
# Reset n_dim:
<- 100
n_dim
# Load and process data:
%>%
covid_path process_image_data(n_dim = n_dim) %>%
1] -> covid_data
.[, , ,
<- array_reshape(covid_data, c(nrow(covid_data), n_dim*n_dim))
covidData_reshaped
%>%
non_covid_path process_image_data(n_dim = n_dim) %>%
1] -> noncovid_data
.[, , ,
<- array_reshape(noncovid_data, c(nrow(noncovid_data), n_dim*n_dim))
noncovidData_reshaped
<- rbind(cbind(covidData_reshaped, 1), cbind(noncovidData_reshaped, 0))
image_data
# Shuffle our data:
set.seed(12012020)
<- image_data[sample(nrow(image_data), replace = FALSE), ]
image_data
# Set 70% data for training, 30% for testing CNN:
set.seed(12012020)
<- sample(x = 1:2, size = nrow(image_data), replace = TRUE, prob = c(0.7, 0.3))
split
<- image_data[split == 1, ]
train
<- image_data[split == 2, ]
test
<- image_data[split == 1, n_dim*n_dim + 1] # Label in training dataset.
train_target
<- image_data[split == 2, n_dim*n_dim + 1] # Label in testing dataset.
test_target
# Convert to categorical for binary classification:
<- to_categorical(train_target)
train_label
<- to_categorical(test_target) test_label
Convolutional Neural Network - CNN được lựa chọn làm mô hình phân loại. Trong post này, keras - một platform thường được sử dụng cho Deep Learning được sử dụng để huấn luyện CNN. Quá trình huấn luyện CNN dưới đây có thể mất vài ba phút:
# Set drop rate:
<- 0.2
drop_rate
<- 2**10
my_dim
# Setup CNN:
<- keras_model_sequential() %>%
model layer_dense(units = my_dim, activation = "relu") %>%
layer_dropout(drop_rate) %>%
layer_dense(units = my_dim / 2, activation = "relu") %>%
layer_dropout(drop_rate) %>%
layer_dense(units = my_dim / 4, activation = "relu") %>%
layer_dropout(drop_rate) %>%
layer_dense(units = 2, activation = "sigmoid") %>% # For binary classification.
compile(optimizer = "adam",
loss = "binary_crossentropy",
metrics = "accuracy")
# Train CNN:
<- model %>%
fit_covid fit(x = train,
y = train_label,
epochs = 10*5,
batch_size = 2**5,
verbose = 2,
validation_split = 0.2)
Chúng ta có thể khảo sát quá trình huấn luyện CNN:
# Process of training CNN:
plot(fit_covid) +
labs(title = "Figure 2: Process of training Convolutional Neural Network ") +
theme(legend.position = "top")
Với CNN đã được huấn luyện ở trên, chúng ta có thể sử dụng để đánh giá khả năng phân loại khi áp dụng cho bộ dữ liệu test:
# Use CNN for predicting:
<- model %>%
prob_predicted predict(test) %>%
2]
.[,
# Model performance by confusion matrix:
<- case_when(prob_predicted > 0.5 ~ "Covid", TRUE ~ "NonCovid") %>% factor()
class_predicted
<- case_when(test_target == 1 ~ "Covid", TRUE ~ "NonCovid") %>% factor()
class_actuals
library(caret)
confusionMatrix(data = class_predicted, reference = class_actuals, positive = "Covid")
## Confusion Matrix and Statistics
##
## Reference
## Prediction Covid NonCovid
## Covid 375 0
## NonCovid 0 372
##
## Accuracy : 1
## 95% CI : (0.9951, 1)
## No Information Rate : 0.502
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 1
##
## Mcnemar's Test P-Value : NA
##
## Sensitivity : 1.000
## Specificity : 1.000
## Pos Pred Value : 1.000
## Neg Pred Value : 1.000
## Prevalence : 0.502
## Detection Rate : 0.502
## Detection Prevalence : 0.502
## Balanced Accuracy : 1.000
##
## 'Positive' Class : Covid
##
Từ Confusion Matrix ta có thể thấy CNN đạt mức chính xác 100% trên bộ dữ liệu test.
sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 19043)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=English_United States.1252
## [2] LC_CTYPE=English_United States.1252
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.1252
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] caret_6.0-90 lattice_0.20-45 ggplot2_3.3.5 dplyr_1.0.7
## [5] reshape2_1.4.4 keras_2.7.0 magrittr_2.0.1
##
## loaded via a namespace (and not attached):
## [1] Rcpp_1.0.7 lubridate_1.8.0 listenv_0.8.0
## [4] png_0.1-7 class_7.3-19 assertthat_0.2.1
## [7] zeallot_0.1.0 digest_0.6.28 ipred_0.9-12
## [10] foreach_1.5.1 utf8_1.2.2 parallelly_1.30.0
## [13] R6_2.5.1 plyr_1.8.6 stats4_4.1.2
## [16] evaluate_0.14 highr_0.9 pillar_1.6.4
## [19] tfruns_1.5.0 rlang_0.4.12 data.table_1.14.2
## [22] whisker_0.4 jquerylib_0.1.4 rpart_4.1-15
## [25] Matrix_1.3-4 reticulate_1.22 rmarkdown_2.11
## [28] labeling_0.4.2 splines_4.1.2 gower_0.2.2
## [31] stringr_1.4.0 munsell_0.5.0 compiler_4.1.2
## [34] xfun_0.28 pkgconfig_2.0.3 base64enc_0.1-3
## [37] globals_0.14.0 tensorflow_2.7.0 htmltools_0.5.2
## [40] nnet_7.3-16 tidyselect_1.1.1 tibble_3.1.6
## [43] prodlim_2019.11.13 codetools_0.2-18 viridisLite_0.4.0
## [46] future_1.23.0 fansi_0.5.0 crayon_1.4.2
## [49] withr_2.4.2 ModelMetrics_1.2.2.2 MASS_7.3-54
## [52] recipes_0.1.17 grid_4.1.2 nlme_3.1-153
## [55] jsonlite_1.7.2.9000 gtable_0.3.0 lifecycle_1.0.1
## [58] DBI_1.1.1 pROC_1.18.0 scales_1.1.1
## [61] future.apply_1.8.1 stringi_1.7.6 farver_2.1.0
## [64] timeDate_3043.102 bslib_0.3.1 ellipsis_0.3.2
## [67] generics_0.1.1 vctrs_0.3.8 lava_1.6.10
## [70] iterators_1.0.13 tools_4.1.2 glue_1.5.0
## [73] purrr_0.3.4 parallel_4.1.2 fastmap_1.1.0
## [76] survival_3.2-13 yaml_2.2.1 colorspace_2.0-2
## [79] knitr_1.36 sass_0.4.0
```