<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Copyright 2018 The TensorFlow Authors.
Step1:  ビジュアルアテンションを用いた画像キャプショニング
<table class="tfo-notebook-buttons" align="left">
  <td>     <a target="_blank" href="https
Step2:  MS-COCO データセットのダウンロードと準備
MS-COCO データセットを使用してモデルをトレーニングします。データセットには 82,000 を超える画像が含まれており、各画像には少なくとも 5 つの異なるキャプション注釈があります。以下のコードは、データセットを自動的にダウンロードして抽出します。
注意
Step3:  オプション
Step4:  InceptionV3 を使った画像の前処理
つぎに、（Imagenet を使って訓練済みの）InceptionV3をつかって、画像を分類します。最後の畳み込み層から特徴量を抽出します。
最初に、以下のように画像を InceptionV3 が期待する形式に変換します。
画像を 299 ピクセル × 299 ピクセルにリサイズ
preprocess_input メソッドを使って画像の前処理を行います。画像を InceptionV3 のトレーニング用画像の形式に合うように −1 から 1 の範囲のピクセルを持つ形式に正規化します。
Step5:  InceptionV3 を初期化し Imagenet で学習済みの重みをロードする
次に、出力レイヤーが InceptionV3 アーキテクチャの最後の畳み込みレイヤーである tf.keras モデルを作成します。このレイヤーの出力の形状は 8x8x2048 です。この例ではアテンションを使用しているため、最後の畳み込みレイヤーを使用します。ボトルネックになる可能性があるため、トレーニング中にこの初期化は実行しません。
画像を 1 枚ずつネットワークに送り込み、処理結果のベクトルをディクショナリに保管します (image_name --&gt; feature_vector)
すべての画像がネットワークに渡された後、ディクショナリをディスクに保存します。
Step6:  InceptionV3 から抽出した特徴量をキャッシュする
それぞれの画像を InceptionV3 で前処理し、出力をディスクにキャッシュします。出力を RAM にキャッシュすれば速くなりますが、画像 1 枚あたり 8 * 8 * 2048 個の浮動小数点数が必要で、メモリを大量に必要とします。本チュートリアルの執筆時点では、これは Colab のメモリ上限  (現在は 12GB) を超えています。
より高度なキャッシング戦略（たとえば画像を分散保存しディスクのランダムアクセス入出力を低減するなど）を使えば性能は向上しますが、より多くのコーディングが必要となります。
このキャッシングは Colab で GPU を使った場合で約 10 分ほどかかります。プログレスバーを表示したければ次のようにします。
tqdm をインストールする。
!pip install tqdm
tqdm をインポートします
Step7:  キャプションの前処理とトークン化
次の手順で、TextVectorization レイヤーを使用して、テキストキャプションを整数シーケンスに変換します。
adapt を使用して、すべてのキャプションを反復処理し、キャプションを単語に分割し、上位 5,000 語の語彙を計算します（メモリを節約するため）。
各単語を語彙のインデックスにマッピングして、すべてのキャプションをトークン化します。すべての出力シーケンスは、長さ 50 までパディングされます。
結果を表示するために、単語からインデックスおよびインデックスから単語へのマッピングを作成します。
Step8:  データを訓練用とテスト用に分割
Step9:  訓練用の tf.data データセットの作成
画像とキャプションの準備ができました！次に、モデルのトレーニングに使用する tf.data データセットを作成します。
Step10:  モデル
興味深い事実
Step11:  チェックポイント
Step12:  訓練
それぞれの .npy ファイルに保存されている特徴量を取り出し、エンコーダに渡す
エンコーダの出力、(0 で初期化された) 隠れ状態と、デコーダの入力 (開始トークン) をデコーダに渡します。
デコーダは予測値とデコーダの隠れ状態を返す
デコーダの隠れ状態はモデルに戻され、予測値をつかって損失を計算する
デコーダの次の入力を決めるために teacher forcing を用いる
Teacher forcing は、デコーダの次の入力として正解の単語を渡す手法である
最後のステップは、勾配を計算してそれをオプティマイザに適用し誤差逆伝播を行うことである
Step13:  キャプション！
評価関数はトレーニングループと似ていますが、教師強制 (teacher forcing) は使われません。時間ステップごとのデコーダへの入力は、隠れ状態とエンコーダの出力に加えて、一つ前の予測値です。
モデルが終了トークンを予測したら、予測を終了する。
それぞれの時間ステップごとに、アテンションの重みを保存します。
Step14:  あなた独自の画像でためそう
トレーニングしたばかりのモデルで独自の画像にキャプションを付ける方法を以下に示します。比較的少量のデータでトレーニングされているので、使用する画像がトレーニングデータと異なることがあることに注意してください (奇妙な結果がでるかもしれません！)
<ASSISTANT_TASK:>
Python Code:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Explanation: Copyright 2018 The TensorFlow Authors.
End of explanation
import tensorflow as tf
# You'll generate plots of attention in order to see which parts of an image
# your 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
Explanation: ビジュアルアテンションを用いた画像キャプショニング
<table class="tfo-notebook-buttons" align="left">
  <td>     <a target="_blank" href="https://www.tensorflow.org/tutorials/text/image_captioning">     <img src="https://www.tensorflow.org/images/tf_logo_32px.png">     TensorFlow.org で表示</a>
</td>
  <td>     <a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/tutorials/text/image_captioning.ipynb"><img src="https://www.tensorflow.org/images/colab_logo_32px.png">Google Colab で実行</a>
</td>
  <td>     <a target="_blank" href="https://github.com/tensorflow/docs-l10n/blob/master/site/ja/tutorials/text/image_captioning.ipynb">     <img src="https://www.tensorflow.org/images/GitHub-Mark-32px.png">     GitHub でソースを表示</a>
</td>
  <td><a href="https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ja/tutorials/text/image_captioning.ipynb"><img src="https://www.tensorflow.org/images/download_logo_32px.png"> ノートブックをダウンロード</a></td>
</table>
以下の例のような画像が与えられた場合、目標は「波に乗っているサーファー」などのキャプションを生成することです。
画像ソース; ライセンス: パブリックドメイン
これを達成するため、アテンションベースのモデルを用います。これにより、キャプションを生成する際にモデルが画像のどの部分に焦点を当てているかを見ることができます。
モデルの構造は、Show, Attend and Tell: Neural Image Caption Generation with Visual Attention と類似のものです。
このノートブックには例として、最初から最後までの一連の処理が含まれています。このノートブックを実行すると、MS-COCO データセットをダウンロードし、Inception V3 を使って画像のサブセットを前処理し、キャッシュします。その後、エンコーダー・デコーダーモデルをトレーニングし、トレーニングしたモデルを使って新しい画像のキャプションを生成します。
この例では、比較的少量のデータ、およそ 20,000 枚の画像に対する最初の 30,000 のキャプションを使ってモデルをトレーニングします (データセットには 1 枚の画像あたり複数のキャプションがあります)。
End of explanation
# 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
Explanation: MS-COCO データセットのダウンロードと準備
MS-COCO データセットを使用してモデルをトレーニングします。データセットには 82,000 を超える画像が含まれており、各画像には少なくとも 5 つの異なるキャプション注釈があります。以下のコードは、データセットを自動的にダウンロードして抽出します。
注意: 容量の大きいファイルをダウンロードします。トレーニング用のデータセットは、13GB のファイルです。
End of explanation
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))
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])
Explanation: オプション: トレーニング用データセットのサイズ制限
このチュートリアルではトレーニングをスピードアップするために、30,000 個のキャプションのサブセットとそれに対応する画像を使用して、モデルをトレーニングします。より多くのデータを使用することを選択すると、キャプションの品質が向上します。
End of explanation
def load_image(image_path):
    img = tf.io.read_file(image_path)
    img = tf.io.decode_jpeg(img, channels=3)
    img = tf.keras.layers.Resizing(299, 299)(img)
    img = tf.keras.applications.inception_v3.preprocess_input(img)
    return img, image_path
Explanation: InceptionV3 を使った画像の前処理
つぎに、（Imagenet を使って訓練済みの）InceptionV3をつかって、画像を分類します。最後の畳み込み層から特徴量を抽出します。
最初に、以下のように画像を InceptionV3 が期待する形式に変換します。
画像を 299 ピクセル × 299 ピクセルにリサイズ
preprocess_input メソッドを使って画像の前処理を行います。画像を InceptionV3 のトレーニング用画像の形式に合うように −1 から 1 の範囲のピクセルを持つ形式に正規化します。
End of explanation
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)
Explanation: InceptionV3 を初期化し Imagenet で学習済みの重みをロードする
次に、出力レイヤーが InceptionV3 アーキテクチャの最後の畳み込みレイヤーである tf.keras モデルを作成します。このレイヤーの出力の形状は 8x8x2048 です。この例ではアテンションを使用しているため、最後の畳み込みレイヤーを使用します。ボトルネックになる可能性があるため、トレーニング中にこの初期化は実行しません。
画像を 1 枚ずつネットワークに送り込み、処理結果のベクトルをディクショナリに保管します (image_name --&gt; feature_vector)
すべての画像がネットワークに渡された後、ディクショナリをディスクに保存します。
End of explanation
# 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())
Explanation: InceptionV3 から抽出した特徴量をキャッシュする
それぞれの画像を InceptionV3 で前処理し、出力をディスクにキャッシュします。出力を RAM にキャッシュすれば速くなりますが、画像 1 枚あたり 8 * 8 * 2048 個の浮動小数点数が必要で、メモリを大量に必要とします。本チュートリアルの執筆時点では、これは Colab のメモリ上限  (現在は 12GB) を超えています。
より高度なキャッシング戦略（たとえば画像を分散保存しディスクのランダムアクセス入出力を低減するなど）を使えば性能は向上しますが、より多くのコーディングが必要となります。
このキャッシングは Colab で GPU を使った場合で約 10 分ほどかかります。プログレスバーを表示したければ次のようにします。
tqdm をインストールする。
!pip install tqdm
tqdm をインポートします:
from tqdm import tqdm
下記の行を:
for img, path in image_dataset:
次のように変更します:
for img, path in tqdm(image_dataset):
End of explanation
caption_dataset = tf.data.Dataset.from_tensor_slices(train_captions)
# We will override the default standardization of TextVectorization to preserve
# "<>" characters, so we preserve the tokens for the <start> and <end>.
def standardize(inputs):
  inputs = tf.strings.lower(inputs)
  return tf.strings.regex_replace(inputs,
                                  r"!\"#$%&\(\)\*\+.,-/:;=?@\[\\\]^_`{|}~", "")
# Max word count for a caption.
max_length = 50
# Use the top 5000 words for a vocabulary.
vocabulary_size = 5000
tokenizer = tf.keras.layers.TextVectorization(
    max_tokens=vocabulary_size,
    standardize=standardize,
    output_sequence_length=max_length)
# Learn the vocabulary from the caption data.
tokenizer.adapt(caption_dataset)
# Create the tokenized vectors
cap_vector = caption_dataset.map(lambda x: tokenizer(x))
# Create mappings for words to indices and indicies to words.
word_to_index = tf.keras.layers.StringLookup(
    mask_token="",
    vocabulary=tokenizer.get_vocabulary())
index_to_word = tf.keras.layers.StringLookup(
    mask_token="",
    vocabulary=tokenizer.get_vocabulary(),
    invert=True)
Explanation: キャプションの前処理とトークン化
次の手順で、TextVectorization レイヤーを使用して、テキストキャプションを整数シーケンスに変換します。
adapt を使用して、すべてのキャプションを反復処理し、キャプションを単語に分割し、上位 5,000 語の語彙を計算します（メモリを節約するため）。
各単語を語彙のインデックスにマッピングして、すべてのキャプションをトークン化します。すべての出力シーケンスは、長さ 50 までパディングされます。
結果を表示するために、単語からインデックスおよびインデックスから単語へのマッピングを作成します。
End of explanation
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)
Explanation: データを訓練用とテスト用に分割
End of explanation
# Feel free to change these parameters according to your system's configuration
BATCH_SIZE = 64
BUFFER_SIZE = 1000
embedding_dim = 256
units = 512
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.int64]),
          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)
Explanation: 訓練用の tf.data データセットの作成
画像とキャプションの準備ができました！次に、モデルのトレーニングに使用する tf.data データセットを作成します。
End of explanation
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, tokenizer.vocabulary_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_)
Explanation: モデル
興味深い事実: 下記のデコーダは Neural Machine Translation with Attention の例のデコーダとまったく同一です。
このモデルのアーキテクチャは、Show, Attend and Tell の論文にインスパイアされたものです。
この例では、InceptionV3 の下層の畳み込みレイヤーから特徴量を取り出します。得られるベクトルの形状は (8, 8, 2048) です。
このベクトルを (64, 2048) に変形します。
このベクトルは (1 層の全結合レイヤーからなる) CNN エンコーダに渡されます。
RNN（ここではGRU）が画像を介して次の単語を予測します。
End of explanation
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)
Explanation: チェックポイント
End of explanation
# 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([word_to_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')
plt.plot(loss_plot)
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Loss Plot')
plt.show()
Explanation: 訓練
それぞれの .npy ファイルに保存されている特徴量を取り出し、エンコーダに渡す
エンコーダの出力、(0 で初期化された) 隠れ状態と、デコーダの入力 (開始トークン) をデコーダに渡します。
デコーダは予測値とデコーダの隠れ状態を返す
デコーダの隠れ状態はモデルに戻され、予測値をつかって損失を計算する
デコーダの次の入力を決めるために teacher forcing を用いる
Teacher forcing は、デコーダの次の入力として正解の単語を渡す手法である
最後のステップは、勾配を計算してそれをオプティマイザに適用し誤差逆伝播を行うことである
End of explanation
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([word_to_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()
        predicted_word = tf.compat.as_text(index_to_word(predicted_id).numpy())
        result.append(predicted_word)
        if predicted_word == '<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(int(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([tf.compat.as_text(index_to_word(i).numpy())
                         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)
Explanation: キャプション！
評価関数はトレーニングループと似ていますが、教師強制 (teacher forcing) は使われません。時間ステップごとのデコーダへの入力は、隠れ状態とエンコーダの出力に加えて、一つ前の予測値です。
モデルが終了トークンを予測したら、予測を終了する。
それぞれの時間ステップごとに、アテンションの重みを保存します。
End of explanation
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)
Explanation: あなた独自の画像でためそう
トレーニングしたばかりのモデルで独自の画像にキャプションを付ける方法を以下に示します。比較的少量のデータでトレーニングされているので、使用する画像がトレーニングデータと異なることがあることに注意してください (奇妙な結果がでるかもしれません！)
End of explanation
<END_TASK>