Xem bài phát biểu, phiên sản phẩm, hội thảo, v.v. từ Google I / O Xem danh sách phát

Chú thích hình ảnh với sự chú ý trực quan

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Với một hình ảnh như ví dụ bên dưới, mục tiêu của chúng tôi là tạo ra một chú thích chẳng hạn như "một người lướt ván đang cưỡi trên con sóng".

Người đàn ông lướt sóng

Nguồn ảnh ; Giấy phép: Miền công cộng

Để thực hiện điều này, bạn sẽ sử dụng mô hình dựa trên sự chú ý, cho phép chúng tôi xem những phần nào của hình ảnh mà mô hình tập trung vào khi tạo chú thích.

Sự dự đoán

Kiến trúc mô hình tương tự như Show, Attend and Tell: Neural Image Caption Generation with Visual Attention .

Sổ tay này là một ví dụ từ đầu đến cuối. Khi bạn chạy sổ ghi chép, nó sẽ tải xuống tập dữ liệu MS-COCO , xử lý trước và lưu vào bộ nhớ cache một tập hợp con các hình ảnh bằng Inception V3, đào tạo mô hình bộ mã hóa-giải mã và tạo phụ đề cho các hình ảnh mới bằng mô hình được đào tạo.

Trong ví dụ này, bạn sẽ đào tạo một mô hình trên một lượng dữ liệu tương đối nhỏ — 30.000 phụ đề đầu tiên cho khoảng 20.000 hình ảnh (vì có nhiều phụ đề cho mỗi hình ảnh trong tập dữ liệu).

import tensorflow as tf

# You'll generate plots of attention in order to see which parts of an image
# our model focuses on during captioning
import matplotlib.pyplot as plt

import collections
import random
import numpy as np
import os
import time
import json
from PIL import Image

Tải xuống và chuẩn bị tập dữ liệu MS-COCO

Bạn sẽ sử dụng tập dữ liệu MS-COCO để đào tạo mô hình của chúng tôi. Tập dữ liệu chứa hơn 82.000 hình ảnh, mỗi hình ảnh có ít nhất 5 chú thích phụ đề khác nhau. Đoạn mã dưới đây tải xuống và trích xuất tập dữ liệu tự động.

# Download caption annotation files
annotation_folder = '/annotations/'
if not os.path.exists(os.path.abspath('.') + annotation_folder):
  annotation_zip = tf.keras.utils.get_file('captions.zip',
                                           cache_subdir=os.path.abspath('.'),
                                           origin='http://images.cocodataset.org/annotations/annotations_trainval2014.zip',
                                           extract=True)
  annotation_file = os.path.dirname(annotation_zip)+'/annotations/captions_train2014.json'
  os.remove(annotation_zip)

# Download image files
image_folder = '/train2014/'
if not os.path.exists(os.path.abspath('.') + image_folder):
  image_zip = tf.keras.utils.get_file('train2014.zip',
                                      cache_subdir=os.path.abspath('.'),
                                      origin='http://images.cocodataset.org/zips/train2014.zip',
                                      extract=True)
  PATH = os.path.dirname(image_zip) + image_folder
  os.remove(image_zip)
else:
  PATH = os.path.abspath('.') + image_folder
Downloading data from http://images.cocodataset.org/annotations/annotations_trainval2014.zip
252878848/252872794 [==============================] - 16s 0us/step
Downloading data from http://images.cocodataset.org/zips/train2014.zip
13510574080/13510573713 [==============================] - 792s 0us/step

Tùy chọn: giới hạn kích thước của tập huấn luyện

Để tăng tốc đào tạo cho hướng dẫn này, bạn sẽ sử dụng một tập hợp con gồm 30.000 phụ đề và hình ảnh tương ứng của chúng để đào tạo mô hình của chúng tôi. Chọn sử dụng nhiều dữ liệu hơn sẽ dẫn đến chất lượng phụ đề được cải thiện.

with open(annotation_file, 'r') as f:
    annotations = json.load(f)
# Group all captions together having the same image ID.
image_path_to_caption = collections.defaultdict(list)
for val in annotations['annotations']:
  caption = f"<start> {val['caption']} <end>"
  image_path = PATH + 'COCO_train2014_' + '%012d.jpg' % (val['image_id'])
  image_path_to_caption[image_path].append(caption)
image_paths = list(image_path_to_caption.keys())
random.shuffle(image_paths)

# Select the first 6000 image_paths from the shuffled set.
# Approximately each image id has 5 captions associated with it, so that will
# lead to 30,000 examples.
train_image_paths = image_paths[:6000]
print(len(train_image_paths))
6000
train_captions = []
img_name_vector = []

for image_path in train_image_paths:
  caption_list = image_path_to_caption[image_path]
  train_captions.extend(caption_list)
  img_name_vector.extend([image_path] * len(caption_list))
print(train_captions[0])
Image.open(img_name_vector[0])
<start> two brown bears lying together and relaxing on a rock <end>

png

Xử lý trước hình ảnh bằng InceptionV3

Tiếp theo, bạn sẽ sử dụng InceptionV3 (được đào tạo trước trên Imagenet) để phân loại từng ảnh. Bạn sẽ trích xuất các tính năng từ lớp phức hợp cuối cùng.

Đầu tiên, bạn sẽ chuyển đổi hình ảnh sang định dạng mong đợi của InceptionV3 bằng cách:

  • Thay đổi kích thước hình ảnh thành 299px x 299px
  • Xử lý trước hình ảnh bằng phương thức preprocess_input để 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 load_image(image_path):
    img = tf.io.read_file(image_path)
    img = tf.image.decode_jpeg(img, channels=3)
    img = tf.image.resize(img, (299, 299))
    img = tf.keras.applications.inception_v3.preprocess_input(img)
    return img, image_path

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

Bây giờ bạn sẽ tạo một mô hình tf.keras trong đó lớp đầu ra là lớp tích hợp cuối cùng trong kiến ​​trúc InceptionV3. Hình dạng của đầu ra của lớp này là 8x8x2048 . Bạn sử dụng lớp phức hợp cuối cùng vì bạn đang sử dụng sự chú ý trong ví dụ này. Bạn không thực hiện quá trình khởi tạo này trong quá trình đào tạo vì nó có thể trở thành một nút cổ chai.

  • Bạn chuyển tiếp từng hình ảnh qua mạng và lưu trữ vectơ kết quả trong một từ điển (image_name -> feature_vector).
  • Sau khi tất cả các hình ảnh được chuyển qua mạng, bạn lưu từ điển vào đĩa.
image_model = tf.keras.applications.InceptionV3(include_top=False,
                                                weights='imagenet')
new_input = image_model.input
hidden_layer = image_model.layers[-1].output

image_features_extract_model = tf.keras.Model(new_input, hidden_layer)
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/inception_v3/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5
87916544/87910968 [==============================] - 1s 0us/step

Lưu vào bộ đệm các tính năng được trích xuất từ ​​InceptionV3

Bạn sẽ xử lý trước mỗi hình ảnh với InceptionV3 và lưu đầu ra vào đĩa đệm. Lưu vào bộ nhớ đệm đầu ra trong RAM sẽ nhanh hơn nhưng cũng tốn nhiều bộ nhớ, yêu cầu 8 * 8 * 2048 float cho mỗi hình ảnh. Tại thời điểm viết bài, điều này vượt quá giới hạn bộ nhớ của Colab (bộ nhớ hiện tại là 12GB).

Hiệu suất có thể được cải thiện với chiến lược bộ nhớ đệm phức tạp hơn (ví dụ: bằng cách làm sắc nét hình ảnh để giảm I / O đĩa truy cập ngẫu nhiên), nhưng điều đó sẽ yêu cầu nhiều mã hơn.

Bộ nhớ đệm sẽ mất khoảng 10 phút để chạy trong Colab với GPU. Nếu bạn muốn xem thanh tiến trình, bạn có thể:

  1. cài đặt tqdm :

    !pip install -q tqdm

  2. Nhập tqdm:

    from tqdm import tqdm

  3. Thay đổi dòng sau:

    for img, path in image_dataset:

    đến:

    for img, path in tqdm(image_dataset):

# Get unique images
encode_train = sorted(set(img_name_vector))

# Feel free to change batch_size according to your system configuration
image_dataset = tf.data.Dataset.from_tensor_slices(encode_train)
image_dataset = image_dataset.map(
  load_image, num_parallel_calls=tf.data.AUTOTUNE).batch(16)

for img, path in image_dataset:
  batch_features = image_features_extract_model(img)
  batch_features = tf.reshape(batch_features,
                              (batch_features.shape[0], -1, batch_features.shape[3]))

  for bf, p in zip(batch_features, path):
    path_of_feature = p.numpy().decode("utf-8")
    np.save(path_of_feature, bf.numpy())

Xử lý trước và mã hóa các chú thích

  • Đầu tiên, bạn sẽ mã hóa các chú thích (ví dụ: bằng cách tách trên khoảng trắng). Điều này cung cấp cho chúng tôi vốn từ vựng về tất cả các từ duy nhất trong dữ liệu (ví dụ: "lướt sóng", "bóng đá", v.v.).
  • Tiếp theo, bạn sẽ giới hạn kích thước từ vựng ở 5.000 từ hàng đầu (để tiết kiệm bộ nhớ). Bạn sẽ thay thế tất cả các từ khác bằng mã thông báo "UNK" (không xác định).
  • Sau đó, bạn tạo ánh xạ từ-chỉ mục và chỉ mục-thành-từ.
  • Cuối cùng, bạn đệm tất cả các dãy có cùng độ dài với dãy dài nhất.
# Find the maximum length of any caption in our dataset
def calc_max_length(tensor):
    return max(len(t) for t in tensor)
# Choose the top 5000 words from the vocabulary
top_k = 5000
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=top_k,
                                                  oov_token="<unk>",
                                                  filters='!"#$%&()*+.,-/:;=?@[\]^_`{|}~ ')
tokenizer.fit_on_texts(train_captions)
tokenizer.word_index['<pad>'] = 0
tokenizer.index_word[0] = '<pad>'
# Create the tokenized vectors
train_seqs = tokenizer.texts_to_sequences(train_captions)
# Pad each vector to the max_length of the captions
# If you do not provide a max_length value, pad_sequences calculates it automatically
cap_vector = tf.keras.preprocessing.sequence.pad_sequences(train_seqs, padding='post')
# Calculates the max_length, which is used to store the attention weights
max_length = calc_max_length(train_seqs)

Chia dữ liệu thành đào tạo và thử nghiệm

img_to_cap_vector = collections.defaultdict(list)
for img, cap in zip(img_name_vector, cap_vector):
  img_to_cap_vector[img].append(cap)

# Create training and validation sets using an 80-20 split randomly.
img_keys = list(img_to_cap_vector.keys())
random.shuffle(img_keys)

slice_index = int(len(img_keys)*0.8)
img_name_train_keys, img_name_val_keys = img_keys[:slice_index], img_keys[slice_index:]

img_name_train = []
cap_train = []
for imgt in img_name_train_keys:
  capt_len = len(img_to_cap_vector[imgt])
  img_name_train.extend([imgt] * capt_len)
  cap_train.extend(img_to_cap_vector[imgt])

img_name_val = []
cap_val = []
for imgv in img_name_val_keys:
  capv_len = len(img_to_cap_vector[imgv])
  img_name_val.extend([imgv] * capv_len)
  cap_val.extend(img_to_cap_vector[imgv])
len(img_name_train), len(cap_train), len(img_name_val), len(cap_val)
(24011, 24011, 6001, 6001)

Tạo tập dữ liệu tf.data để đào tạo

Hình ảnh và chú thích của chúng tôi đã sẵn sàng! Tiếp theo, hãy tạo tập dữ liệu tf.data để sử dụng cho việc đào tạo mô hình của chúng tôi.

# Feel free to change these parameters according to your system's configuration

BATCH_SIZE = 64
BUFFER_SIZE = 1000
embedding_dim = 256
units = 512
vocab_size = top_k + 1
num_steps = len(img_name_train) // BATCH_SIZE
# Shape of the vector extracted from InceptionV3 is (64, 2048)
# These two variables represent that vector shape
features_shape = 2048
attention_features_shape = 64
# Load the numpy files
def map_func(img_name, cap):
  img_tensor = np.load(img_name.decode('utf-8')+'.npy')
  return img_tensor, cap
dataset = tf.data.Dataset.from_tensor_slices((img_name_train, cap_train))

# Use map to load the numpy files in parallel
dataset = dataset.map(lambda item1, item2: tf.numpy_function(
          map_func, [item1, item2], [tf.float32, tf.int32]),
          num_parallel_calls=tf.data.AUTOTUNE)

# Shuffle and batch
dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
dataset = dataset.prefetch(buffer_size=tf.data.AUTOTUNE)

Mô hình

Sự thật thú vị: bộ giải mã dưới đây giống với bộ giải mã trong ví dụ về Dịch máy thần kinh có chú ý .

Kiến trúc mô hình được lấy cảm hứng từ giấy Show, Attend và Tell .

  • Trong ví dụ này, bạn trích xuất các tính năng từ lớp tích tụ dưới của InceptionV3 cho chúng ta một vectơ có hình dạng (8, 8, 2048).
  • Bạn ép nó thành hình (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 đủ duy nhất).
  • RNN (ở đây là GRU) chú ý đến hình ảnh để dự đoán từ tiếp theo.
class BahdanauAttention(tf.keras.Model):
  def __init__(self, units):
    super(BahdanauAttention, self).__init__()
    self.W1 = tf.keras.layers.Dense(units)
    self.W2 = tf.keras.layers.Dense(units)
    self.V = tf.keras.layers.Dense(1)

  def call(self, features, hidden):
    # features(CNN_encoder output) shape == (batch_size, 64, embedding_dim)

    # hidden shape == (batch_size, hidden_size)
    # hidden_with_time_axis shape == (batch_size, 1, hidden_size)
    hidden_with_time_axis = tf.expand_dims(hidden, 1)

    # attention_hidden_layer shape == (batch_size, 64, units)
    attention_hidden_layer = (tf.nn.tanh(self.W1(features) +
                                         self.W2(hidden_with_time_axis)))

    # score shape == (batch_size, 64, 1)
    # This gives you an unnormalized score for each image feature.
    score = self.V(attention_hidden_layer)

    # attention_weights shape == (batch_size, 64, 1)
    attention_weights = tf.nn.softmax(score, axis=1)

    # context_vector shape after sum == (batch_size, hidden_size)
    context_vector = attention_weights * features
    context_vector = tf.reduce_sum(context_vector, axis=1)

    return context_vector, attention_weights
class CNN_Encoder(tf.keras.Model):
    # Since you have already extracted the features and dumped it
    # This encoder passes those features through a Fully connected layer
    def __init__(self, embedding_dim):
        super(CNN_Encoder, self).__init__()
        # shape after fc == (batch_size, 64, embedding_dim)
        self.fc = tf.keras.layers.Dense(embedding_dim)

    def call(self, x):
        x = self.fc(x)
        x = tf.nn.relu(x)
        return x
class RNN_Decoder(tf.keras.Model):
  def __init__(self, embedding_dim, units, vocab_size):
    super(RNN_Decoder, self).__init__()
    self.units = units

    self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)
    self.gru = tf.keras.layers.GRU(self.units,
                                   return_sequences=True,
                                   return_state=True,
                                   recurrent_initializer='glorot_uniform')
    self.fc1 = tf.keras.layers.Dense(self.units)
    self.fc2 = tf.keras.layers.Dense(vocab_size)

    self.attention = BahdanauAttention(self.units)

  def call(self, x, features, hidden):
    # defining attention as a separate model
    context_vector, attention_weights = self.attention(features, hidden)

    # x shape after passing through embedding == (batch_size, 1, embedding_dim)
    x = self.embedding(x)

    # x shape after concatenation == (batch_size, 1, embedding_dim + hidden_size)
    x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)

    # passing the concatenated vector to the GRU
    output, state = self.gru(x)

    # shape == (batch_size, max_length, hidden_size)
    x = self.fc1(output)

    # x shape == (batch_size * max_length, hidden_size)
    x = tf.reshape(x, (-1, x.shape[2]))

    # output shape == (batch_size * max_length, vocab)
    x = self.fc2(x)

    return x, state, attention_weights

  def reset_state(self, batch_size):
    return tf.zeros((batch_size, self.units))
encoder = CNN_Encoder(embedding_dim)
decoder = RNN_Decoder(embedding_dim, units, vocab_size)
optimizer = tf.keras.optimizers.Adam()
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(
    from_logits=True, reduction='none')


def loss_function(real, pred):
  mask = tf.math.logical_not(tf.math.equal(real, 0))
  loss_ = loss_object(real, pred)

  mask = tf.cast(mask, dtype=loss_.dtype)
  loss_ *= mask

  return tf.reduce_mean(loss_)

Trạm kiểm soát

checkpoint_path = "./checkpoints/train"
ckpt = tf.train.Checkpoint(encoder=encoder,
                           decoder=decoder,
                           optimizer=optimizer)
ckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=5)
start_epoch = 0
if ckpt_manager.latest_checkpoint:
  start_epoch = int(ckpt_manager.latest_checkpoint.split('-')[-1])
  # restoring the latest checkpoint in checkpoint_path
  ckpt.restore(ckpt_manager.latest_checkpoint)

Đào tạo

  • Bạn trích xuất các tính năng được lưu trữ trong các tệp .npy tương ứng và sau đó chuyển các tính năng đó qua bộ mã hóa.
  • Đầu ra của bộ mã hóa, trạng thái ẩn (được khởi tạo thành 0) và đầu vào của bộ giải mã (là mã thông báo bắt đầu) được chuyển đến bộ giải mã.
  • Bộ giải mã trả về các dự đoán và trạng thái ẩn bộ giải mã.
  • Trạng thái ẩn của bộ giải mã sau đó được chuyển trở lại mô hình và các dự đoán được sử dụng để tính toán tổn thất.
  • Sử dụng giáo viên buộc để quyết định đầu vào tiếp theo cho bộ giải mã.
  • Giáo viên ép buộc là kỹ thuật trong đó từ đích được chuyển làm đầu vào tiếp theo cho bộ giải mã.
  • Bước cuối cùng là tính toán các gradient và áp dụng nó vào trình tối ưu hóa và backpropagate.
# adding this in a separate cell because if you run the training cell
# many times, the loss_plot array will be reset
loss_plot = []
@tf.function
def train_step(img_tensor, target):
  loss = 0

  # initializing the hidden state for each batch
  # because the captions are not related from image to image
  hidden = decoder.reset_state(batch_size=target.shape[0])

  dec_input = tf.expand_dims([tokenizer.word_index['<start>']] * target.shape[0], 1)

  with tf.GradientTape() as tape:
      features = encoder(img_tensor)

      for i in range(1, target.shape[1]):
          # passing the features through the decoder
          predictions, hidden, _ = decoder(dec_input, features, hidden)

          loss += loss_function(target[:, i], predictions)

          # using teacher forcing
          dec_input = tf.expand_dims(target[:, i], 1)

  total_loss = (loss / int(target.shape[1]))

  trainable_variables = encoder.trainable_variables + decoder.trainable_variables

  gradients = tape.gradient(loss, trainable_variables)

  optimizer.apply_gradients(zip(gradients, trainable_variables))

  return loss, total_loss
EPOCHS = 20

for epoch in range(start_epoch, EPOCHS):
    start = time.time()
    total_loss = 0

    for (batch, (img_tensor, target)) in enumerate(dataset):
        batch_loss, t_loss = train_step(img_tensor, target)
        total_loss += t_loss

        if batch % 100 == 0:
            average_batch_loss = batch_loss.numpy()/int(target.shape[1])
            print(f'Epoch {epoch+1} Batch {batch} Loss {average_batch_loss:.4f}')
    # storing the epoch end loss value to plot later
    loss_plot.append(total_loss / num_steps)

    if epoch % 5 == 0:
      ckpt_manager.save()

    print(f'Epoch {epoch+1} Loss {total_loss/num_steps:.6f}')
    print(f'Time taken for 1 epoch {time.time()-start:.2f} sec\n')
Epoch 1 Batch 0 Loss 1.9253
Epoch 1 Batch 100 Loss 1.0291
Epoch 1 Batch 200 Loss 0.9413
Epoch 1 Batch 300 Loss 0.8769
Epoch 1 Loss 0.995607
Time taken for 1 epoch 132.04 sec

Epoch 2 Batch 0 Loss 0.8563
Epoch 2 Batch 100 Loss 0.7218
Epoch 2 Batch 200 Loss 0.7245
Epoch 2 Batch 300 Loss 0.8244
Epoch 2 Loss 0.757344
Time taken for 1 epoch 47.62 sec

Epoch 3 Batch 0 Loss 0.7345
Epoch 3 Batch 100 Loss 0.7220
Epoch 3 Batch 200 Loss 0.6223
Epoch 3 Batch 300 Loss 0.6888
Epoch 3 Loss 0.682421
Time taken for 1 epoch 47.19 sec

Epoch 4 Batch 0 Loss 0.6640
Epoch 4 Batch 100 Loss 0.5588
Epoch 4 Batch 200 Loss 0.6241
Epoch 4 Batch 300 Loss 0.6511
Epoch 4 Loss 0.634715
Time taken for 1 epoch 47.03 sec

Epoch 5 Batch 0 Loss 0.6118
Epoch 5 Batch 100 Loss 0.6183
Epoch 5 Batch 200 Loss 0.6742
Epoch 5 Batch 300 Loss 0.5720
Epoch 5 Loss 0.595271
Time taken for 1 epoch 48.29 sec

Epoch 6 Batch 0 Loss 0.6411
Epoch 6 Batch 100 Loss 0.5683
Epoch 6 Batch 200 Loss 0.5578
Epoch 6 Batch 300 Loss 0.5706
Epoch 6 Loss 0.562115
Time taken for 1 epoch 48.05 sec

Epoch 7 Batch 0 Loss 0.5801
Epoch 7 Batch 100 Loss 0.5177
Epoch 7 Batch 200 Loss 0.4892
Epoch 7 Batch 300 Loss 0.5099
Epoch 7 Loss 0.532225
Time taken for 1 epoch 47.26 sec

Epoch 8 Batch 0 Loss 0.5718
Epoch 8 Batch 100 Loss 0.5307
Epoch 8 Batch 200 Loss 0.4917
Epoch 8 Batch 300 Loss 0.5391
Epoch 8 Loss 0.504676
Time taken for 1 epoch 47.27 sec

Epoch 9 Batch 0 Loss 0.5103
Epoch 9 Batch 100 Loss 0.5037
Epoch 9 Batch 200 Loss 0.5306
Epoch 9 Batch 300 Loss 0.4305
Epoch 9 Loss 0.478346
Time taken for 1 epoch 47.07 sec

Epoch 10 Batch 0 Loss 0.4872
Epoch 10 Batch 100 Loss 0.4551
Epoch 10 Batch 200 Loss 0.4485
Epoch 10 Batch 300 Loss 0.4768
Epoch 10 Loss 0.455038
Time taken for 1 epoch 47.06 sec

Epoch 11 Batch 0 Loss 0.4802
Epoch 11 Batch 100 Loss 0.4332
Epoch 11 Batch 200 Loss 0.4093
Epoch 11 Batch 300 Loss 0.3760
Epoch 11 Loss 0.430722
Time taken for 1 epoch 47.48 sec

Epoch 12 Batch 0 Loss 0.4423
Epoch 12 Batch 100 Loss 0.4336
Epoch 12 Batch 200 Loss 0.3845
Epoch 12 Batch 300 Loss 0.4071
Epoch 12 Loss 0.409110
Time taken for 1 epoch 46.93 sec

Epoch 13 Batch 0 Loss 0.4196
Epoch 13 Batch 100 Loss 0.3909
Epoch 13 Batch 200 Loss 0.4037
Epoch 13 Batch 300 Loss 0.3795
Epoch 13 Loss 0.389614
Time taken for 1 epoch 47.15 sec

Epoch 14 Batch 0 Loss 0.4171
Epoch 14 Batch 100 Loss 0.4034
Epoch 14 Batch 200 Loss 0.3479
Epoch 14 Batch 300 Loss 0.3864
Epoch 14 Loss 0.368141
Time taken for 1 epoch 46.99 sec

Epoch 15 Batch 0 Loss 0.3634
Epoch 15 Batch 100 Loss 0.3302
Epoch 15 Batch 200 Loss 0.3254
Epoch 15 Batch 300 Loss 0.3207
Epoch 15 Loss 0.349797
Time taken for 1 epoch 47.52 sec

Epoch 16 Batch 0 Loss 0.3496
Epoch 16 Batch 100 Loss 0.3430
Epoch 16 Batch 200 Loss 0.3176
Epoch 16 Batch 300 Loss 0.3312
Epoch 16 Loss 0.333141
Time taken for 1 epoch 47.37 sec

Epoch 17 Batch 0 Loss 0.3340
Epoch 17 Batch 100 Loss 0.3199
Epoch 17 Batch 200 Loss 0.3235
Epoch 17 Batch 300 Loss 0.3129
Epoch 17 Loss 0.316967
Time taken for 1 epoch 46.89 sec

Epoch 18 Batch 0 Loss 0.3187
Epoch 18 Batch 100 Loss 0.3215
Epoch 18 Batch 200 Loss 0.2849
Epoch 18 Batch 300 Loss 0.2791
Epoch 18 Loss 0.301642
Time taken for 1 epoch 46.76 sec

Epoch 19 Batch 0 Loss 0.2936
Epoch 19 Batch 100 Loss 0.2945
Epoch 19 Batch 200 Loss 0.2915
Epoch 19 Batch 300 Loss 0.2920
Epoch 19 Loss 0.287884
Time taken for 1 epoch 46.66 sec

Epoch 20 Batch 0 Loss 0.2980
Epoch 20 Batch 100 Loss 0.3259
Epoch 20 Batch 200 Loss 0.2756
Epoch 20 Batch 300 Loss 0.2547
Epoch 20 Loss 0.281900
Time taken for 1 epoch 46.99 sec
plt.plot(loss_plot)
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Loss Plot')
plt.show()

png

Chú thích!

  • Chức năng đánh giá tương tự như vòng lặp đào tạo, ngoại trừ bạn không sử dụng giáo viên buộc ở đây. Đầu vào cho bộ giải mã tại mỗi bước thời gian là các dự đoán trước đó của nó cùng với trạng thái ẩn và đầu ra của bộ mã hóa.
  • Dừng dự đoán khi mô hình dự đoán mã thông báo kết thúc.
  • Và lưu trữ trọng số chú ý cho mỗi bước thời gian.
def evaluate(image):
    attention_plot = np.zeros((max_length, attention_features_shape))

    hidden = decoder.reset_state(batch_size=1)

    temp_input = tf.expand_dims(load_image(image)[0], 0)
    img_tensor_val = image_features_extract_model(temp_input)
    img_tensor_val = tf.reshape(img_tensor_val, (img_tensor_val.shape[0],
                                                 -1,
                                                 img_tensor_val.shape[3]))

    features = encoder(img_tensor_val)

    dec_input = tf.expand_dims([tokenizer.word_index['<start>']], 0)
    result = []

    for i in range(max_length):
        predictions, hidden, attention_weights = decoder(dec_input,
                                                         features,
                                                         hidden)

        attention_plot[i] = tf.reshape(attention_weights, (-1, )).numpy()

        predicted_id = tf.random.categorical(predictions, 1)[0][0].numpy()
        result.append(tokenizer.index_word[predicted_id])

        if tokenizer.index_word[predicted_id] == '<end>':
            return result, attention_plot

        dec_input = tf.expand_dims([predicted_id], 0)

    attention_plot = attention_plot[:len(result), :]
    return result, attention_plot
def plot_attention(image, result, attention_plot):
    temp_image = np.array(Image.open(image))

    fig = plt.figure(figsize=(10, 10))

    len_result = len(result)
    for i in range(len_result):
        temp_att = np.resize(attention_plot[i], (8, 8))
        grid_size = max(np.ceil(len_result/2), 2)
        ax = fig.add_subplot(grid_size, grid_size, i+1)
        ax.set_title(result[i])
        img = ax.imshow(temp_image)
        ax.imshow(temp_att, cmap='gray', alpha=0.6, extent=img.get_extent())

    plt.tight_layout()
    plt.show()
# captions on the validation set
rid = np.random.randint(0, len(img_name_val))
image = img_name_val[rid]
real_caption = ' '.join([tokenizer.index_word[i]
                        for i in cap_val[rid] if i not in [0]])
result, attention_plot = evaluate(image)

print('Real Caption:', real_caption)
print('Prediction Caption:', ' '.join(result))
plot_attention(image, result, attention_plot)
Real Caption: <start> several <unk> of bananas that are leaning against a building <end>
Prediction Caption: a number of bananas and some bananas and bananas <end>
/home/kbuilder/.local/lib/python3.7/site-packages/ipykernel_launcher.py:10: MatplotlibDeprecationWarning: Passing non-integers as three-element position specification is deprecated since 3.3 and will be removed two minor releases later.
  # Remove the CWD from sys.path while we load stuff.

png

Hãy thử nó trên hình ảnh của riêng bạn

Để giải trí, bên dưới chúng tôi đã cung cấp một phương pháp bạn có thể sử dụng để chú thích hình ảnh của chính mình với mô hình mà chúng tôi vừa đào tạo. Hãy nhớ rằng nó được đào tạo trên một lượng dữ liệu tương đối nhỏ và hình ảnh của bạn có thể khác với dữ liệu đào tạo (vì vậy hãy chuẩn bị cho những kết quả kỳ lạ!)

image_url = 'https://tensorflow.org/images/surf.jpg'
image_extension = image_url[-4:]
image_path = tf.keras.utils.get_file('image'+image_extension, origin=image_url)

result, attention_plot = evaluate(image_path)
print('Prediction Caption:', ' '.join(result))
plot_attention(image_path, result, attention_plot)
# opening the image
Image.open(image_path)
Downloading data from https://tensorflow.org/images/surf.jpg
65536/64400 [==============================] - 0s 4us/step
Prediction Caption: a man on a large wave on a surfboard <end>
/home/kbuilder/.local/lib/python3.7/site-packages/ipykernel_launcher.py:10: MatplotlibDeprecationWarning: Passing non-integers as three-element position specification is deprecated since 3.3 and will be removed two minor releases later.
  # Remove the CWD from sys.path while we load stuff.

png

png

Bước tiếp theo

Chúc mừng! Bạn vừa đào tạo một người mẫu chú thích hình ảnh một cách chú ý. Tiếp theo, hãy xem ví dụ này về Dịch máy thần kinh với sự chú ý . Nó sử dụng một kiến ​​trúc tương tự để dịch giữa các câu tiếng Tây Ban Nha và tiếng Anh. Bạn cũng có thể thử nghiệm việc đào tạo mã trong sổ ghi chép này trên một tập dữ liệu khác.