Bài 15: Ứng dụng thêm mô tả cho ảnh (image captioning)
Ở những bài trước mình đã giới thiệu về mô hình Recurrent Neural Network (RNN) cho bài toán dữ liệu dạng chuỗi. Tuy nhiên RNN chỉ có short term memory và bị vanishing gradient. Tiếp đó mình đã giới thiệu về Long short term memory (LSTM) có cả short term memory và long term memory, hơn thế nữa tránh được vaninishing gradient. Bài này mình sẽ viết về ứng dụng của LSTM cho ứng dụng image captioning.
Bài viết được tham khảo từ đây.
Nội dung
Ứng dụng
Ta có thể thấy ngay 2 ứng dụng của image captioning:
- Để giúp những người già mắt kém hoặc người mù có thể biết được cảnh vật xung quanh hay hỗ trợ việc di chuyển. Quy trình sẽ là: Image -> text -> voice.
- Giúp google search có thể tìm kiếm được hình ảnh dựa vào caption.
Dataset
Dữ liệu dùng trong bài này là Flickr8k Dataset. Mọi người tải ở đây. Dữ liệu gồm 8000 ảnh, 6000 ảnh cho traning set, 1000 cho dev set (validation set) và 1000 ảnh cho test set.
Bạn tải về có 2 folder: Flicker8k_Dataset và Flicker8k_Text. Flicker8k_Dataset chứa các ảnh với tên là các id khác nhau. Flicker8k_Text chứa:
- Flickr_8k.testImages, Flickr_8k.devImages, Flickr_8k.trainImages, Flickr_8k.devImages chứa id các ảnh dùng cho việc test, train, validation.
- Flickr8k.token chứa các caption của ảnh, mỗi ảnh chứa 5 captions
Ví dụ ảnh dưới có 5 captions:
- A child in a pink dress is climbing up a set of stairs in an entry way.
- A girl going into a wooden building .
- A little girl climbing into a wooden playhouse .
- A little girl climbing the stairs to her playhouse .
- A little girl in a pink dress going into a wooden cabin .
Thực ra 1 ảnh nhiều caption cũng hợp lý vì bức ảnh có thể được mô tả theo nhiều cách khác nhau. Một ảnh 5 caption sẽ cho ra 5 traning set khác nhau: (ảnh, caption 1), (ảnh, caption 2), (ảnh, caption 3), (ảnh, caption 4), (ảnh, caption 5). Như vậy traning set sẽ có 6000 * 5 =40000 dataset.
Phân tích bài toán
Input là ảnh và output là text, ví dụ “man in black shirt is playing guitar”.
Nhìn chung các mô hình machine learning hay deep learning đều không xử lý trực tiếp với text như ‘man’, ‘in’, ‘black’,… mà thường phải quy đổi (encode) về dạng số. Từng từ sẽ được encode sang dạng vector với độ dài số định, phương pháp đấy gọi là word embedding. Để hiểu rõ hơn về word embedding mọi người xem thêm ở đây (bài tiếng việt giải thích rất chi tiết).
Nhìn thấy output là text nghĩ ngay đến RNN và sử dụng mô hình LSTM.
Input là ảnh thường được extract feature qua pre-trained model với dataset lớn như ImageNet và model phổ biến như VGG16, ResNet, quá trình được gọi là embedding và output là 1 vector.
Ý tưởng sẽ là dùng embedding của ảnh và dùng các từ phía trước để dự đoán từ tiếp theo trong caption.
Ví dụ:
- Embedding vector + A -> girl
- Embedding vector + A girl -> going
- Embedding vector + A girl going -> into
- Embedding vector + A girl going into -> a.
- Embedding vector + A girl going into a -> wooden building .
- Embedding vector + A girl going into a wooden -> building .
Để dự đoán từ tiếp theo ta sẽ xây dựng từ điển các từ xuất hiện trong training set (ví dụ 2000 từ) và bài toán trở thành bài toán phân loại từ, xem từ tiếp theo là từ nào, khá giống như bài phân loại ảnh.
Các bước chi tiết
Image embedding với Inception
Có lẽ cái tên GoogLeNet sẽ quen thuộc hơn và gặp nhiều hơn so với Inception, GoogLeNet là version 1 của Inception, hiện giờ mô hình phổ biến là Inception v3.
Thay vì trong mỗi Conv layer chỉ dùng 1 kernel size nhất định như 3*3, 5*5, thì giờ ở một layer có nhiều kernel size khác nhau, do đó mô hình có thể học được nhiều thuộc tính khác nhau của ảnh trong mỗi layer.
Cụ thể hơn mọi người xem thêm ở đây.
Ta sẽ sử dụng pre-trained model Inception v3 với dataset Imagenet. Do là pre-trained model yêu cầu ảnh đầu vào là 229*229 nên ra sẽ resize ảnh về kích thước này. Sau khi qua pre-trained model ta sẽ lấy được embedding vector của ảnh, kích thước 256*1
Text preprocessing
Ta xử lý text qua một số bước cơ bản.
- Chuyển chữ hoa thành chữ thường, “Hello” -> “hello”
- Bỏ các kí tự đặc biệt như “%”, “$”, “#”
- Loại bỏ các chữ có số như hey199
Sau đó ta sẽ thêm 2 từ “startseq” và “endseq” để biểu thị sự bắt đầu và kết thúc của caption. Ví dụ: “startseq a girl going into a wooden building endseq“. “endseq” dùng khi test ảnh thì biết kết thúc của caption.
Ta thấy có 8763 chữ khác nhau trong số 40000 caption. Tuy nhiên ta không quan tâm lắm những từ mà chỉ xuất hiện 1 vài lần, vì nó giống như là nhiễu vậy và không tốt cho việc học và dự đoán từ của model, nên ta chỉ giữ lại những từ mà xuất hiện trên 10 lần trong số tất cả các caption. Sau khi bỏ những từ xuất hiện ít hơn 10 lần ta còn 1651 từ.
Tuy nhiên do độ dài các sequence khác nhau, ví dụ: “A”, ” A girl going”, ” A girl going into a wooden”, nên ta cần padding thêm để các chuỗi có cùng độ dài bằng với độ dài của chuỗi dài nhất là 34. Do đó số tổng số từ (từ điển) ta có là 1651 + 1 (từ dùng để padding).
Word embedding
Pre-trained GLOVE Model được sử dụng cho quá trình word embedding.
Mọi người vào link này để tải file glove.6B.zip
Từng dòng trong file sẽ lưu text và encoded vector khích thước 200*1
Output
Bài toán là dự đoán từ tiếp theo trong chuỗi ở input với ảnh hiện tại, nên output là từ nào trong số 1652 từ trong từ điển mà ta có. Với bài toán phân loại thì softmax activation và categorical_crossentropy loss function được sử dụng.
Model
Layer (type) Output Shape Param # Connected to ================================================================================================== input_3 (InputLayer) (None, 34) 0 __________________________________________________________________________________________________ input_2 (InputLayer) (None, 2048) 0 __________________________________________________________________________________________________ embedding_1 (Embedding) (None, 34, 200) 330400 input_3[0][0] __________________________________________________________________________________________________ dropout_1 (Dropout) (None, 2048) 0 input_2[0][0] __________________________________________________________________________________________________ dropout_2 (Dropout) (None, 34, 200) 0 embedding_1[0][0] __________________________________________________________________________________________________ dense_1 (Dense) (None, 256) 524544 dropout_1[0][0] __________________________________________________________________________________________________ lstm_1 (LSTM) (None, 256) 467968 dropout_2[0][0] __________________________________________________________________________________________________ add_1 (Add) (None, 256) 0 dense_1[0][0] lstm_1[0][0] __________________________________________________________________________________________________ dense_2 (Dense) (None, 256) 65792 add_1[0][0] __________________________________________________________________________________________________ dense_3 (Dense) (None, 1652) 424564 dense_2[0][0] ================================================================================================== Total params: 1,813,268 Trainable params: 1,813,268 Non-trainable params: 0