Mô hình LSTM

Một phần của tài liệu chú thích ảnh tự động dựa trên cnn, rnn và lstm (Trang 40)

Mô hình LSTM là một bước đột phá đạt được từ mô hình RNN. Nó giải quyết triệt để vấn đề không xử lý được câu hỏi dài mà những mô hình khác đang gặp phải.

Hình 1.23 Mô hình LSTM Networks. [13]

Ở hình 1.36, mỗi một đường mang một véc-tơ từ đầu ra của một nút tới đầu vào của một nút khác. Các hình trong màu hồng biểu diễn các phép toán như: phép cộng véc-tơ, phép nhân véc-tơ, … còn các ô màu vàng được sử dụng để học trong các từng mạng nơ-ron. Các đường hợp nhau kí hiệu việc kết hợp, còn các đường rẽ nhánh chỉ

nội dung của nó được sao chép và chuyển tới các nơi khác nhau.

LSTM cung cấp nhiều khả năng kiểm soát và do đó, kết quả tốt hơn. Nhưng cũng đi kèm với sự phức tạp và chi phí hoạt động nhiều hơn.

29

2CHƯƠNG 2. BÀI TOÁN CHÚ THÍCH ẢNH TỰ ĐỘNG DỰA TRÊN CNN,

RNN & LSTM 2.1 Xác định bài toán.

• Input: Ảnh

Hình ảnh đưa vào có thể được trích xuất từ camera, video, webcam hoặc từ các thiết bị như máy ảnh, smart phone, …

• Output: Văn bản hoặc giọng nói với nhiều ngôn ngữ.

Dữ liệu ra là văn bản và giọng nói với nhiều ngôn ngữ khác nhau như: Tiếng việt, tiếng anh, tiếng pháp, tiếng nhật, …

2.2 Ý tưởng bài toán.

Với Input là ảnh thường được trích xuất đặc trưng (extract feature) qua pre- trained model với dataset lớn như ImageNet và model phổ biến như Darknet, VGG16, ResNet, quá trình được gọi là embedding và output là một 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.

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 ta 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

Hình 2.1 Mô hình chú thích ảnh của bài toán

Để 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à 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.

30

Sau khi đưa ra chú thích, chúng ta sử dụng tiện ích text to speech (TTS) để chuyển từ văn bản sang giọng nói.

2.3 Tiến trình thực hiện bài toán:

2.3.1 Phát hiện đối tượng (Object detection).

Đầu vào là một ảnh, đối với bài toán phát hiện đối tượng (object detection), ta không chỉ phải phân loại được đối tượng (object) trên bức ảnh mà còn phải định vị được vị trí của đối tượng đó.

Để giải quyết bài toán object detection, ta chia ảnh thành nhiều hộp (box), mỗi box sẽ phát hiện đối tượng trong box đó. Vị trí của đối tượng chính là tọa độ của box đó. Thay vì chia thành từng box, ta sẽ sử dụng thuật toán để lựa chọn những khu vực ứng viên, các vùng ứng viên này có thể tưởng như là những vùng liên thông với nhau trên kênh màu RGB, sau đó với mỗi vùng ứng viên này, ta dùng model để phân loại object. Trong bài toán này chúng tôi sử dụng mô hình YOLOv3 để phát hiện đối tượng trong ảnh.

Phát hiện đối tượng với Yolov3 bằng Karas

Các bước thực hiện phát hiện đối tượng với Yolov3.

Bước 1: Nhập các thư viện

import numpy as np

from numpy import expand_dims

from keras.models import load_model, Model from

keras.preprocessing.image import load_img from

keras.preprocessing.image import img_to_array from

matplotlib import pyplot

from matplotlib.patches import Rectangle

Bước 2: Tạo một Class WeightReader để tải tệp weights đã được huấn luyện trước cho yolov3.

Lớp WeightReader sẽ phân tích cú pháp tệp và tải trọng số (Weights) mô hình vào bộ nhớ để đặt nó trong mô hình Keras.

Chúng ta cần xác định một mô hình Keras có số lượng và loại lớp thích hợp để phù hợp với trọng lượng mô hình đã tải xuống. Kiến trúc mô hình được gọi là

DarkNet ” và ban đầu được dựa trên mô hình VGG-16.

Chúng ta cần tải các trọng số của mô hình. Trọng số mô hình được lưu trữ ở bất kỳ định dạng nào được DarkNet sử dụng. Sử dụng lớp WeightReader được cung cấp trong tập lệnh.

Bước 3: Tạo mô hình Yolov3

#creating the YOLO model

def make_yolov3_model():

input_image = Input(shape=(None, None, 3))

# Layer 0 => 4

x = _conv_block(input_image, [{'filter': 32, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 0}, {'filter': 64, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 1},{'filter': 32, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 2},{'filter': 64, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 3}])

# Tạo các Layer từ 5 => 98.

# Layer 99 => 106

yolo_106 = _conv_block(x, [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky':

True, 'layer_idx': 99},

{'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 100}, {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 101}, {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 102}, {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 103}, {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 104},

{'filter': 255, 'kernel': 1, 'stride': 1, 'bnorm': False, 'leaky': False, 'layer_idx': 105}], skip=False)model = Model(input_image, [yolo_82, yolo_94, yolo_106]) return model

Bước 4: Tạo mô hình yolo và tải các trọng lượng đã được huấn luyện trước (pre-trained weights).

# tạo yolo v3

yolov3 = make_yolov3_model ()

# tải các trọng lượng được đào tạo trên Flickr vào mô hình weight_reader = WeightReader ('yolov3.weights')

weight_reader.load_weights (yolov3)

Bước 5: Giá trị của các biến.

Các siêu tham số và giá trị dùng cài đặt trong mô hình YOLOv3 của bài toán.

32

Bước 6: Tải hình ảnh vào đúng hình dạng đầu vào là 460x460 from numpy import expand_dims def load_image_pixels (filename, shape) : # tải hình ảnh để có hình dạng

image = load_img (filename) width, height = image.size

# tải hình ảnh với kích thước yêu cầu

image = load_img (tên tệp, target_size = shape)

#convert to numpy array image = img_to_array (image)

#scale pixel value to [0, 1] image = image.astype ('float32') image / = 255.0

#thêm kích thước để chúng ta có một hình ảnh mẫu = expand_dims (image , 0)

Bước 7: Tạo lớp cho hộp giới hạn

class BoundBox:

def __init__(self, xmin, ymin, xmax, ymax, objness=None, classes=None):

self.xmin = xmin self.ymin = ymin

33 self.xmax = xmax self.ymax = ymax self.objness = objness self.classes = classes self.label = -1 self.score = -1

Bước 8: Xác định các chức năng của:

• Interval overlap

• Intersection over Union(IoU) của hai hộp.

• Non-Max Suppression

• Hàm Sigmoid

def _sigmoid(x):

return 1. / (1. + np.exp(-x))def _interval_overlap(interval_a, interval_b):

x1, x2 = interval_a x3, x4 = interval_bif x3 < x1: if x4 < x1: return 0 else: return min(x2,x4) — x1 else: if x2 < x3: return 0 else: return min(x2,x4) — x3

Bước 9: Giải mã đầu ra (out put) của mạng.

def decode_netout(netout, anchors, obj_thresh, net_h, net_w): grid_h, grid_w = netout.shape[:2]

nb_box = 3

netout = netout.reshape((grid_h, grid_w, nb_box, -1)) nb_class = netout.shape[-1] - 5

boxes = []

netout[..., :2] = _sigmoid(netout[..., :2]) netout[..., 4:] = _sigmoid(netout[..., 4:])

netout[..., 5:] = netout[..., 4][..., np.newaxis] * netout[..., 5:] netout[..., 5:] *= netout[..., 5:] > obj_thresh

for i in range(grid_h * grid_w): row = i / grid_w

col = i % grid_w

for b in range(nb_box):

#4th element is objectness score objectness

= netout[int(row)][int(col)][b][4] if

(objectness.all() <= obj_thresh): continue

# first 4 elements are x, y, w, and h

x, y, w, h = netout[int(row)][int(col)][b][:4]

x = (col + x) / grid_w # center position, unit: image width

y = (row + y) / grid_h # center position, unit: image height

w = anchors[2 * b + 0] * np.exp(w) / net_w # unit: image width

h = anchors[2 * b + 1] * np.exp(h) / net_h # unit: image height

#last elements are class

probabilities classes =

netout[int(row)][col][b][5:]

box = BoundBox(x - w / 2, y - h / 2, x + w / 2, y + h / 2, objectness, classes)

boxes.append(box)

return boxes

Bước 10: Sửa lỗi các hộp Yolov3.

Các hộp giới hạn cần được kéo dài trở lại hình dạng của hình ảnh ban đầu. Điều này

sẽ cho phép vẽ hình ảnh gốc và vẽ các hộp giới hạn, phát hiện các đối tượng thực.

def correct_yolo_boxes(boxes, image_h, image_w, net_h, net_w): new_w, new_h = net_w, net_h

for i in range(len(boxes)):

x_offset, x_scale = (net_w - new_w) / 2. / net_w, float(new_w) / net_w

y_offset, y_scale = (net_h - new_h) / 2. / net_h, float(new_h) / net_h boxes[i].xmin = int((boxes[i].xmin - x_offset) / x_scale * image_w) boxes[i].xmax = int((boxes[i].xmax - x_offset) / x_scale * image_w) boxes[i].ymin = int((boxes[i].ymin - y_offset) / y_scale * image_h) boxes[i].ymax = int((boxes[i].ymax - y_offset) / y_scale * image_h)

Bước 11: Nhận tất cả các hộp trên ngưỡng quy định.

Hàm get_boxes lấy danh sách các hộp, nhãn và ngưỡng làm đối số và trả về danh sách song song các hộp, nhãn và điểm số.

def get_boxes(boxes, labels, thresh):

v_boxes, v_labels, v_scores = list(), list(), list()

# enumerate all boxes

for box in boxes:

#enumerate all possible

labels for i in

#check if the threshold for this label is high

enough if box.classes[i] > thresh:

v_boxes.append(box) v_labels.append(labels[i])

v_scores.append(box.classes[i] * 100)

# don't break, many labels may trigger for one

box return v_boxes, v_labels, v_scores

Bước 12: Vẽ một hộp màu trắng xung quanh các đối tượng trong hình.

def draw_boxes(filename, v_boxes, v_labels, v_scores):

# load the image

data = pyplot.imread(filename)

#plot the image

pyplot.imshow(data )

#get the context for drawing

boxes ax = pyplot.gca()

# plot each box

for i in range(len(v_boxes)): box = v_boxes[i]

# get coordinates

y1, x1, y2, x2 = box.ymin, box.xmin, box.ymax, box.xmax

#calculate width and height of the

box width, height = x2 - x1, y2 - y1

# create the shape

rect = Rectangle((x1, y1), width, height, fill=False, color='white')

#draw the box

ax.add_patch(rect)

# draw text and score in top left corner

label = "%s (%.3f)" % (v_labels[i], v_scores[i])

pyplot.text(x1, y1, label, bbox=dict(facecolor='green', alpha=0.8))

# show the plot

# pyplot.figure(figsize=(12,9))

pyplot.axis('off')

pyplot.savefig(filename[:-4] + '_detected' + filename[-4:], pad_inches=0, bbox_inches='tight', transparent=True)

# pyplot.show()

pyplot.clf()

return filename[7:-4] + '_detected' + filename[-4:]

2.3.2 Chú thích hình ảnh (Image Captioning).

2.3.2.1 Cài đặt thư viện học sâu Keras và TensorFlow.

Bước 1: Cài đặt Python với môi trường ảo. Bước 2: Cài đặt TensorFlow.

Bước 3: Cài đặt Keras.

Bước 4: Xác minh rằng tệp keras.json được cấu hình đúng. Bước 5: Liên kết Sym trong OpenCV.

Bước 6: Kiểm tra cài đặt Keras + TensorFlow.

2.3.2.2 Xử lý hình ảnh

Hình ảnh đầu vào (X) cho mô hình được đưa ra dưới dạng một vectơ. Chúng ta cần chuyển đổi mọi hình ảnh thành một vectơ có kích thước cố định, sau đó có thể được cung cấp làm đầu vào cho mạng thần kinh CNN. Chúng ta lựa chọn học chuyển bằng cách sử dụng mô hình InceptionV3 (Mạng thần kinh chuyển đổi) do Google Research tạo ra.

Sử dụng InceptionV3 (được huấn luyện trước trên imagenet) để phân loại hình ảnh. Ta sẽ trích xuất đặc trưng từ convolutional layer cuối cùng.

Đầu tiên, ta chuyển đổi hình ảnh vào InceptionV3 với định dạng 299px x 299 px. Tiếp theo ta chuẩn hóa hình ảnh sao cho nó chứa các pixel trong phạm vi từ -1 đến 1, phù hợp với định dạng của hình ảnh được sử dụng để huấn luyện InceptionV3.

def preprocess(image_path):

img = image.load_img(image_path, target_size=(299, 299)) x = image.img_to_array(img)

x = np.expand_dims(x, axis=0)

x = preprocess_input(x)

return x

Khởi tạo InceptionV3 và tải trọng số Imagenet được đào tạo trước

Ta tạo một mô hình tf.keras trong đó lớp đầu ra là convolutional layer cuối cùng trong kiến trúc InceptionV3.

def get_encode_img_model():

model = InceptionV3(weights=DATA_PATH +

'/inception_v3_weights_tf_dim_ordering_tf_kernels.h5') new_input = model.input

new_output = model.layers[-2].output model_new = Model(new_input, new_output) print('Encode image model loaded')

return model_new

37

Ta sẽ xử lý trước mỗi hình ảnh với InceptionV3 và lưu đầu ra vào đĩa.

2.3.2.3 Xử lý văn bản (Text)

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 chú thích. 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 chú thích.

2.3.2.4 Kiến trúc mô hình:

• Ta trích xuất các tính năng từ lớp Xoắnthấp hơn của InceptionV3 cho chúng ta một vectơ hình dạng (8, 8, 2048).

• Từ hình dạng (8, 8, 2048) ta chuyển thành một vectơ hình dạng (64,

2048).

• Vectơ này sau đó được chuyển qua Bộ mã hóa CNN (bao gồm một lớp

được kết nối đầy đủ).

• Dùng RNN để dự đoán từ tiếp theo.

Mô hình hình ảnh:

Hình ảnh đã mã hóa từ lớp fully connected của mô hình từ 2048 chiều xuống 300 chiều.

Hình 2.2 Mô hình hình ảnh

Mô hình ngôn ngữ:

Là một véc-tơ được chuyển đổi thành embeding véc-tơ và sau đó chuyển qua LSTM hai chiều.

38

Hình 2.3 Mô hình ngôn ngữ

Mô hình hình ảnh và mô hình ngôn ngữ sau đó được hợp nhất và chuyển qua một LSTM hai chiều khác để tạo ra một vectơ kích thước từ vựng. Giá trị xác suất cao nhất của vectơ từ vựng là từ dự đoán tiếp theo.

Mô hình bài toán:

Hình 2.4 Mô hình bài toán:

Mô hình các lớp:

Hình 2.5 Mô hình các lớp

Giá trị các siêu tham số của mô hình.

2.3.3 CHUYỂN VĂN BẢN THÀNH GIỌNG NÓI (TEXT TO SPEECH)

Để chuyển văn bản thành giọng nói, chúng ta sử dụng một số thư viện có sẳn trong Python như: Pyttsx3, gTTS, …

• Pyttsx3 là một thư viện chuyển đổi văn bản thành giọng nói trong Python. Nó sử dụng các công cụ nói khác nhau dựa trên hệ điều hành của bạn.

40

• gTTS là một mô đun dùng để lưu văn bản nói thành tập tin âm thanh mp3. gTTS sử dụng Google Text to Speech (TTS) API . Cài đặt các modul như sau:

from gtts import gTTS

from googletrans import Translator

AUDIO_PATH = 'static/'

def get_tts(text, image_name):

audio_url = 'audios/' + image_name[7:-4] + '.mp3' tts = gTTS(text)

tts.save(AUDIO_PATH + audio_url)

return audio_url

def get_tts_translate(text, image_name,language = 'en'):

audio_url = 'audios/' + image_name[7:-4] + '_' + language +

'_.mp3'

translator = Translator()

translation_text = translator.translate(text, dest=language) print(translation_text)

#tts = gTTS(text,lang=language, slow=False)

tts = gTTS(translation_text.text, lang=language, slow=False) tts.save(AUDIO_PATH + audio_url)

return audio_url,translation_text.text

3 CHƯƠNG 3: THỰC NGHIỆM MÔ HÌNH

Chương này tiến hành thực nghiệm mô hình chú thích ảnh tự động bằng cách sử dụng CNN, RNN, LSTM. Mô tả về dữ liệu thực nghiệm cũng như công cụ sử dụng trong hệ thống.

3.1 DỮ LIỆU VÀ CÔNG CỤ THỰC NGHIỆM3.1.1 Dữ liệu: 3.1.1 Dữ liệu:

Dữ liệu dùng trong luận văn là Flickr8k. Dữ liệu gồm 8000 ảnh, 6000 ảnh cho traning set, 1000 cho dev set (validation set) và 1000 ảnh cho test set. Khi 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 .

Hình 3.1 Ảnh trong Flickr8k

42

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.

3.1.2 Công cụ sử dụng:

Trong luận văn này để thử nghiệm được mô hình chúng tôi đã kết hợp sử dụng các thư viện mã nguồn mở và các công cụ có sẵn để xử lý dữ liệu, huấn luyện mô hình và dự báo.

Tesnorflow là một thư viện nguồn mở để phát triển các ứng dụng học máy. Các ứng dụng này được thực hiện bằng cách sử dụng các đồ thị để tổ chức dòng chảy của các hoạt động và các bộ tensors để đại diện cho dữ liệu. Nó cung cấp một giao diện lập trình ứng dụng (API) trong Python, cũng như một bộ các hàm thấp hơn được thực hiện bằng cách sử dụng C ++. Nó cung cấp một bộ các tính năng để cho phép nhanh hơn mẫu và thực hiện các mô hình học máy và các ứng dụng cho các nền tảng điện toán không đồng nhất cao.

Python là một ngôn ngữ lập trình thông dịch (interpreted), hướng đối tượng (object-oriented), và là một ngôn ngữ bậc cao (high-level) ngữ nghĩa động (dynamic semantics). Python hỗ trợ các module và gói (packages), khuyến khích chương trình module hóa và tái sử dụng mã. Trình thông dịch Python và thư viện chuẩn mở rộng có sẵn dưới dạng mã nguồn miễn phí cho tất cả.

3.2 THỰC NGHIỆM

3.2.1 Cài đặt thực nghiệm mô hình.

Khai báo các thư viện cần thiết (Keras, TensorFlow).

from keras.preprocessing import sequence from keras.models import Sequential import numpy as np

import pandas as pd import pickle

from keras.preprocessing import image import keras

from keras import backend

from keras.models import load_model import time

from PIL import Image

from flask import Flask, request import tensorflow as tf

import os

Input dữ liệu hình ảnh Flickr, tạo tệp trainimgs.txt và testimages.txt

token_dir = DataPath+ "Flickr8k_text/Flickr8k.token.txt" image_captions = open(token_dir).read().split('\n')

caption = {}

for i in range(len(image_captions)-1): id_capt = image_captions[i].split("\t") id_capt[0] = id_capt[0][:len(id_capt[0])-

2] # to rip off the #0,#1,#2,#3,#4 from the tokens file if id_capt[0] in caption:

caption[id_capt[0]].append(id_capt[1]) else:

caption[id_capt[0]] = [id_capt[1]]

Một phần của tài liệu chú thích ảnh tự động dựa trên cnn, rnn và lstm (Trang 40)

Tải bản đầy đủ (DOCX)

(77 trang)
w