Bài viết dưới đây sẽ demo một ứng dụng nhỏ của deep learning trong việc đọc các con số. Tập dữ liệu được sử dụng là mnist. Đây là bộ dữ liệu hình ảnh của gần 70 nghìn các con số khác nhau khá quen thuộc với các ví dụ phân tích về machine learning.

Package chúng ta sử dụng trong bài phân tích này là keras, một thư viện chuyên dùng trong deeplearning của python và đã được kế thừa sang R. Khi bạn cài thư viện này trên R nếu gặp trục trặc do missing package thì rất có thể python chưa được cài keras và các gói phụ trợ. Do đó cần quay trở lại màn hình command line gõ lệnh pip install packageName để cài bổ sung cho python.

rm(list = ls())
library(keras)
mnist <- dataset_mnist()
train_images <- mnist$train$x
train_labels <- mnist$train$y
test_images <- mnist$test$x 
test_labels <- mnist$test$y

Các images đã được encode dưới dạng 3D arrays và labels của image dưới dạng 1D arrays

str(train_images)
##  int [1:60000, 1:28, 1:28] 0 0 0 0 0 0 0 0 0 0 ...
str(train_labels)
##  int [1:60000(1d)] 5 0 4 1 9 2 1 3 1 4 ...

Bản chất của các định dạng này là tensor, một kiểu dữ liệu có thể biểu diễn các không gian n chiều bằng những không gian n-1 chiều nhằm hỗ trợ tính toán được dễ dàng hơn.

Build network dựa trên train_data

network <- keras_model_sequential() %>% 
  layer_dense(units = 52, activation = "relu", input_shape = c(28*28)) %>% 
  layer_dense(units = 10, activation = "softmax")

Compile network vừa tạo

network %>% compile(  optimizer = "rmsprop",  
                      loss = "categorical_crossentropy",  
                      metrics = c("accuracy") )

Chức năng complile này sẽ có tác dụng điều chỉnh mạng tại chỗ chứ không tạo ra một object mới như thông thường trong R. Bởi thế nên bạn có thể thấy network không được save đè lên nó hoặc một biến mới.

reshape lại array thành matrix được mã hóa dưới dạng nhị phân 0,1

train_images <- array_reshape(train_images, c(60000,28*28))
train_images <- train_images / 255

test_images <- array_reshape(test_images, c(10000,28*28)) 
test_images <- test_images / 255

chuyển sang dạng categorical các encode label để sử dụng trong training model.

train_labels <- to_categorical(train_labels) 
test_labels <- to_categorical(test_labels)

training model

set.seed(123)
history <- network %>% fit(train_images, train_labels, 
                epochs=5, 
                batch_size = 128)
plot(history)

khi chúng ta gọi vào fit function, mạng network sẽ bắt đầu vòng lặp với các mini-batch có kích cỡ 128 (batch_size = 128) và số vòng lặp sẽ là 5 lần tổng cộng (epochs = 5). Sau mỗi bước lặp, network sẽ tính toán lại gradient descent của weight để tối ưu hóa các hàm loss trên từng batch. Sau tổng cộng 5 epochs network sẽ trải qua 5*469=2345 lần update các gradient descent (mỗi epoch là 469 lần) để loss của network sẽ đủ nhỏ nhằm nâng cao độ chính xác của model trong phân loại các chữ số.

Trên đồ thị chúng ta có thể thấy loss và acc tỷ lệ nghịch với nhau có ý nghĩa rằng lượng thông tin bị mất đi càng ít thì mức độ chính xác càng cao.

Sử dụng network vừa tạo để dự báo trên tập test

set.seed(1)
metrics <- network %>% evaluate(test_images, test_labels)
metrics
## $loss
## [1] 0.1240839
## 
## $acc
## [1] 0.964

Tỷ lệ dự báo chính xác trên tập test chỉ là 96.4% thấp hơn một chút so với trên tập train. Đây là điều dễ hiểu vì các model machine-learning thường có xu hướng dự báo kém hơn trên những tập dữ liệu mới.

Dự̣ báo kết quả cho 10 số đầu tiên trên tập test:

network %>% predict_classes(test_images[1:10,])
##  [1] 7 2 1 0 4 1 4 9 6 9

Hình ảnh thực tế của các số này

test_images <- mnist$test$x 
par(mfrow=c(2,5),mar=c(rep(0.1,4)))
for (i in 1:10){
  digit <- test_images[i,,]
  plot(as.raster(digit, max = 255))
}

Như vậy chúng ta đã hoàn thành một module xử lý hình ảnh bằng thư viện keras với kết quả dự báo chuẩn xác khá cao. Tuy nhiên đây mới chỉ là model trên lý thuyết. Để xử lý được các hình ảnh bất kì ngoài thực tế thì:

Note: Tài liệu và thông tin bài viết được tham khảo từ cuốn deep learning with R của tác giả francois

https://www.amazon.com/Deep-Learning-R-Francois-Chollet/dp/161729554X