ヘルプKaggleにTensorFlowグレートバリアリーフを保護チャレンジに参加

言語理解のためのTransformerモデル

TensorFlow.orgで表示 GoogleColabで実行 GitHubでソースを表示ノートブックをダウンロード

このチュートリアルで列車はTransformerモデルを変換するポルトガル語、英語へのデータセットを。これは、の知識を前提と高度な例であるテキスト生成注意を

Transformerモデルの背後にある核となるアイデアは、その配列の表現を計算する入力シーケンスの異なる位置に出席するために-the能力自己注目です。変圧器は、自己の注目層のスタックを作成し、製品の注意マルチヘッドの注目ドットスケーリングのセクションで説明します。

代わりの自己注目層のスタックを用いて変圧器モデルハンドルの可変サイズ入力のRNN又はCNNsを。この一般的なアーキテクチャには、いくつかの利点があります。

  • データ全体の時間的/空間的関係については何も想定していません。これは、オブジェクトのセット(例えば、処理のために理想的であるスタークラフト単位)。
  • レイヤー出力は、RNNのような一連の出力ではなく、並列で計算できます。
  • 遠くの項目は、(参照、多くのRNN-段階、またはコンボリューション層を通過することなく、互いの出力に影響を与えることができますシーンメモリートランスなど)。
  • 長期的な依存関係を学習できます。これは、多くのシーケンスタスクでの課題です。

このアーキテクチャの欠点は次のとおりです。

  • 時系列のために、時間ステップの出力ではなく入力のみと現在の隠された状態の全体の履歴から計算されます。これはあまり効率的ではあります。
  • 入力は、時間的/空間的な関係を持っいる場合は、テキストのように、いくつかの位置エンコーディングが追加されなければならないか、モデルが効果的に言葉のバッグが表示されます。

このノートブックでモデルをトレーニングした後、ポルトガル語の文を入力して英語の翻訳を返すことができるようになります。

注意ヒートマップ

設定

pip install tensorflow_datasets
pip install -U tensorflow-text
import collections
import logging
import os
import pathlib
import re
import string
import sys
import time

import numpy as np
import matplotlib.pyplot as plt

import tensorflow_datasets as tfds
import tensorflow_text as text
import tensorflow as tf
logging.getLogger('tensorflow').setLevel(logging.ERROR)  # suppress warnings

データセットをダウンロードする

使用TensorFlowデータセットをロードするためにポルトガル語-英語の翻訳データセットからのTEDトークオープン翻訳プロジェクトを

このデータセットには、約50000のトレーニング例、1100の検証例、および2000のテスト例が含まれています。

examples, metadata = tfds.load('ted_hrlr_translate/pt_to_en', with_info=True,
                               as_supervised=True)
train_examples, val_examples = examples['train'], examples['validation']

tf.data.Datasetテキスト例のTensorFlowデータセット利回り対によって返されるオブジェクト:

for pt_examples, en_examples in train_examples.batch(3).take(1):
  for pt in pt_examples.numpy():
    print(pt.decode('utf-8'))

  print()

  for en in en_examples.numpy():
    print(en.decode('utf-8'))
e quando melhoramos a procura , tiramos a única vantagem da impressão , que é a serendipidade .
mas e se estes fatores fossem ativos ?
mas eles não tinham a curiosidade de me testar .

and when you improve searchability , you actually take away the one advantage of print , which is serendipity .
but what if it were active ?
but they did n't test for curiosity .

テキストのトークン化とトークン化解除

テキストでモデルを直接トレーニングすることはできません。最初に、テキストを数値表現に変換する必要があります。通常、テキストをトークンIDのシーケンスに変換します。これは、埋め込みへのインデックスとして使用されます。

1つの一般的な実装がで実証されたチュートリアルでは、トークナイザサブワードサブワードトークナイザ(ビルドをtext.BertTokenizerこのデータセットと、輸出、それらをするために最適化) saved_modelを

ダウンロードして解凍して、インポートsaved_model

model_name = "ted_hrlr_translate_pt_en_converter"
tf.keras.utils.get_file(
    f"{model_name}.zip",
    f"https://storage.googleapis.com/download.tensorflow.org/models/{model_name}.zip",
    cache_dir='.', cache_subdir='', extract=True
)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/models/ted_hrlr_translate_pt_en_converter.zip
188416/184801 [==============================] - 0s 0us/step
196608/184801 [===============================] - 0s 0us/step
'./ted_hrlr_translate_pt_en_converter.zip'
tokenizers = tf.saved_model.load(model_name)

tf.saved_model 2枚のテキストトークナイザ、英語用とポルトガル語のための1つを含んでいます。どちらも同じ方法です。

[item for item in dir(tokenizers.en) if not item.startswith('_')]
['detokenize',
 'get_reserved_tokens',
 'get_vocab_path',
 'get_vocab_size',
 'lookup',
 'tokenize',
 'tokenizer',
 'vocab']

tokenize方法は、トークンIDのパディングされたバッチに文字列の一括変換します。このメソッドは、句読点、小文字、およびユニコードを分割します-トークン化する前に入力を正規化します。入力データはすでに標準化されているため、この標準化はここには表示されません。

for en in en_examples.numpy():
  print(en.decode('utf-8'))
and when you improve searchability , you actually take away the one advantage of print , which is serendipity .
but what if it were active ?
but they did n't test for curiosity .
encoded = tokenizers.en.tokenize(en_examples)

for row in encoded.to_list():
  print(row)
[2, 72, 117, 79, 1259, 1491, 2362, 13, 79, 150, 184, 311, 71, 103, 2308, 74, 2679, 13, 148, 80, 55, 4840, 1434, 2423, 540, 15, 3]
[2, 87, 90, 107, 76, 129, 1852, 30, 3]
[2, 87, 83, 149, 50, 9, 56, 664, 85, 2512, 15, 3]

detokenizeバック人間が読めるテキストにこれらのトークンIDを変換するための方法を試み:

round_trip = tokenizers.en.detokenize(encoded)
for line in round_trip.numpy():
  print(line.decode('utf-8'))
and when you improve searchability , you actually take away the one advantage of print , which is serendipity .
but what if it were active ?
but they did n ' t test for curiosity .

低いレベルlookupトークンテキストにトークンIDとは法の変換:

tokens = tokenizers.en.lookup(encoded)
tokens
<tf.RaggedTensor [[b'[START]', b'and', b'when', b'you', b'improve', b'search', b'##ability', b',', b'you', b'actually', b'take', b'away', b'the', b'one', b'advantage', b'of', b'print', b',', b'which', b'is', b's', b'##ere', b'##nd', b'##ip', b'##ity', b'.', b'[END]'], [b'[START]', b'but', b'what', b'if', b'it', b'were', b'active', b'?', b'[END]'], [b'[START]', b'but', b'they', b'did', b'n', b"'", b't', b'test', b'for', b'curiosity', b'.', b'[END]']]>

ここでは、トークナイザーの「サブワード」の側面を見ることができます。 「検索可能性」という単語は「検索##可能性」に分解され、「セレンディピティ」という単語は「s ## ere ## nd ## ip ## ity」に分解されます。

入力パイプラインを設定する

トレーニングに適した入力パイプラインを構築するには、データセットにいくつかの変換を適用します。

この関数は、生のテキストのバッチをエンコードするために使用されます。

def tokenize_pairs(pt, en):
    pt = tokenizers.pt.tokenize(pt)
    # Convert from ragged to dense, padding with zeros.
    pt = pt.to_tensor()

    en = tokenizers.en.tokenize(en)
    # Convert from ragged to dense, padding with zeros.
    en = en.to_tensor()
    return pt, en

データを処理、シャッフル、バッチ処理する単純な入力パイプラインは次のとおりです。

BUFFER_SIZE = 20000
BATCH_SIZE = 64
def make_batches(ds):
  return (
      ds
      .cache()
      .shuffle(BUFFER_SIZE)
      .batch(BATCH_SIZE)
      .map(tokenize_pairs, num_parallel_calls=tf.data.AUTOTUNE)
      .prefetch(tf.data.AUTOTUNE))


train_batches = make_batches(train_examples)
val_batches = make_batches(val_examples)

位置エンコーディング

アテンションレイヤーは、入力を順番のないベクトルのセットと見なします。このモデルには、反復層または畳み込み層も含まれていません。このため、文中のトークンの相対位置に関する情報をモデルに提供するために、「位置エンコーディング」が追加されています。

位置符号化ベクトルが埋め込みベクトルに追加されます。埋め込みは、同様の意味を持つトークンが互いに近づくd次元空間のトークンを表します。ただし、埋め込みは、文内のトークンの相対位置をエンコードしません。そう位置エンコーディングを添加した後、トークンはd次元空間において、その意味の類似性および文章中のそれらの位置に基づいて相互に近くなります。

位置エンコーディングの計算式は次のとおりです。

\[\Large{PE_{(pos, 2i)} = \sin(pos / 10000^{2i / d_{model} })} \]

\[\Large{PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i / d_{model} })} \]

def get_angles(pos, i, d_model):
  angle_rates = 1 / np.power(10000, (2 * (i//2)) / np.float32(d_model))
  return pos * angle_rates
def positional_encoding(position, d_model):
  angle_rads = get_angles(np.arange(position)[:, np.newaxis],
                          np.arange(d_model)[np.newaxis, :],
                          d_model)

  # apply sin to even indices in the array; 2i
  angle_rads[:, 0::2] = np.sin(angle_rads[:, 0::2])

  # apply cos to odd indices in the array; 2i+1
  angle_rads[:, 1::2] = np.cos(angle_rads[:, 1::2])

  pos_encoding = angle_rads[np.newaxis, ...]

  return tf.cast(pos_encoding, dtype=tf.float32)
n, d = 2048, 512
pos_encoding = positional_encoding(n, d)
print(pos_encoding.shape)
pos_encoding = pos_encoding[0]

# Juggle the dimensions for the plot
pos_encoding = tf.reshape(pos_encoding, (n, d//2, 2))
pos_encoding = tf.transpose(pos_encoding, (2, 1, 0))
pos_encoding = tf.reshape(pos_encoding, (d, n))

plt.pcolormesh(pos_encoding, cmap='RdBu')
plt.ylabel('Depth')
plt.xlabel('Position')
plt.colorbar()
plt.show()
(1, 2048, 512)

png

マスキング

シーケンスのバッチ内のすべてのパッドトークンをマスクします。これにより、モデルがパディングを入力として扱わないようになります。パッド値場所マスク示す0存在している:それは出力1それらの位置に、及び0そうでありません。

def create_padding_mask(seq):
  seq = tf.cast(tf.math.equal(seq, 0), tf.float32)

  # add extra dimensions to add the padding
  # to the attention logits.
  return seq[:, tf.newaxis, tf.newaxis, :]  # (batch_size, 1, 1, seq_len)
x = tf.constant([[7, 6, 0, 0, 1], [1, 2, 3, 0, 0], [0, 0, 0, 4, 5]])
create_padding_mask(x)
<tf.Tensor: shape=(3, 1, 1, 5), dtype=float32, numpy=
array([[[[0., 0., 1., 1., 0.]]],


       [[[0., 0., 0., 1., 1.]]],


       [[[1., 1., 1., 0., 0.]]]], dtype=float32)>

先読みマスクは、シーケンス内の将来のトークンをマスクするために使用されます。つまり、マスクはどのエントリを使用しないかを示します。

これは、3番目のトークンを予測するために、1番目と2番目のトークンのみが使用されることを意味します。同様に、4番目のトークンを予測するために、1番目、2番目、および3番目のトークンのみが使用されます。

def create_look_ahead_mask(size):
  mask = 1 - tf.linalg.band_part(tf.ones((size, size)), -1, 0)
  return mask  # (seq_len, seq_len)
x = tf.random.uniform((1, 3))
temp = create_look_ahead_mask(x.shape[1])
temp
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[0., 1., 1.],
       [0., 0., 1.],
       [0., 0., 0.]], dtype=float32)>

スケーリングされたドット積の注意

scaled_dot_product_attention

トランスフォーマーが使用するアテンション関数は、Q(クエリ)、K(キー)、V(値)の3つの入力を取ります。注意の重みを計算するために使用される式は次のとおりです。

\[\Large{Attention(Q, K, V) = softmax_k\left(\frac{QK^T}{\sqrt{d_k} }\right) V} \]

内積の注意は、深さの平方根の係数でスケーリングされます。これは、深さの値が大きい場合、ドット積の大きさが大きくなり、勾配が小さいソフトマックス関数を押して、非常にハードなソフトマックスになるためです。

例えば、と考えてQK平均0と1の分散彼らの行列乗算が0との分散の平均値になります持ってdk 。だから、の平方根dkあなたがの値に関係なく、一貫した分散を得るため、スケーリングのために使用されているdk 。分散が低すぎる場合、出力がフラットすぎて効果的に最適化できない可能性があります。分散が高すぎると、初期化時にソフトマックスが飽和し、学習が困難になる可能性があります。

マスクは-1e9(負の無限大に近い)で乗算されます。これは、マスクがQとKのスケーリングされた行列乗算と合計され、ソフトマックスの直前に適用されるために行われます。目標はこれらのセルをゼロにすることであり、softmaxへの大きな負の入力は出力でほぼゼロになります。

def scaled_dot_product_attention(q, k, v, mask):
  """Calculate the attention weights.
  q, k, v must have matching leading dimensions.
  k, v must have matching penultimate dimension, i.e.: seq_len_k = seq_len_v.
  The mask has different shapes depending on its type(padding or look ahead)
  but it must be broadcastable for addition.

  Args:
    q: query shape == (..., seq_len_q, depth)
    k: key shape == (..., seq_len_k, depth)
    v: value shape == (..., seq_len_v, depth_v)
    mask: Float tensor with shape broadcastable
          to (..., seq_len_q, seq_len_k). Defaults to None.

  Returns:
    output, attention_weights
  """

  matmul_qk = tf.matmul(q, k, transpose_b=True)  # (..., seq_len_q, seq_len_k)

  # scale matmul_qk
  dk = tf.cast(tf.shape(k)[-1], tf.float32)
  scaled_attention_logits = matmul_qk / tf.math.sqrt(dk)

  # add the mask to the scaled tensor.
  if mask is not None:
    scaled_attention_logits += (mask * -1e9)

  # softmax is normalized on the last axis (seq_len_k) so that the scores
  # add up to 1.
  attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)  # (..., seq_len_q, seq_len_k)

  output = tf.matmul(attention_weights, v)  # (..., seq_len_q, depth_v)

  return output, attention_weights

ソフトマックス正規化はKで行われるため、その値によってQに与えられる重要度が決まります。

出力は、注意の重みとV(値)ベクトルの乗算を表します。これにより、焦点を当てたいトークンがそのまま保持され、無関係なトークンがフラッシュされます。

def print_out(q, k, v):
  temp_out, temp_attn = scaled_dot_product_attention(
      q, k, v, None)
  print('Attention weights are:')
  print(temp_attn)
  print('Output is:')
  print(temp_out)
np.set_printoptions(suppress=True)

temp_k = tf.constant([[10, 0, 0],
                      [0, 10, 0],
                      [0, 0, 10],
                      [0, 0, 10]], dtype=tf.float32)  # (4, 3)

temp_v = tf.constant([[1, 0],
                      [10, 0],
                      [100, 5],
                      [1000, 6]], dtype=tf.float32)  # (4, 2)

# This `query` aligns with the second `key`,
# so the second `value` is returned.
temp_q = tf.constant([[0, 10, 0]], dtype=tf.float32)  # (1, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are:
tf.Tensor([[0. 1. 0. 0.]], shape=(1, 4), dtype=float32)
Output is:
tf.Tensor([[10.  0.]], shape=(1, 2), dtype=float32)
# This query aligns with a repeated key (third and fourth),
# so all associated values get averaged.
temp_q = tf.constant([[0, 0, 10]], dtype=tf.float32)  # (1, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are:
tf.Tensor([[0.  0.  0.5 0.5]], shape=(1, 4), dtype=float32)
Output is:
tf.Tensor([[550.    5.5]], shape=(1, 2), dtype=float32)
# This query aligns equally with the first and second key,
# so their values get averaged.
temp_q = tf.constant([[10, 10, 0]], dtype=tf.float32)  # (1, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are:
tf.Tensor([[0.5 0.5 0.  0. ]], shape=(1, 4), dtype=float32)
Output is:
tf.Tensor([[5.5 0. ]], shape=(1, 2), dtype=float32)

すべてのクエリを一緒に渡します。

temp_q = tf.constant([[0, 0, 10],
                      [0, 10, 0],
                      [10, 10, 0]], dtype=tf.float32)  # (3, 3)
print_out(temp_q, temp_k, temp_v)
Attention weights are:
tf.Tensor(
[[0.  0.  0.5 0.5]
 [0.  1.  0.  0. ]
 [0.5 0.5 0.  0. ]], shape=(3, 4), dtype=float32)
Output is:
tf.Tensor(
[[550.    5.5]
 [ 10.    0. ]
 [  5.5   0. ]], shape=(3, 2), dtype=float32)

マルチヘッドアテンション

マルチヘッドアテンション

マルチヘッドアテンションは、次の4つの部分で構成されます。

  • 線形レイヤー。
  • スケーリングされたドット積の注意。
  • 最終的な線形レイヤー。

各マルチヘッドアテンションブロックは3つの入力を取得します。 Q(クエリ)、K(キー)、V(値)。これらは、マルチヘッドアテンション機能の前に線形(高密度)レイヤーを通過します。

上図の(K,Q,V) (sepearte線形通されるDense各注目ヘッド用)層。簡潔/効率を実装以下のコードは、これに単緻密層使用num_heads多くの出力として回。出力はの形に再配置される(batch, num_heads, ...)の注目機能を適用する前に。

scaled_dot_product_attention上記で定義された関数は、効率のために放送、単一のコールに適用されます。注意ステップでは、適切なマスクを使用する必要があります。各ヘッドの注目出力は、次に、(使用して連結されtf.transpose 、そしてtf.reshape )および最終通さDense層。

単一のアテンションヘッドの代わりに、Q、K、およびVは複数のヘッドに分割されます。これにより、モデルは、異なる位置にある異なる表現部分空間からの情報に共同で対応できるようになります。分割後、各ヘッドの次元が減少するため、計算コストの合計は、完全な次元の単一ヘッドの注意と同じになります。

class MultiHeadAttention(tf.keras.layers.Layer):
  def __init__(self, d_model, num_heads):
    super(MultiHeadAttention, self).__init__()
    self.num_heads = num_heads
    self.d_model = d_model

    assert d_model % self.num_heads == 0

    self.depth = d_model // self.num_heads

    self.wq = tf.keras.layers.Dense(d_model)
    self.wk = tf.keras.layers.Dense(d_model)
    self.wv = tf.keras.layers.Dense(d_model)

    self.dense = tf.keras.layers.Dense(d_model)

  def split_heads(self, x, batch_size):
    """Split the last dimension into (num_heads, depth).
    Transpose the result such that the shape is (batch_size, num_heads, seq_len, depth)
    """
    x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))
    return tf.transpose(x, perm=[0, 2, 1, 3])

  def call(self, v, k, q, mask):
    batch_size = tf.shape(q)[0]

    q = self.wq(q)  # (batch_size, seq_len, d_model)
    k = self.wk(k)  # (batch_size, seq_len, d_model)
    v = self.wv(v)  # (batch_size, seq_len, d_model)

    q = self.split_heads(q, batch_size)  # (batch_size, num_heads, seq_len_q, depth)
    k = self.split_heads(k, batch_size)  # (batch_size, num_heads, seq_len_k, depth)
    v = self.split_heads(v, batch_size)  # (batch_size, num_heads, seq_len_v, depth)

    # scaled_attention.shape == (batch_size, num_heads, seq_len_q, depth)
    # attention_weights.shape == (batch_size, num_heads, seq_len_q, seq_len_k)
    scaled_attention, attention_weights = scaled_dot_product_attention(
        q, k, v, mask)

    scaled_attention = tf.transpose(scaled_attention, perm=[0, 2, 1, 3])  # (batch_size, seq_len_q, num_heads, depth)

    concat_attention = tf.reshape(scaled_attention,
                                  (batch_size, -1, self.d_model))  # (batch_size, seq_len_q, d_model)

    output = self.dense(concat_attention)  # (batch_size, seq_len_q, d_model)

    return output, attention_weights

作成MultiHeadAttention試して層を。シーケンス内の各位置で、 yMultiHeadAttention各位置で同じ長さの新しいベクトルを返し、シーケンス内の他のすべての場所にわたって全8つの注意ヘッドを実行します。

temp_mha = MultiHeadAttention(d_model=512, num_heads=8)
y = tf.random.uniform((1, 60, 512))  # (batch_size, encoder_sequence, d_model)
out, attn = temp_mha(y, k=y, q=y, mask=None)
out.shape, attn.shape
(TensorShape([1, 60, 512]), TensorShape([1, 8, 60, 60]))

ポイントワイズフィードフォワードネットワーク

ポイントワイズフィードフォワードネットワークは、2つの完全に接続された層で構成され、その間にReLUアクティベーションがあります。

def point_wise_feed_forward_network(d_model, dff):
  return tf.keras.Sequential([
      tf.keras.layers.Dense(dff, activation='relu'),  # (batch_size, seq_len, dff)
      tf.keras.layers.Dense(d_model)  # (batch_size, seq_len, d_model)
  ])
sample_ffn = point_wise_feed_forward_network(512, 2048)
sample_ffn(tf.random.uniform((64, 50, 512))).shape
TensorShape([64, 50, 512])

エンコーダーとデコーダー

変成器

変圧器モデルは標準と同じ一般的なパターンは以下の注意モデルとシーケンスにシーケンスを

  • 入力文を通過させるNシーケンス内の各トークンのための出力を生成するエンコーダ層。
  • デコーダーは、エンコーダーの出力とそれ自体の入力(自己注意)に注意を払い、次の単語を予測します。

エンコーダーレイヤー

各エンコーダーレイヤーは、サブレイヤーで構成されています。

  1. マルチヘッドアテンション(パディングマスク付き)
  2. ポイントワイズフィードフォワードネットワーク。

これらのサブレイヤーのそれぞれは、その周りに残りの接続があり、その後にレイヤーの正規化が続きます。残りの接続は、深いネットワークでの勾配消失問題を回避するのに役立ちます。

各サブレイヤの出力はLayerNorm(x + Sublayer(x))正規化で行われd_model (最後)の軸。トランスにはN個のエンコーダ層があります。

class EncoderLayer(tf.keras.layers.Layer):
  def __init__(self, d_model, num_heads, dff, rate=0.1):
    super(EncoderLayer, self).__init__()

    self.mha = MultiHeadAttention(d_model, num_heads)
    self.ffn = point_wise_feed_forward_network(d_model, dff)

    self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
    self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)

    self.dropout1 = tf.keras.layers.Dropout(rate)
    self.dropout2 = tf.keras.layers.Dropout(rate)

  def call(self, x, training, mask):

    attn_output, _ = self.mha(x, x, x, mask)  # (batch_size, input_seq_len, d_model)
    attn_output = self.dropout1(attn_output, training=training)
    out1 = self.layernorm1(x + attn_output)  # (batch_size, input_seq_len, d_model)

    ffn_output = self.ffn(out1)  # (batch_size, input_seq_len, d_model)
    ffn_output = self.dropout2(ffn_output, training=training)
    out2 = self.layernorm2(out1 + ffn_output)  # (batch_size, input_seq_len, d_model)

    return out2
sample_encoder_layer = EncoderLayer(512, 8, 2048)

sample_encoder_layer_output = sample_encoder_layer(
    tf.random.uniform((64, 43, 512)), False, None)

sample_encoder_layer_output.shape  # (batch_size, input_seq_len, d_model)
TensorShape([64, 43, 512])

デコーダーレイヤー

各デコーダーレイヤーは、サブレイヤーで構成されています。

  1. マスクされたマルチヘッドアテンション(先読みマスクとパディングマスク付き)
  2. マルチヘッドアテンション(パディングマスク付き)。 V(値)とK(キー)を入力として、エンコーダの出力を受け取ります。 Q(クエリ)がマスクされたマルチヘッドの注目サブレイヤからの出力を受けます
  3. ポイントワイズフィードフォワードネットワーク

これらのサブレイヤーのそれぞれは、その周りに残りの接続があり、その後にレイヤーの正規化が続きます。各サブレイヤの出力はLayerNorm(x + Sublayer(x))正規化で行われd_model (最後)の軸。

トランスにはN個のデコーダ層があります。

Qはデコーダーの最初のアテンションブロックからの出力を受け取り、Kはエンコーダー出力を受け取るので、アテンションウェイトはエンコーダーの出力に基づいてデコーダーの入力に与えられる重要性を表します。言い換えると、デコーダーは、エンコーダーの出力を調べて、自身の出力に自己応答することにより、次のトークンを予測します。上記の内積注意セクションのデモを参照してください。

class DecoderLayer(tf.keras.layers.Layer):
  def __init__(self, d_model, num_heads, dff, rate=0.1):
    super(DecoderLayer, self).__init__()

    self.mha1 = MultiHeadAttention(d_model, num_heads)
    self.mha2 = MultiHeadAttention(d_model, num_heads)

    self.ffn = point_wise_feed_forward_network(d_model, dff)

    self.layernorm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
    self.layernorm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
    self.layernorm3 = tf.keras.layers.LayerNormalization(epsilon=1e-6)

    self.dropout1 = tf.keras.layers.Dropout(rate)
    self.dropout2 = tf.keras.layers.Dropout(rate)
    self.dropout3 = tf.keras.layers.Dropout(rate)

  def call(self, x, enc_output, training,
           look_ahead_mask, padding_mask):
    # enc_output.shape == (batch_size, input_seq_len, d_model)

    attn1, attn_weights_block1 = self.mha1(x, x, x, look_ahead_mask)  # (batch_size, target_seq_len, d_model)
    attn1 = self.dropout1(attn1, training=training)
    out1 = self.layernorm1(attn1 + x)

    attn2, attn_weights_block2 = self.mha2(
        enc_output, enc_output, out1, padding_mask)  # (batch_size, target_seq_len, d_model)
    attn2 = self.dropout2(attn2, training=training)
    out2 = self.layernorm2(attn2 + out1)  # (batch_size, target_seq_len, d_model)

    ffn_output = self.ffn(out2)  # (batch_size, target_seq_len, d_model)
    ffn_output = self.dropout3(ffn_output, training=training)
    out3 = self.layernorm3(ffn_output + out2)  # (batch_size, target_seq_len, d_model)

    return out3, attn_weights_block1, attn_weights_block2
sample_decoder_layer = DecoderLayer(512, 8, 2048)

sample_decoder_layer_output, _, _ = sample_decoder_layer(
    tf.random.uniform((64, 50, 512)), sample_encoder_layer_output,
    False, None, None)

sample_decoder_layer_output.shape  # (batch_size, target_seq_len, d_model)
TensorShape([64, 50, 512])

エンコーダー

Encoderで構成されています。

  1. 入力埋め込み
  2. 位置エンコーディング
  3. N個のエンコーダーレイヤー

入力は、位置エンコーディングと合計される埋め込みを通過します。この合計の出力は、エンコーダーレイヤーへの入力です。エンコーダーの出力は、デコーダーへの入力です。

class Encoder(tf.keras.layers.Layer):
  def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
               maximum_position_encoding, rate=0.1):
    super(Encoder, self).__init__()

    self.d_model = d_model
    self.num_layers = num_layers

    self.embedding = tf.keras.layers.Embedding(input_vocab_size, d_model)
    self.pos_encoding = positional_encoding(maximum_position_encoding,
                                            self.d_model)

    self.enc_layers = [EncoderLayer(d_model, num_heads, dff, rate)
                       for _ in range(num_layers)]

    self.dropout = tf.keras.layers.Dropout(rate)

  def call(self, x, training, mask):

    seq_len = tf.shape(x)[1]

    # adding embedding and position encoding.
    x = self.embedding(x)  # (batch_size, input_seq_len, d_model)
    x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
    x += self.pos_encoding[:, :seq_len, :]

    x = self.dropout(x, training=training)

    for i in range(self.num_layers):
      x = self.enc_layers[i](x, training, mask)

    return x  # (batch_size, input_seq_len, d_model)
sample_encoder = Encoder(num_layers=2, d_model=512, num_heads=8,
                         dff=2048, input_vocab_size=8500,
                         maximum_position_encoding=10000)
temp_input = tf.random.uniform((64, 62), dtype=tf.int64, minval=0, maxval=200)

sample_encoder_output = sample_encoder(temp_input, training=False, mask=None)

print(sample_encoder_output.shape)  # (batch_size, input_seq_len, d_model)
(64, 62, 512)

デコーダ

Decoderで構成されています。

  1. 出力埋め込み
  2. 位置エンコーディング
  3. N個のデコーダーレイヤー

ターゲットは、位置エンコーディングと合計される埋め込みを通過します。この合計の出力は、デコーダー層への入力です。デコーダーの出力は、最終的な線形層への入力です。

class Decoder(tf.keras.layers.Layer):
  def __init__(self, num_layers, d_model, num_heads, dff, target_vocab_size,
               maximum_position_encoding, rate=0.1):
    super(Decoder, self).__init__()

    self.d_model = d_model
    self.num_layers = num_layers

    self.embedding = tf.keras.layers.Embedding(target_vocab_size, d_model)
    self.pos_encoding = positional_encoding(maximum_position_encoding, d_model)

    self.dec_layers = [DecoderLayer(d_model, num_heads, dff, rate)
                       for _ in range(num_layers)]
    self.dropout = tf.keras.layers.Dropout(rate)

  def call(self, x, enc_output, training,
           look_ahead_mask, padding_mask):

    seq_len = tf.shape(x)[1]
    attention_weights = {}

    x = self.embedding(x)  # (batch_size, target_seq_len, d_model)
    x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
    x += self.pos_encoding[:, :seq_len, :]

    x = self.dropout(x, training=training)

    for i in range(self.num_layers):
      x, block1, block2 = self.dec_layers[i](x, enc_output, training,
                                             look_ahead_mask, padding_mask)

      attention_weights[f'decoder_layer{i+1}_block1'] = block1
      attention_weights[f'decoder_layer{i+1}_block2'] = block2

    # x.shape == (batch_size, target_seq_len, d_model)
    return x, attention_weights
sample_decoder = Decoder(num_layers=2, d_model=512, num_heads=8,
                         dff=2048, target_vocab_size=8000,
                         maximum_position_encoding=5000)
temp_input = tf.random.uniform((64, 26), dtype=tf.int64, minval=0, maxval=200)

output, attn = sample_decoder(temp_input,
                              enc_output=sample_encoder_output,
                              training=False,
                              look_ahead_mask=None,
                              padding_mask=None)

output.shape, attn['decoder_layer2_block2'].shape
(TensorShape([64, 26, 512]), TensorShape([64, 8, 26, 62]))

トランスフォーマーを作成する

トランスフォーマーは、エンコーダー、デコーダー、および最終的な線形レイヤーで構成されます。デコーダーの出力は線形層への入力であり、その出力が返されます。

class Transformer(tf.keras.Model):
  def __init__(self, num_layers, d_model, num_heads, dff, input_vocab_size,
               target_vocab_size, pe_input, pe_target, rate=0.1):
    super().__init__()
    self.encoder = Encoder(num_layers, d_model, num_heads, dff,
                             input_vocab_size, pe_input, rate)

    self.decoder = Decoder(num_layers, d_model, num_heads, dff,
                           target_vocab_size, pe_target, rate)

    self.final_layer = tf.keras.layers.Dense(target_vocab_size)

  def call(self, inputs, training):
    # Keras models prefer if you pass all your inputs in the first argument
    inp, tar = inputs

    enc_padding_mask, look_ahead_mask, dec_padding_mask = self.create_masks(inp, tar)

    enc_output = self.encoder(inp, training, enc_padding_mask)  # (batch_size, inp_seq_len, d_model)

    # dec_output.shape == (batch_size, tar_seq_len, d_model)
    dec_output, attention_weights = self.decoder(
        tar, enc_output, training, look_ahead_mask, dec_padding_mask)

    final_output = self.final_layer(dec_output)  # (batch_size, tar_seq_len, target_vocab_size)

    return final_output, attention_weights

  def create_masks(self, inp, tar):
    # Encoder padding mask
    enc_padding_mask = create_padding_mask(inp)

    # Used in the 2nd attention block in the decoder.
    # This padding mask is used to mask the encoder outputs.
    dec_padding_mask = create_padding_mask(inp)

    # Used in the 1st attention block in the decoder.
    # It is used to pad and mask future tokens in the input received by
    # the decoder.
    look_ahead_mask = create_look_ahead_mask(tf.shape(tar)[1])
    dec_target_padding_mask = create_padding_mask(tar)
    look_ahead_mask = tf.maximum(dec_target_padding_mask, look_ahead_mask)

    return enc_padding_mask, look_ahead_mask, dec_padding_mask
sample_transformer = Transformer(
    num_layers=2, d_model=512, num_heads=8, dff=2048,
    input_vocab_size=8500, target_vocab_size=8000,
    pe_input=10000, pe_target=6000)

temp_input = tf.random.uniform((64, 38), dtype=tf.int64, minval=0, maxval=200)
temp_target = tf.random.uniform((64, 36), dtype=tf.int64, minval=0, maxval=200)

fn_out, _ = sample_transformer([temp_input, temp_target], training=False)

fn_out.shape  # (batch_size, tar_seq_len, target_vocab_size)
TensorShape([64, 36, 8000])

ハイパーパラメータを設定する

小さなこの例を維持するには、比較的速い、の値num_layers, d_model, dff減少しています。

ベースモデルは、に記載の:使用num_layers=6, d_model=512, dff=2048

num_layers = 4
d_model = 128
dff = 512
num_heads = 8
dropout_rate = 0.1

オプティマイザ

中式に従ってカスタム学習率スケジューラとアダム・オプティマイザを使用した紙

\[\Large{lrate = d_{model}^{-0.5} * \min(step{\_}num^{-0.5}, step{\_}num \cdot warmup{\_}steps^{-1.5})}\]

class CustomSchedule(tf.keras.optimizers.schedules.LearningRateSchedule):
  def __init__(self, d_model, warmup_steps=4000):
    super(CustomSchedule, self).__init__()

    self.d_model = d_model
    self.d_model = tf.cast(self.d_model, tf.float32)

    self.warmup_steps = warmup_steps

  def __call__(self, step):
    arg1 = tf.math.rsqrt(step)
    arg2 = step * (self.warmup_steps ** -1.5)

    return tf.math.rsqrt(self.d_model) * tf.math.minimum(arg1, arg2)
learning_rate = CustomSchedule(d_model)

optimizer = tf.keras.optimizers.Adam(learning_rate, beta_1=0.9, beta_2=0.98,
                                     epsilon=1e-9)
temp_learning_rate_schedule = CustomSchedule(d_model)

plt.plot(temp_learning_rate_schedule(tf.range(40000, dtype=tf.float32)))
plt.ylabel("Learning Rate")
plt.xlabel("Train Step")
Text(0.5, 0, 'Train Step')

png

損失と指標

ターゲットシーケンスはパディングされるため、損失を計算するときにパディングマスクを適用することが重要です。

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_sum(loss_)/tf.reduce_sum(mask)


def accuracy_function(real, pred):
  accuracies = tf.equal(real, tf.argmax(pred, axis=2))

  mask = tf.math.logical_not(tf.math.equal(real, 0))
  accuracies = tf.math.logical_and(mask, accuracies)

  accuracies = tf.cast(accuracies, dtype=tf.float32)
  mask = tf.cast(mask, dtype=tf.float32)
  return tf.reduce_sum(accuracies)/tf.reduce_sum(mask)
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.Mean(name='train_accuracy')

トレーニングとチェックポイント

transformer = Transformer(
    num_layers=num_layers,
    d_model=d_model,
    num_heads=num_heads,
    dff=dff,
    input_vocab_size=tokenizers.pt.get_vocab_size().numpy(),
    target_vocab_size=tokenizers.en.get_vocab_size().numpy(),
    pe_input=1000,
    pe_target=1000,
    rate=dropout_rate)

チェックポイントパスとチェックポイントマネージャーを作成します。これは、チェックポイントごとに保存するために使用されるnエポックを。

checkpoint_path = "./checkpoints/train"

ckpt = tf.train.Checkpoint(transformer=transformer,
                           optimizer=optimizer)

ckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=5)

# if a checkpoint exists, restore the latest checkpoint.
if ckpt_manager.latest_checkpoint:
  ckpt.restore(ckpt_manager.latest_checkpoint)
  print('Latest checkpoint restored!!')

ターゲットはtar_inpとtar_realに分けられます。 tar_inpは、デコーダーへの入力として渡されます。 tar_real同じ入力が1だけシフトすることである:の各位置でtar_inputtar_real予測されるべき次のトークンを含みます。

例えば、 sentence =「ジャングルの中でSOS AライオンはEOSに眠っています」

tar_inp =「ジャングルの中でSOS Aライオンは寝ています」

tar_real =「ジャングルの中でライオンがEOSに眠っています」

トランスフォーマーは自己回帰モデルです。一度に1つの部分で予測を行い、これまでの出力を使用して次に何をするかを決定します。

この例を、トレーニング中に教師強制的に(のように使用するテキスト生成チュートリアル)。教師の強制は、モデルが現在のタイムステップで何を予測するかに関係なく、真の出力を次のタイムステップに渡します。

変圧器は、各トークンを予測したように、自己の注目は、それがより良い次のトークンを予測するために、入力シーケンス内の前のトークンを見ることができます。

モデルが期待される出力を覗き見するのを防ぐために、モデルは先読みマスクを使用します。

EPOCHS = 20
# The @tf.function trace-compiles train_step into a TF graph for faster
# execution. The function specializes to the precise shape of the argument
# tensors. To avoid re-tracing due to the variable sequence lengths or variable
# batch sizes (the last batch is smaller), use input_signature to specify
# more generic shapes.

train_step_signature = [
    tf.TensorSpec(shape=(None, None), dtype=tf.int64),
    tf.TensorSpec(shape=(None, None), dtype=tf.int64),
]


@tf.function(input_signature=train_step_signature)
def train_step(inp, tar):
  tar_inp = tar[:, :-1]
  tar_real = tar[:, 1:]

  with tf.GradientTape() as tape:
    predictions, _ = transformer([inp, tar_inp],
                                 training = True)
    loss = loss_function(tar_real, predictions)

  gradients = tape.gradient(loss, transformer.trainable_variables)
  optimizer.apply_gradients(zip(gradients, transformer.trainable_variables))

  train_loss(loss)
  train_accuracy(accuracy_function(tar_real, predictions))

入力言語としてポルトガル語が使用され、ターゲット言語は英語です。

for epoch in range(EPOCHS):
  start = time.time()

  train_loss.reset_states()
  train_accuracy.reset_states()

  # inp -> portuguese, tar -> english
  for (batch, (inp, tar)) in enumerate(train_batches):
    train_step(inp, tar)

    if batch % 50 == 0:
      print(f'Epoch {epoch + 1} Batch {batch} Loss {train_loss.result():.4f} Accuracy {train_accuracy.result():.4f}')

  if (epoch + 1) % 5 == 0:
    ckpt_save_path = ckpt_manager.save()
    print(f'Saving checkpoint for epoch {epoch+1} at {ckpt_save_path}')

  print(f'Epoch {epoch + 1} Loss {train_loss.result():.4f} Accuracy {train_accuracy.result():.4f}')

  print(f'Time taken for 1 epoch: {time.time() - start:.2f} secs\n')
Epoch 1 Batch 0 Loss 8.8389 Accuracy 0.0000
Epoch 1 Batch 50 Loss 8.7850 Accuracy 0.0015
Epoch 1 Batch 100 Loss 8.6954 Accuracy 0.0258
Epoch 1 Batch 150 Loss 8.5875 Accuracy 0.0361
Epoch 1 Batch 200 Loss 8.4497 Accuracy 0.0396
Epoch 1 Batch 250 Loss 8.2832 Accuracy 0.0412
Epoch 1 Batch 300 Loss 8.0957 Accuracy 0.0424
Epoch 1 Batch 350 Loss 7.9001 Accuracy 0.0462
Epoch 1 Batch 400 Loss 7.7106 Accuracy 0.0530
Epoch 1 Batch 450 Loss 7.5449 Accuracy 0.0608
Epoch 1 Batch 500 Loss 7.3965 Accuracy 0.0686
Epoch 1 Batch 550 Loss 7.2629 Accuracy 0.0764
Epoch 1 Batch 600 Loss 7.1374 Accuracy 0.0841
Epoch 1 Batch 650 Loss 7.0225 Accuracy 0.0915
Epoch 1 Batch 700 Loss 6.9148 Accuracy 0.0987
Epoch 1 Batch 750 Loss 6.8137 Accuracy 0.1055
Epoch 1 Batch 800 Loss 6.7228 Accuracy 0.1115
Epoch 1 Loss 6.7072 Accuracy 0.1126
Time taken for 1 epoch: 62.48 secs

Epoch 2 Batch 0 Loss 5.3320 Accuracy 0.2099
Epoch 2 Batch 50 Loss 5.2248 Accuracy 0.2119
Epoch 2 Batch 100 Loss 5.1947 Accuracy 0.2152
Epoch 2 Batch 150 Loss 5.1643 Accuracy 0.2191
Epoch 2 Batch 200 Loss 5.1383 Accuracy 0.2224
Epoch 2 Batch 250 Loss 5.1123 Accuracy 0.2254
Epoch 2 Batch 300 Loss 5.0864 Accuracy 0.2277
Epoch 2 Batch 350 Loss 5.0697 Accuracy 0.2291
Epoch 2 Batch 400 Loss 5.0487 Accuracy 0.2313
Epoch 2 Batch 450 Loss 5.0272 Accuracy 0.2331
Epoch 2 Batch 500 Loss 5.0060 Accuracy 0.2349
Epoch 2 Batch 550 Loss 4.9882 Accuracy 0.2365
Epoch 2 Batch 600 Loss 4.9677 Accuracy 0.2382
Epoch 2 Batch 650 Loss 4.9496 Accuracy 0.2400
Epoch 2 Batch 700 Loss 4.9314 Accuracy 0.2417
Epoch 2 Batch 750 Loss 4.9172 Accuracy 0.2429
Epoch 2 Batch 800 Loss 4.9005 Accuracy 0.2444
Epoch 2 Loss 4.8976 Accuracy 0.2447
Time taken for 1 epoch: 47.81 secs

Epoch 3 Batch 0 Loss 4.7853 Accuracy 0.2318
Epoch 3 Batch 50 Loss 4.6041 Accuracy 0.2673
Epoch 3 Batch 100 Loss 4.5869 Accuracy 0.2693
Epoch 3 Batch 150 Loss 4.5681 Accuracy 0.2723
Epoch 3 Batch 200 Loss 4.5502 Accuracy 0.2748
Epoch 3 Batch 250 Loss 4.5433 Accuracy 0.2755
Epoch 3 Batch 300 Loss 4.5279 Accuracy 0.2771
Epoch 3 Batch 350 Loss 4.5123 Accuracy 0.2792
Epoch 3 Batch 400 Loss 4.5001 Accuracy 0.2807
Epoch 3 Batch 450 Loss 4.4849 Accuracy 0.2825
Epoch 3 Batch 500 Loss 4.4699 Accuracy 0.2842
Epoch 3 Batch 550 Loss 4.4543 Accuracy 0.2861
Epoch 3 Batch 600 Loss 4.4397 Accuracy 0.2879
Epoch 3 Batch 650 Loss 4.4260 Accuracy 0.2896
Epoch 3 Batch 700 Loss 4.4098 Accuracy 0.2918
Epoch 3 Batch 750 Loss 4.3934 Accuracy 0.2938
Epoch 3 Batch 800 Loss 4.3774 Accuracy 0.2958
Epoch 3 Loss 4.3743 Accuracy 0.2961
Time taken for 1 epoch: 47.78 secs

Epoch 4 Batch 0 Loss 4.1607 Accuracy 0.3198
Epoch 4 Batch 50 Loss 4.0206 Accuracy 0.3366
Epoch 4 Batch 100 Loss 4.0181 Accuracy 0.3379
Epoch 4 Batch 150 Loss 4.0005 Accuracy 0.3390
Epoch 4 Batch 200 Loss 3.9809 Accuracy 0.3420
Epoch 4 Batch 250 Loss 3.9716 Accuracy 0.3436
Epoch 4 Batch 300 Loss 3.9561 Accuracy 0.3453
Epoch 4 Batch 350 Loss 3.9396 Accuracy 0.3476
Epoch 4 Batch 400 Loss 3.9287 Accuracy 0.3492
Epoch 4 Batch 450 Loss 3.9099 Accuracy 0.3516
Epoch 4 Batch 500 Loss 3.8948 Accuracy 0.3534
Epoch 4 Batch 550 Loss 3.8796 Accuracy 0.3554
Epoch 4 Batch 600 Loss 3.8647 Accuracy 0.3573
Epoch 4 Batch 650 Loss 3.8496 Accuracy 0.3593
Epoch 4 Batch 700 Loss 3.8345 Accuracy 0.3613
Epoch 4 Batch 750 Loss 3.8216 Accuracy 0.3631
Epoch 4 Batch 800 Loss 3.8113 Accuracy 0.3645
Epoch 4 Loss 3.8084 Accuracy 0.3649
Time taken for 1 epoch: 47.74 secs

Epoch 5 Batch 0 Loss 3.7892 Accuracy 0.3515
Epoch 5 Batch 50 Loss 3.5277 Accuracy 0.3971
Epoch 5 Batch 100 Loss 3.4909 Accuracy 0.4026
Epoch 5 Batch 150 Loss 3.4709 Accuracy 0.4059
Epoch 5 Batch 200 Loss 3.4637 Accuracy 0.4068
Epoch 5 Batch 250 Loss 3.4614 Accuracy 0.4071
Epoch 5 Batch 300 Loss 3.4471 Accuracy 0.4093
Epoch 5 Batch 350 Loss 3.4360 Accuracy 0.4102
Epoch 5 Batch 400 Loss 3.4277 Accuracy 0.4112
Epoch 5 Batch 450 Loss 3.4186 Accuracy 0.4124
Epoch 5 Batch 500 Loss 3.4127 Accuracy 0.4133
Epoch 5 Batch 550 Loss 3.4023 Accuracy 0.4145
Epoch 5 Batch 600 Loss 3.3931 Accuracy 0.4154
Epoch 5 Batch 650 Loss 3.3821 Accuracy 0.4169
Epoch 5 Batch 700 Loss 3.3719 Accuracy 0.4183
Epoch 5 Batch 750 Loss 3.3632 Accuracy 0.4195
Epoch 5 Batch 800 Loss 3.3550 Accuracy 0.4205
Saving checkpoint for epoch 5 at ./checkpoints/train/ckpt-1
Epoch 5 Loss 3.3540 Accuracy 0.4206
Time taken for 1 epoch: 47.47 secs

Epoch 6 Batch 0 Loss 3.5078 Accuracy 0.3912
Epoch 6 Batch 50 Loss 3.1028 Accuracy 0.4487
Epoch 6 Batch 100 Loss 3.0855 Accuracy 0.4503
Epoch 6 Batch 150 Loss 3.0784 Accuracy 0.4515
Epoch 6 Batch 200 Loss 3.0664 Accuracy 0.4534
Epoch 6 Batch 250 Loss 3.0621 Accuracy 0.4537
Epoch 6 Batch 300 Loss 3.0512 Accuracy 0.4556
Epoch 6 Batch 350 Loss 3.0368 Accuracy 0.4580
Epoch 6 Batch 400 Loss 3.0283 Accuracy 0.4592
Epoch 6 Batch 450 Loss 3.0176 Accuracy 0.4608
Epoch 6 Batch 500 Loss 3.0083 Accuracy 0.4623
Epoch 6 Batch 550 Loss 2.9966 Accuracy 0.4639
Epoch 6 Batch 600 Loss 2.9871 Accuracy 0.4652
Epoch 6 Batch 650 Loss 2.9777 Accuracy 0.4664
Epoch 6 Batch 700 Loss 2.9722 Accuracy 0.4673
Epoch 6 Batch 750 Loss 2.9650 Accuracy 0.4684
Epoch 6 Batch 800 Loss 2.9562 Accuracy 0.4697
Epoch 6 Loss 2.9548 Accuracy 0.4698
Time taken for 1 epoch: 47.10 secs

Epoch 7 Batch 0 Loss 2.7935 Accuracy 0.4985
Epoch 7 Batch 50 Loss 2.6880 Accuracy 0.5017
Epoch 7 Batch 100 Loss 2.6676 Accuracy 0.5053
Epoch 7 Batch 150 Loss 2.6658 Accuracy 0.5062
Epoch 7 Batch 200 Loss 2.6631 Accuracy 0.5068
Epoch 7 Batch 250 Loss 2.6634 Accuracy 0.5069
Epoch 7 Batch 300 Loss 2.6575 Accuracy 0.5078
Epoch 7 Batch 350 Loss 2.6485 Accuracy 0.5088
Epoch 7 Batch 400 Loss 2.6472 Accuracy 0.5092
Epoch 7 Batch 450 Loss 2.6432 Accuracy 0.5097
Epoch 7 Batch 500 Loss 2.6398 Accuracy 0.5103
Epoch 7 Batch 550 Loss 2.6372 Accuracy 0.5111
Epoch 7 Batch 600 Loss 2.6340 Accuracy 0.5115
Epoch 7 Batch 650 Loss 2.6292 Accuracy 0.5123
Epoch 7 Batch 700 Loss 2.6266 Accuracy 0.5127
Epoch 7 Batch 750 Loss 2.6253 Accuracy 0.5129
Epoch 7 Batch 800 Loss 2.6217 Accuracy 0.5134
Epoch 7 Loss 2.6215 Accuracy 0.5134
Time taken for 1 epoch: 47.31 secs

Epoch 8 Batch 0 Loss 2.5891 Accuracy 0.5090
Epoch 8 Batch 50 Loss 2.4158 Accuracy 0.5395
Epoch 8 Batch 100 Loss 2.4099 Accuracy 0.5399
Epoch 8 Batch 150 Loss 2.4026 Accuracy 0.5408
Epoch 8 Batch 200 Loss 2.4023 Accuracy 0.5409
Epoch 8 Batch 250 Loss 2.4053 Accuracy 0.5404
Epoch 8 Batch 300 Loss 2.4085 Accuracy 0.5395
Epoch 8 Batch 350 Loss 2.4022 Accuracy 0.5406
Epoch 8 Batch 400 Loss 2.4031 Accuracy 0.5409
Epoch 8 Batch 450 Loss 2.3993 Accuracy 0.5416
Epoch 8 Batch 500 Loss 2.3970 Accuracy 0.5421
Epoch 8 Batch 550 Loss 2.3945 Accuracy 0.5429
Epoch 8 Batch 600 Loss 2.3908 Accuracy 0.5433
Epoch 8 Batch 650 Loss 2.3884 Accuracy 0.5439
Epoch 8 Batch 700 Loss 2.3864 Accuracy 0.5443
Epoch 8 Batch 750 Loss 2.3860 Accuracy 0.5443
Epoch 8 Batch 800 Loss 2.3829 Accuracy 0.5448
Epoch 8 Loss 2.3815 Accuracy 0.5450
Time taken for 1 epoch: 47.15 secs

Epoch 9 Batch 0 Loss 2.4162 Accuracy 0.5382
Epoch 9 Batch 50 Loss 2.2300 Accuracy 0.5635
Epoch 9 Batch 100 Loss 2.2048 Accuracy 0.5665
Epoch 9 Batch 150 Loss 2.2009 Accuracy 0.5681
Epoch 9 Batch 200 Loss 2.2006 Accuracy 0.5687
Epoch 9 Batch 250 Loss 2.2034 Accuracy 0.5682
Epoch 9 Batch 300 Loss 2.1974 Accuracy 0.5690
Epoch 9 Batch 350 Loss 2.2068 Accuracy 0.5678
Epoch 9 Batch 400 Loss 2.2058 Accuracy 0.5682
Epoch 9 Batch 450 Loss 2.2109 Accuracy 0.5677
Epoch 9 Batch 500 Loss 2.2112 Accuracy 0.5676
Epoch 9 Batch 550 Loss 2.2080 Accuracy 0.5685
Epoch 9 Batch 600 Loss 2.2106 Accuracy 0.5680
Epoch 9 Batch 650 Loss 2.2084 Accuracy 0.5684
Epoch 9 Batch 700 Loss 2.2082 Accuracy 0.5686
Epoch 9 Batch 750 Loss 2.2089 Accuracy 0.5685
Epoch 9 Batch 800 Loss 2.2084 Accuracy 0.5687
Epoch 9 Loss 2.2083 Accuracy 0.5686
Time taken for 1 epoch: 46.95 secs

Epoch 10 Batch 0 Loss 2.2234 Accuracy 0.5604
Epoch 10 Batch 50 Loss 2.1030 Accuracy 0.5814
Epoch 10 Batch 100 Loss 2.0774 Accuracy 0.5866
Epoch 10 Batch 150 Loss 2.0655 Accuracy 0.5881
Epoch 10 Batch 200 Loss 2.0661 Accuracy 0.5880
Epoch 10 Batch 250 Loss 2.0635 Accuracy 0.5883
Epoch 10 Batch 300 Loss 2.0616 Accuracy 0.5888
Epoch 10 Batch 350 Loss 2.0636 Accuracy 0.5886
Epoch 10 Batch 400 Loss 2.0621 Accuracy 0.5888
Epoch 10 Batch 450 Loss 2.0670 Accuracy 0.5878
Epoch 10 Batch 500 Loss 2.0652 Accuracy 0.5880
Epoch 10 Batch 550 Loss 2.0686 Accuracy 0.5875
Epoch 10 Batch 600 Loss 2.0692 Accuracy 0.5875
Epoch 10 Batch 650 Loss 2.0691 Accuracy 0.5876
Epoch 10 Batch 700 Loss 2.0707 Accuracy 0.5876
Epoch 10 Batch 750 Loss 2.0704 Accuracy 0.5878
Epoch 10 Batch 800 Loss 2.0722 Accuracy 0.5876
Saving checkpoint for epoch 10 at ./checkpoints/train/ckpt-2
Epoch 10 Loss 2.0715 Accuracy 0.5879
Time taken for 1 epoch: 47.13 secs

Epoch 11 Batch 0 Loss 1.9391 Accuracy 0.6270
Epoch 11 Batch 50 Loss 1.9758 Accuracy 0.5977
Epoch 11 Batch 100 Loss 1.9564 Accuracy 0.6024
Epoch 11 Batch 150 Loss 1.9526 Accuracy 0.6037
Epoch 11 Batch 200 Loss 1.9573 Accuracy 0.6030
Epoch 11 Batch 250 Loss 1.9471 Accuracy 0.6048
Epoch 11 Batch 300 Loss 1.9459 Accuracy 0.6048
Epoch 11 Batch 350 Loss 1.9490 Accuracy 0.6042
Epoch 11 Batch 400 Loss 1.9518 Accuracy 0.6040
Epoch 11 Batch 450 Loss 1.9549 Accuracy 0.6038
Epoch 11 Batch 500 Loss 1.9543 Accuracy 0.6040
Epoch 11 Batch 550 Loss 1.9537 Accuracy 0.6043
Epoch 11 Batch 600 Loss 1.9546 Accuracy 0.6042
Epoch 11 Batch 650 Loss 1.9556 Accuracy 0.6040
Epoch 11 Batch 700 Loss 1.9582 Accuracy 0.6038
Epoch 11 Batch 750 Loss 1.9592 Accuracy 0.6037
Epoch 11 Batch 800 Loss 1.9606 Accuracy 0.6037
Epoch 11 Loss 1.9614 Accuracy 0.6036
Time taken for 1 epoch: 46.59 secs

Epoch 12 Batch 0 Loss 1.7234 Accuracy 0.6256
Epoch 12 Batch 50 Loss 1.8507 Accuracy 0.6169
Epoch 12 Batch 100 Loss 1.8460 Accuracy 0.6184
Epoch 12 Batch 150 Loss 1.8366 Accuracy 0.6207
Epoch 12 Batch 200 Loss 1.8454 Accuracy 0.6196
Epoch 12 Batch 250 Loss 1.8398 Accuracy 0.6205
Epoch 12 Batch 300 Loss 1.8441 Accuracy 0.6202
Epoch 12 Batch 350 Loss 1.8440 Accuracy 0.6199
Epoch 12 Batch 400 Loss 1.8443 Accuracy 0.6200
Epoch 12 Batch 450 Loss 1.8452 Accuracy 0.6198
Epoch 12 Batch 500 Loss 1.8499 Accuracy 0.6193
Epoch 12 Batch 550 Loss 1.8520 Accuracy 0.6190
Epoch 12 Batch 600 Loss 1.8554 Accuracy 0.6185
Epoch 12 Batch 650 Loss 1.8587 Accuracy 0.6179
Epoch 12 Batch 700 Loss 1.8610 Accuracy 0.6176
Epoch 12 Batch 750 Loss 1.8655 Accuracy 0.6170
Epoch 12 Batch 800 Loss 1.8684 Accuracy 0.6167
Epoch 12 Loss 1.8688 Accuracy 0.6167
Time taken for 1 epoch: 46.38 secs

Epoch 13 Batch 0 Loss 1.7697 Accuracy 0.6350
Epoch 13 Batch 50 Loss 1.7443 Accuracy 0.6337
Epoch 13 Batch 100 Loss 1.7422 Accuracy 0.6352
Epoch 13 Batch 150 Loss 1.7497 Accuracy 0.6331
Epoch 13 Batch 200 Loss 1.7603 Accuracy 0.6315
Epoch 13 Batch 250 Loss 1.7623 Accuracy 0.6316
Epoch 13 Batch 300 Loss 1.7656 Accuracy 0.6315
Epoch 13 Batch 350 Loss 1.7669 Accuracy 0.6312
Epoch 13 Batch 400 Loss 1.7683 Accuracy 0.6310
Epoch 13 Batch 450 Loss 1.7758 Accuracy 0.6298
Epoch 13 Batch 500 Loss 1.7758 Accuracy 0.6300
Epoch 13 Batch 550 Loss 1.7784 Accuracy 0.6296
Epoch 13 Batch 600 Loss 1.7804 Accuracy 0.6294
Epoch 13 Batch 650 Loss 1.7825 Accuracy 0.6291
Epoch 13 Batch 700 Loss 1.7867 Accuracy 0.6286
Epoch 13 Batch 750 Loss 1.7878 Accuracy 0.6284
Epoch 13 Batch 800 Loss 1.7913 Accuracy 0.6280
Epoch 13 Loss 1.7916 Accuracy 0.6280
Time taken for 1 epoch: 46.41 secs

Epoch 14 Batch 0 Loss 1.4785 Accuracy 0.6762
Epoch 14 Batch 50 Loss 1.7171 Accuracy 0.6378
Epoch 14 Batch 100 Loss 1.6949 Accuracy 0.6424
Epoch 14 Batch 150 Loss 1.6862 Accuracy 0.6440
Epoch 14 Batch 200 Loss 1.6893 Accuracy 0.6442
Epoch 14 Batch 250 Loss 1.6927 Accuracy 0.6432
Epoch 14 Batch 300 Loss 1.6943 Accuracy 0.6428
Epoch 14 Batch 350 Loss 1.6951 Accuracy 0.6427
Epoch 14 Batch 400 Loss 1.6961 Accuracy 0.6426
Epoch 14 Batch 450 Loss 1.7003 Accuracy 0.6420
Epoch 14 Batch 500 Loss 1.7028 Accuracy 0.6415
Epoch 14 Batch 550 Loss 1.7027 Accuracy 0.6413
Epoch 14 Batch 600 Loss 1.7066 Accuracy 0.6406
Epoch 14 Batch 650 Loss 1.7110 Accuracy 0.6399
Epoch 14 Batch 700 Loss 1.7140 Accuracy 0.6395
Epoch 14 Batch 750 Loss 1.7174 Accuracy 0.6390
Epoch 14 Batch 800 Loss 1.7198 Accuracy 0.6389
Epoch 14 Loss 1.7210 Accuracy 0.6387
Time taken for 1 epoch: 46.84 secs

Epoch 15 Batch 0 Loss 1.7209 Accuracy 0.6358
Epoch 15 Batch 50 Loss 1.6188 Accuracy 0.6545
Epoch 15 Batch 100 Loss 1.6084 Accuracy 0.6567
Epoch 15 Batch 150 Loss 1.6169 Accuracy 0.6557
Epoch 15 Batch 200 Loss 1.6215 Accuracy 0.6542
Epoch 15 Batch 250 Loss 1.6268 Accuracy 0.6534
Epoch 15 Batch 300 Loss 1.6257 Accuracy 0.6539
Epoch 15 Batch 350 Loss 1.6300 Accuracy 0.6531
Epoch 15 Batch 400 Loss 1.6318 Accuracy 0.6527
Epoch 15 Batch 450 Loss 1.6360 Accuracy 0.6521
Epoch 15 Batch 500 Loss 1.6403 Accuracy 0.6515
Epoch 15 Batch 550 Loss 1.6445 Accuracy 0.6509
Epoch 15 Batch 600 Loss 1.6467 Accuracy 0.6505
Epoch 15 Batch 650 Loss 1.6501 Accuracy 0.6499
Epoch 15 Batch 700 Loss 1.6537 Accuracy 0.6495
Epoch 15 Batch 750 Loss 1.6560 Accuracy 0.6492
Epoch 15 Batch 800 Loss 1.6602 Accuracy 0.6486
Saving checkpoint for epoch 15 at ./checkpoints/train/ckpt-3
Epoch 15 Loss 1.6598 Accuracy 0.6487
Time taken for 1 epoch: 46.54 secs

Epoch 16 Batch 0 Loss 1.5373 Accuracy 0.6739
Epoch 16 Batch 50 Loss 1.5678 Accuracy 0.6614
Epoch 16 Batch 100 Loss 1.5524 Accuracy 0.6646
Epoch 16 Batch 150 Loss 1.5550 Accuracy 0.6640
Epoch 16 Batch 200 Loss 1.5612 Accuracy 0.6627
Epoch 16 Batch 250 Loss 1.5703 Accuracy 0.6608
Epoch 16 Batch 300 Loss 1.5771 Accuracy 0.6597
Epoch 16 Batch 350 Loss 1.5812 Accuracy 0.6593
Epoch 16 Batch 400 Loss 1.5846 Accuracy 0.6588
Epoch 16 Batch 450 Loss 1.5864 Accuracy 0.6587
Epoch 16 Batch 500 Loss 1.5906 Accuracy 0.6581
Epoch 16 Batch 550 Loss 1.5940 Accuracy 0.6575
Epoch 16 Batch 600 Loss 1.5938 Accuracy 0.6576
Epoch 16 Batch 650 Loss 1.5959 Accuracy 0.6575
Epoch 16 Batch 700 Loss 1.5991 Accuracy 0.6571
Epoch 16 Batch 750 Loss 1.6017 Accuracy 0.6568
Epoch 16 Batch 800 Loss 1.6035 Accuracy 0.6566
Epoch 16 Loss 1.6043 Accuracy 0.6565
Time taken for 1 epoch: 46.25 secs

Epoch 17 Batch 0 Loss 1.6442 Accuracy 0.6463
Epoch 17 Batch 50 Loss 1.5289 Accuracy 0.6670
Epoch 17 Batch 100 Loss 1.5225 Accuracy 0.6684
Epoch 17 Batch 150 Loss 1.5237 Accuracy 0.6685
Epoch 17 Batch 200 Loss 1.5301 Accuracy 0.6674
Epoch 17 Batch 250 Loss 1.5323 Accuracy 0.6672
Epoch 17 Batch 300 Loss 1.5332 Accuracy 0.6670
Epoch 17 Batch 350 Loss 1.5349 Accuracy 0.6667
Epoch 17 Batch 400 Loss 1.5377 Accuracy 0.6662
Epoch 17 Batch 450 Loss 1.5399 Accuracy 0.6660
Epoch 17 Batch 500 Loss 1.5412 Accuracy 0.6660
Epoch 17 Batch 550 Loss 1.5468 Accuracy 0.6650
Epoch 17 Batch 600 Loss 1.5474 Accuracy 0.6651
Epoch 17 Batch 650 Loss 1.5504 Accuracy 0.6647
Epoch 17 Batch 700 Loss 1.5534 Accuracy 0.6643
Epoch 17 Batch 750 Loss 1.5562 Accuracy 0.6639
Epoch 17 Batch 800 Loss 1.5583 Accuracy 0.6635
Epoch 17 Loss 1.5593 Accuracy 0.6633
Time taken for 1 epoch: 46.66 secs

Epoch 18 Batch 0 Loss 1.5130 Accuracy 0.6849
Epoch 18 Batch 50 Loss 1.4575 Accuracy 0.6796
Epoch 18 Batch 100 Loss 1.4698 Accuracy 0.6770
Epoch 18 Batch 150 Loss 1.4760 Accuracy 0.6765
Epoch 18 Batch 200 Loss 1.4783 Accuracy 0.6762
Epoch 18 Batch 250 Loss 1.4811 Accuracy 0.6758
Epoch 18 Batch 300 Loss 1.4870 Accuracy 0.6749
Epoch 18 Batch 350 Loss 1.4929 Accuracy 0.6738
Epoch 18 Batch 400 Loss 1.4945 Accuracy 0.6736
Epoch 18 Batch 450 Loss 1.4979 Accuracy 0.6730
Epoch 18 Batch 500 Loss 1.4970 Accuracy 0.6731
Epoch 18 Batch 550 Loss 1.5004 Accuracy 0.6725
Epoch 18 Batch 600 Loss 1.5034 Accuracy 0.6721
Epoch 18 Batch 650 Loss 1.5073 Accuracy 0.6715
Epoch 18 Batch 700 Loss 1.5096 Accuracy 0.6712
Epoch 18 Batch 750 Loss 1.5129 Accuracy 0.6707
Epoch 18 Batch 800 Loss 1.5164 Accuracy 0.6701
Epoch 18 Loss 1.5160 Accuracy 0.6702
Time taken for 1 epoch: 46.40 secs

Epoch 19 Batch 0 Loss 1.5139 Accuracy 0.6813
Epoch 19 Batch 50 Loss 1.4341 Accuracy 0.6832
Epoch 19 Batch 100 Loss 1.4357 Accuracy 0.6828
Epoch 19 Batch 150 Loss 1.4364 Accuracy 0.6829
Epoch 19 Batch 200 Loss 1.4439 Accuracy 0.6816
Epoch 19 Batch 250 Loss 1.4448 Accuracy 0.6816
Epoch 19 Batch 300 Loss 1.4494 Accuracy 0.6812
Epoch 19 Batch 350 Loss 1.4543 Accuracy 0.6805
Epoch 19 Batch 400 Loss 1.4543 Accuracy 0.6804
Epoch 19 Batch 450 Loss 1.4583 Accuracy 0.6795
Epoch 19 Batch 500 Loss 1.4609 Accuracy 0.6789
Epoch 19 Batch 550 Loss 1.4637 Accuracy 0.6786
Epoch 19 Batch 600 Loss 1.4641 Accuracy 0.6787
Epoch 19 Batch 650 Loss 1.4674 Accuracy 0.6780
Epoch 19 Batch 700 Loss 1.4703 Accuracy 0.6776
Epoch 19 Batch 750 Loss 1.4722 Accuracy 0.6773
Epoch 19 Batch 800 Loss 1.4760 Accuracy 0.6768
Epoch 19 Loss 1.4767 Accuracy 0.6766
Time taken for 1 epoch: 46.45 secs

Epoch 20 Batch 0 Loss 1.3065 Accuracy 0.7057
Epoch 20 Batch 50 Loss 1.3843 Accuracy 0.6909
Epoch 20 Batch 100 Loss 1.3941 Accuracy 0.6891
Epoch 20 Batch 150 Loss 1.3995 Accuracy 0.6883
Epoch 20 Batch 200 Loss 1.3997 Accuracy 0.6888
Epoch 20 Batch 250 Loss 1.4033 Accuracy 0.6884
Epoch 20 Batch 300 Loss 1.4076 Accuracy 0.6873
Epoch 20 Batch 350 Loss 1.4130 Accuracy 0.6864
Epoch 20 Batch 400 Loss 1.4144 Accuracy 0.6862
Epoch 20 Batch 450 Loss 1.4186 Accuracy 0.6853
Epoch 20 Batch 500 Loss 1.4206 Accuracy 0.6851
Epoch 20 Batch 550 Loss 1.4225 Accuracy 0.6847
Epoch 20 Batch 600 Loss 1.4253 Accuracy 0.6843
Epoch 20 Batch 650 Loss 1.4299 Accuracy 0.6835
Epoch 20 Batch 700 Loss 1.4324 Accuracy 0.6831
Epoch 20 Batch 750 Loss 1.4376 Accuracy 0.6823
Epoch 20 Batch 800 Loss 1.4405 Accuracy 0.6817
Saving checkpoint for epoch 20 at ./checkpoints/train/ckpt-4
Epoch 20 Loss 1.4410 Accuracy 0.6816
Time taken for 1 epoch: 46.87 secs

推論を実行する

次の手順は推論に使用されます。

  • ポルトガルトークナイザ(使用して入力文をエンコードtokenizers.pt )。これはエンコーダ入力です。
  • デコーダ入力がに初期化される[START]トークン。
  • パディングマスクと先読みマスクを計算します。
  • decoder次にを見て予測を出力するencoder outputと、自身の出力(自己注目)。
  • 予測されたトークンをデコーダー入力に連結し、デコーダーに渡します。
  • このアプローチでは、デコーダーは、予測した前のトークンに基づいて次のトークンを予測します。
class Translator(tf.Module):
  def __init__(self, tokenizers, transformer):
    self.tokenizers = tokenizers
    self.transformer = transformer

  def __call__(self, sentence, max_length=20):
    # input sentence is portuguese, hence adding the start and end token
    assert isinstance(sentence, tf.Tensor)
    if len(sentence.shape) == 0:
      sentence = sentence[tf.newaxis]

    sentence = self.tokenizers.pt.tokenize(sentence).to_tensor()

    encoder_input = sentence

    # as the target is english, the first token to the transformer should be the
    # english start token.
    start_end = self.tokenizers.en.tokenize([''])[0]
    start = start_end[0][tf.newaxis]
    end = start_end[1][tf.newaxis]

    # `tf.TensorArray` is required here (instead of a python list) so that the
    # dynamic-loop can be traced by `tf.function`.
    output_array = tf.TensorArray(dtype=tf.int64, size=0, dynamic_size=True)
    output_array = output_array.write(0, start)

    for i in tf.range(max_length):
      output = tf.transpose(output_array.stack())
      predictions, _ = self.transformer([encoder_input, output], training=False)

      # select the last token from the seq_len dimension
      predictions = predictions[:, -1:, :]  # (batch_size, 1, vocab_size)

      predicted_id = tf.argmax(predictions, axis=-1)

      # concatentate the predicted_id to the output which is given to the decoder
      # as its input.
      output_array = output_array.write(i+1, predicted_id[0])

      if predicted_id == end:
        break

    output = tf.transpose(output_array.stack())
    # output.shape (1, tokens)
    text = tokenizers.en.detokenize(output)[0]  # shape: ()

    tokens = tokenizers.en.lookup(output)[0]

    # `tf.function` prevents us from using the attention_weights that were
    # calculated on the last iteration of the loop. So recalculate them outside
    # the loop.
    _, attention_weights = self.transformer([encoder_input, output[:,:-1]], training=False)

    return text, tokens, attention_weights

このインスタンスの作成Translatorクラスを、数回にそれを試してみます:

translator = Translator(tokenizers, transformer)
def print_translation(sentence, tokens, ground_truth):
  print(f'{"Input:":15s}: {sentence}')
  print(f'{"Prediction":15s}: {tokens.numpy().decode("utf-8")}')
  print(f'{"Ground truth":15s}: {ground_truth}')
sentence = "este é um problema que temos que resolver."
ground_truth = "this is a problem we have to solve ."

translated_text, translated_tokens, attention_weights = translator(
    tf.constant(sentence))
print_translation(sentence, translated_text, ground_truth)
Input:         : este é um problema que temos que resolver.
Prediction     : this is a problem that we have to solve .
Ground truth   : this is a problem we have to solve .
sentence = "os meus vizinhos ouviram sobre esta ideia."
ground_truth = "and my neighboring homes heard about this idea ."

translated_text, translated_tokens, attention_weights = translator(
    tf.constant(sentence))
print_translation(sentence, translated_text, ground_truth)
Input:         : os meus vizinhos ouviram sobre esta ideia.
Prediction     : my neighbors heard about this idea .
Ground truth   : and my neighboring homes heard about this idea .
sentence = "vou então muito rapidamente partilhar convosco algumas histórias de algumas coisas mágicas que aconteceram."
ground_truth = "so i \'ll just share with you some stories very quickly of some magical things that have happened ."

translated_text, translated_tokens, attention_weights = translator(
    tf.constant(sentence))
print_translation(sentence, translated_text, ground_truth)
Input:         : vou então muito rapidamente partilhar convosco algumas histórias de algumas coisas mágicas que aconteceram.
Prediction     : so i ' m going to be very quickly share with you some of the magic stories that happened .
Ground truth   : so i 'll just share with you some stories very quickly of some magical things that have happened .

注意プロット

Translatorクラスのリターンの注目の辞書には、モデルの内部作業を視覚化するために使用することができますマッピングします。

sentence = "este é o primeiro livro que eu fiz."
ground_truth = "this is the first book i've ever done."

translated_text, translated_tokens, attention_weights = translator(
    tf.constant(sentence))
print_translation(sentence, translated_text, ground_truth)
Input:         : este é o primeiro livro que eu fiz.
Prediction     : this is the first book i did .
Ground truth   : this is the first book i've ever done.
def plot_attention_head(in_tokens, translated_tokens, attention):
  # The plot is of the attention when a token was generated.
  # The model didn't generate `<START>` in the output. Skip it.
  translated_tokens = translated_tokens[1:]

  ax = plt.gca()
  ax.matshow(attention)
  ax.set_xticks(range(len(in_tokens)))
  ax.set_yticks(range(len(translated_tokens)))

  labels = [label.decode('utf-8') for label in in_tokens.numpy()]
  ax.set_xticklabels(
      labels, rotation=90)

  labels = [label.decode('utf-8') for label in translated_tokens.numpy()]
  ax.set_yticklabels(labels)
head = 0
# shape: (batch=1, num_heads, seq_len_q, seq_len_k)
attention_heads = tf.squeeze(
  attention_weights['decoder_layer4_block2'], 0)
attention = attention_heads[head]
attention.shape
TensorShape([9, 11])
in_tokens = tf.convert_to_tensor([sentence])
in_tokens = tokenizers.pt.tokenize(in_tokens).to_tensor()
in_tokens = tokenizers.pt.lookup(in_tokens)[0]
in_tokens
<tf.Tensor: shape=(11,), dtype=string, numpy=
array([b'[START]', b'este', b'e', b'o', b'primeiro', b'livro', b'que',
       b'eu', b'fiz', b'.', b'[END]'], dtype=object)>
translated_tokens
<tf.Tensor: shape=(10,), dtype=string, numpy=
array([b'[START]', b'this', b'is', b'the', b'first', b'book', b'i',
       b'did', b'.', b'[END]'], dtype=object)>
plot_attention_head(in_tokens, translated_tokens, attention)

png

def plot_attention_weights(sentence, translated_tokens, attention_heads):
  in_tokens = tf.convert_to_tensor([sentence])
  in_tokens = tokenizers.pt.tokenize(in_tokens).to_tensor()
  in_tokens = tokenizers.pt.lookup(in_tokens)[0]
  in_tokens

  fig = plt.figure(figsize=(16, 8))

  for h, head in enumerate(attention_heads):
    ax = fig.add_subplot(2, 4, h+1)

    plot_attention_head(in_tokens, translated_tokens, head)

    ax.set_xlabel(f'Head {h+1}')

  plt.tight_layout()
  plt.show()
plot_attention_weights(sentence, translated_tokens,
                       attention_weights['decoder_layer4_block2'][0])

png

モデルはなじみのない言葉でも大丈夫です。 「トリケラトプス」も「百科事典」も入力データセットに含まれておらず、共有語彙がなくても、モデルはそれらを音訳することをほとんど学習します。

sentence = "Eu li sobre triceratops na enciclopédia."
ground_truth = "I read about triceratops in the encyclopedia."

translated_text, translated_tokens, attention_weights = translator(
    tf.constant(sentence))
print_translation(sentence, translated_text, ground_truth)

plot_attention_weights(sentence, translated_tokens,
                       attention_weights['decoder_layer4_block2'][0])
Input:         : Eu li sobre triceratops na enciclopédia.
Prediction     : i read about trivalopat nairconcissus in the encyclo
Ground truth   : I read about triceratops in the encyclopedia.

png

書き出す

その推論モデルでは、としてそれをエクスポートしますので、次の、働いているtf.saved_model

これを行うには、さらに別の中でそれをラップtf.Moduleとサブクラス、今回tf.function__call__メソッド:

class ExportTranslator(tf.Module):
  def __init__(self, translator):
    self.translator = translator

  @tf.function(input_signature=[tf.TensorSpec(shape=[], dtype=tf.string)])
  def __call__(self, sentence):
    (result, 
     tokens,
     attention_weights) = self.translator(sentence, max_length=100)

    return result

上記でtf.functionのみ出力文が返されます。おかげ非厳格な実行tf.function不要な値が計算されることはありません。

translator = ExportTranslator(translator)

モデルは、使用して予測をデコードしているのでtf.argmax予測を決定論的です。元のモデルとそのから再ロード1 SavedModel 、同一の予測を与える必要があります。

translator("este é o primeiro livro que eu fiz.").numpy()
b'this is the first book i did .'
tf.saved_model.save(translator, export_dir='translator')
2021-11-02 15:48:30.232789: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:absl:Found untraced functions such as embedding_4_layer_call_and_return_conditional_losses, embedding_4_layer_call_fn, dropout_37_layer_call_and_return_conditional_losses, dropout_37_layer_call_fn, embedding_5_layer_call_and_return_conditional_losses while saving (showing 5 of 560). These functions will not be directly callable after loading.
reloaded = tf.saved_model.load('translator')
reloaded("este é o primeiro livro que eu fiz.").numpy()
b'this is the first book i did .'

概要

このチュートリアルでは、位置エンコーディング、マルチヘッドアテンション、マスキングの重要性、およびトランスフォーマーの作成方法について学習しました。

別のデータセットを使用してトランスフォーマーをトレーニングしてみてください。上記のハイパーパラメータを変更して、ベーストランスまたはトランスXLを作成することもできます。また、作成するために、ここで定義された層を使用することができますBERT美術モデルの列車の状態を。さらに、ビーム検索を実装して、より良い予測を得ることができます。