1 Lịch sử ra đời

Thuật toán khởi nguồn của Deep Learning là Neural Network đã ra đời từ năm 1943, tức khoảng hơn 70 năm trước và trải qua rất nhiều năm thăng trầm phát triển thì hiện nay Deep Learning đang là một trong những từ khóa hot nhất trong lĩnh vực công nghệ AI (Antificial Intelligence) hiện nay.

Một trong những nền móng đầu tiên của Deep Learning phải kể đến như là:

  • Perception (1960s): tuy nhiên thuật toán này được chứng minh là không thể giải quyết tốt các bài toán khi so sánh với các thuật toàn thời bấy giờ và việc nghiên cứu gần như bị gián đoạn khoảng 20 năm và được coi là thời kì ngủ đông lần thứ nhất của Deep Learning

  • Multi Layer Perceptron và Backpropagation (1980s): một vài bước tiến ra đời trong thời gian này và điển hình là Neural Network với nhiều hidden layers. Thuật toán này mang lại một vài bước tiến thành công ban đầu với Convolutional Neural Network sử dụng trong image classification. Tuy nhiên, thời kì này máy tính chưa thực sự phát triển cộng với máy tính thời gian này chưa thực sự phát triển và máy ảnh số chưa phổ biến khiến cho việc training một mô hình CNN cần rất nhiều training dataset cũng như tốn rất nhiều thời gian. Thời gian này nổi lên một thuật toán có khả năng xử lý rất hiệu quả các hạn chế của Deep Learning là Support Vector Machine. Rất nhiều nhà khoa học đã chuyển qua nghiên cứu thuật toán này trong khoảng thời gian này khiến cho việc nghiên cứu về Deep Learning trải qua một thời kì ngủ đông lần thứ hai

  • Đột phá (2012): Lần đầu tiên thuật toán Deep Learning đã chiến thắng trong cuộc thi phân loại ảnh với kết quả khác biệt hoàn toàn với với các thuật toán khác làm sững sờ giới nghiên cứu về Machine Learning thời bấy giờ. Rất nhiều kĩ thuật mới đã được ra đời trong đó nổi bật nhất là hàm activation Reactified Linear Unit đã giải quyết cực kì hiệu quả các vấn đề gặp phải của Deep Learning trong thời gian trước đó và Dropout, Batch, Pooling là kĩ thuật xử lý vấn đề về Overfitting. Một trong những yếu tố quan trọng trong việc sử dụng thành công Deep Learning đó chính là công nghệ về máy tính đã lên một tầng cao mới khi một máy tính với RAM 16GB, 32GB không còn là vấn đề nữa cũng như việc sử dụng GPU trong việc training mô hình giúp tăng tốc độ thuật toán lên rất nhiều lần so với CPU. Chính bước ngoặt đó đã mở ra kỉ nguyên của Deep Learning khi tất cả các mô hình đoạt giải trong năm tiếp theo đều sử dụng Deep Learning

Bài viết hôm nay tôi sẽ giới thiệu về Convolutional Neural Network và ví dụ về cách sử dụng trên R

2 Convolutional Neural Network (CNN)là gì?

Các công ty công nghệ lớn như Google, Facebook, Amazon đang sử dụng CNN cho hệ thống xử lý nhận diện ảnh và có chức năng như nhận diện khuôn mặt người dùng, phát triển xe tự lái, v.v … Một trong những ứng dụng không xa lạ với người dùng Facebook hiện nay đó chính là nhận diện chính xác người nào có trong bước ảnh sau khi đăng lên hoặc khi search từ khóa là Iron man thì hệ thống Google sẽ tự nhận diện các ảnh có gắn nhãn Iron man để đưa ra kết quả

2.1 Convolution là gì?

Mỗi bức ảnh đều có các điểm ảnh nhất định được hiểu là các ma trận ảnh. Convolution layer được học để điều chỉnh lấy ra những thông tin chính xác mà không cần chọn ra các feature. Điều này được thực hiện bằng cách chia nhỏ bước ảnh thành các ma trận nhỏ hơn (Sliding Window) rồi nhân với một ma trận được gọi là Filter hoặc Feature Detect. Kết quả là một ma trận Convoled Feature

2.2 Cấu trúc mạng CNN

Mạng CNN là một tập hợp các lớp Convolution chồng lên nhau và sử dụng các hàm nonlinear activation như ReLU và tanh để kích hoạt các trọng số trong các node. Mỗi một lớp sau khi thông qua các hàm kích hoạt sẽ tạo ra các thông tin trừu tượng hơn cho các lớp tiếp theo. Mỗi một lớp sau khi thông qua các hàm kích hoạt sẽ tạo ra các thông tin trừu tượng hơn cho các lớp tiếp theo. Còn trong mô hình CNNs thì ngược lại. Các layer liên kết được với nhau thông qua cơ chế convolution. Layer tiếp theo là kết quả convolution từ layer trước đó, nhờ vậy mà ta có được các kết nối cục bộ. Như vậy mỗi neuron ở lớp kế tiếp sinh ra từ kết quả của filter áp đặt lên một vùng ảnh cục bộ của neuron trước đó.

Mỗi một lớp được sử dụng các filter khác nhau thông thường có hàng trăm hàng nghìn filter như vậy và kết hợp kết quả của chúng lại. Ngoài ra có một số layer khác như pooling/subsampling layer dùng để chắt lọc lại các thông tin hữu ích hơn (loại bỏ các thông tin nhiễu). Trong quá trình huấn luyện mạng (traning) CNN tự động học các giá trị qua các lớp filter dựa vào cách thức mà bạn thực hiện.

2.3 Các parameter trong CNN

  • Convolutional layer: số lượng layers được sử dụng trong mạng CNN

  • Pooling: Lớp pooling thường được sử dụng ngay sau lớp convolational để đơn giản hóa thông tin đầu ra để giảm bớt số lượng neuron. Pooling phổ biến là max-pooling, thủ tục này chọn giá trị lớn nhất trong vùng đầu vào 2x2. Như vậy qua lớp Max Pooling thì số lượng neuron giảm đi phân nửa. Trong một mạng CNN có nhiều Feature Map nên mỗi Feature Map chúng ta sẽ cho mỗi Max Pooling khác nhau. Chúng ta có thể thấy rằng Max Pooling là cách hỏi xem trong các đặc trưng này thì đặc trưng nào là đặc trưng nhất. Ngoài Max Pooling còn có L2 Pooling. Cuối cùng ta đặt tất cả các lớp lại với nhau thành một CNN với đầu ra gồm các neuron với số lượng tùy bài toán. 2 lớp cuối cùng của các kết nối trong mạng là một lớp đầy đủ kết nối (fully connected layer). Lớp này nối mọi nơron từ lớp max pooled tới mọi nơron của tầng ra. Pooling parameter được chọn thường là 2x2

  • Filter size: thường là ma trận 3x3 hoặc 5x5

  • Epochs: số lượng chu kì lặp đi lặp lại của CNN

  • Batch: để cải thiện việc tính toán trong CNN, ta sẽ dùng phương pháp chia nhỏ các hình ảnh ban đầu thành nhóm nhỏ hơn

3 Xử lý bài toán phân loại hình ảnh

Để áp dụng mô hình CNN trong phân loại hình ảnh, chúng ta sẽ sử dụng data \(cats and dogs\) trong cuộc thi trên Kaggle. Data cats and dogs bao gồm 25000 ảnh bao gồm 12500 dog và 12500 ảnh cats. Tuy nhiên, do việc run mô hình trên cả 25000 ảnh này sẽ tốn rất nhiều thời gian nên trong bài viết này mình chỉ lấy ngãu nhiên 2000 ảnh của dogs và cats cho tập train, 1500 cho tập test và 1500 ảnh cho tập validation. Hãy bắt đầu ngay bây giờ nào:

3.1 Bước 1: Tạo các đường dẫn đến các thư mục train, test và validation

library(keras)
library(dplyr)

original_dataset_dir <- "D:/R WORK/2. DEEP LEARNING/train"
base_dir <- "D:/R WORK/2. DEEP LEARNING/cats_and_dogs_small"

dir.create(base_dir)

train_dir <- file.path(base_dir, "train")
dir.create(train_dir)

validation_dir <- file.path(base_dir, "validation")
dir.create(validation_dir)

test_dir <- file.path(base_dir, "test")
dir.create(test_dir)

train_cats_dir <- file.path(train_dir, "cats")
dir.create(train_cats_dir)

train_dogs_dir <- file.path(train_dir, "dogs")
dir.create(train_dogs_dir)

validation_cats_dir <- file.path(validation_dir, "cats")
dir.create(validation_cats_dir)

validation_dogs_dir <- file.path(validation_dir, "dogs")
dir.create(validation_dogs_dir)

test_cats_dir <- file.path(test_dir, "cats")
dir.create(test_cats_dir)

test_dogs_dir <- file.path(test_dir, "dogs")
dir.create(test_dogs_dir)

3.2 Bước 2: Copy những file ảnh từ file gốc để đưa vào thư mục nhỏ hơn

fnames <- paste0("cat.", 1:1000, ".jpg")
file.copy(file.path(original_dataset_dir, fnames),
          file.path(train_cats_dir))
fnames <- paste0("cat.", 1001:1500, ".jpg")
file.copy(file.path(original_dataset_dir, fnames),
          file.path(validation_cats_dir))
fnames <- paste0("cat.", 1501:2000, ".jpg")
file.copy(file.path(original_dataset_dir, fnames),
          file.path(test_cats_dir))
fnames <- paste0("dog.", 1:1000, ".jpg")
file.copy(file.path(original_dataset_dir, fnames),
          file.path(train_dogs_dir))
fnames <- paste0("dog.", 1001:1500, ".jpg")
file.copy(file.path(original_dataset_dir, fnames),
          file.path(validation_dogs_dir))
fnames <- paste0("dog.", 1501:2000, ".jpg")
file.copy(file.path(original_dataset_dir, fnames),
          file.path(test_dogs_dir))

Chúng ta sẽ test xem trong folder có bao nhiêu ảnh

cat("total training cat images:", length(list.files(train_cats_dir)), "\n")
cat("total training dog images:", length(list.files(train_dogs_dir)), "\n")
cat("total validation cat images:", length(list.files(validation_cats_dir)), "\n")
cat("total validation dog images:", length(list.files(validation_dogs_dir)), "\n")
cat("total test cat images:", length(list.files(test_cats_dir)), "\n")
cat("total test dog images:", length(list.files(test_dogs_dir)), "\n")

3.3 Bước 3: Thiết kế các layers của model CNN.

Ở đây mình sẽ thiết kế mô hình bằng 4 convolution layers + max pooling nối tiếp nhau, kế theo fatten layer + dense layer. Tiếp đó mô hình sẽ được compile với hàm loss function là binary crossentropy với bài toán phân loại 2 classes, hàm opimizer là RMSPROP và tiêu chi huấn luận là Accuracy

model <- keras_model_sequential() %>%
  layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu",
                input_shape = c(150, 150, 3)) %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_conv_2d(filters = 128, kernel_size = c(3, 3), activation = "relu") %>%
  layer_max_pooling_2d(pool_size = c(2, 2)) %>%
  layer_flatten() %>%
  layer_dropout(rate = 0.5) %>%
  layer_dense(units = 512, activation = "relu") %>%
  layer_dense(units = 1, activation = "sigmoid")

model %>% compile(
  loss = "binary_crossentropy",
  optimizer = optimizer_rmsprop(lr = 1e-4),
  metrics = c("acc")
)

3.4 Bước 4: Resize ảnh và data augmentation

Resize các bức ảnh về dạng 150:150. Ngoài ra do lượng ảnh chúng ta cho vào mô hình khá bé nên sẽ cần sử dụng phương pháp data augmentation để tạo thêm các bức ảnh mới. Bước làm như vậy sẽ giúp giảm thiểu overfiting của mô hình

datagen <- image_data_generator(
  rescale = 1/255,
  rotation_range = 40,
  width_shift_range = 0.2,
  height_shift_range = 0.2,
  shear_range = 0.2,
  zoom_range = 0.2,
  horizontal_flip = TRUE
)

test_datagen <- image_data_generator(rescale = 1/255)
train_generator <- flow_images_from_directory(
  train_dir,
  datagen,
  target_size = c(150, 150),
  batch_size = 32,
  class_mode = "binary"
)
validation_generator <- flow_images_from_directory(
  validation_dir,
  test_datagen,
  target_size = c(150, 150),
  batch_size = 32,
  class_mode = "binary"
)

3.5 Bước 5: Run model

Ta có thể thấy với epochs = 30 thì mô hình đang tốt dần lên với accuracy đạt được tầm 78% trên tập validation. Trên thực tế nếu ta đặt epochs = 100 thì mô hình sẽ có accuracy lên đến 87% trên tập validation. TUy nhiên do việc train rất tốn thời gian (khoảng nửa ngày nên mô hình này sẽ chỉ dừng ở epochs = 30 thôi)

history <- model %>% fit_generator(
  train_generator,
  steps_per_epoch = 100,
  epochs = 30,
  validation_data = validation_generator,
  validation_steps = 50
)
model %>% save_model_hdf5("D:/R WORK/2. DEEP LEARNING/model/cats_and_dogs_small_2.h5")
load(file = "D:/R WORK/2. DEEP LEARNING/model/seft_train.Rda")
library(ggplot2)
library(reshape2)
library(dplyr)
df <- data.frame(acc = history$metrics$acc,
                 val_acc = history$metrics$val_acc,
                 epochs = c(1:30))
df1 <- df %>% 
  select(3,1,2) %>% 
  melt(id.vars = "epochs")

df1 %>% 
  ggplot(aes(x = epochs, y = value, col = variable)) +
  geom_line() +
  geom_point() +
  scale_x_continuous(breaks = seq(0,30,5)) +
  theme_bw()