언어 이해를위한 변환기 모델

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서 소스 보기노트북 다운로드

이 튜토리얼 기차는 변압기 모델 번역하는 포르투갈어 영어로 데이터 집합을 . 이 지식 가정 고급 예입니다 텍스트 생성관심을 .

변압기 모델 뒤에 핵심 아이디어는 자기의 관심을 그 시퀀스의 표현을 계산하기 입력 시퀀스의 다른 위치에 참석하기 위해 -THE 수 있습니다. 변압기는 자기 관심 층의 스택을 만들고 내적 관심과 멀티 헤드의 관심을 스케일 섹션에서 설명한다.

대신에 자기 관심 층의 스택을 사용하여 변압기 모델 핸들 변수 크기의 입력 RNNs 또는 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
2021-08-11 18:06:01.275429: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
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']
2021-08-11 18:06:06.574219: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcuda.so.1
2021-08-11 18:06:07.217445: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.218327: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-08-11 18:06:07.218366: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-08-11 18:06:07.221506: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2021-08-11 18:06:07.221620: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
2021-08-11 18:06:07.222729: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcufft.so.10
2021-08-11 18:06:07.223084: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcurand.so.10
2021-08-11 18:06:07.224143: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusolver.so.11
2021-08-11 18:06:07.225154: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusparse.so.11
2021-08-11 18:06:07.225371: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudnn.so.8
2021-08-11 18:06:07.225496: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.226385: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.227265: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
2021-08-11 18:06:07.227758: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-08-11 18:06:07.228383: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.229369: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-08-11 18:06:07.229453: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.230338: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.231219: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
2021-08-11 18:06:07.231261: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-08-11 18:06:07.828832: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1258] Device interconnect StreamExecutor with strength 1 edge matrix:
2021-08-11 18:06:07.828868: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1264]      0 
2021-08-11 18:06:07.828877: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1277] 0:   N 
2021-08-11 18:06:07.829113: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.830098: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.831030: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-08-11 18:06:07.831854: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1418] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 14646 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0)

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'))
2021-08-11 18:06:07.938998: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:176] None of the MLIR Optimization Passes are enabled (registered 2)
2021-08-11 18:06:07.939525: I tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2000165000 Hz
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 시퀀스로 변환합니다.

하나의 인기 구현은에서 증명되고 튜토리얼 토크 나이 Subword subword tokenizers (빌드 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
'./ted_hrlr_translate_pt_en_converter.zip'
tokenizers = tf.saved_model.load(model_name)

tf.saved_model 두 개의 텍스트 tokenizers, 영어 하나와 포르투갈어를 포함하고 있습니다. 둘 다 동일한 방법을 사용합니다.

[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]']]>

여기에서 토크나이저의 "하위 단어" 측면을 볼 수 있습니다. "searchability"라는 단어는 "search ##ability"로, "serendipity"라는 단어는 "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)>

미리보기 마스크는 시퀀스에서 미래 토큰을 마스킹하는 데 사용됩니다. 즉, 마스크는 사용해서는 안 되는 항목을 나타냅니다.

즉, 세 번째 토큰을 예측하기 위해 첫 번째와 두 번째 토큰만 사용됩니다. 네 번째 토큰을 예측하는 것과 유사하게 첫 번째, 두 번째 및 세 번째 토큰만 사용됩니다.

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 내적 주의

scaled_dot_product_attention

변환기에서 사용하는 어텐션 기능은 Q(쿼리), K(키), V(값)의 세 가지 입력을 받습니다. 주의 가중치를 계산하는 데 사용되는 방정식은 다음과 같습니다.

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

내적 주의는 깊이의 제곱근 계수로 조정됩니다. 이것은 깊이 값이 크면 내적(dot product)이 큰 크기로 커지기 때문에 softmax 함수를 밀어서 기울기가 작은 경우 매우 단단한 softmax가 생성됩니다.

예를 들어 것을 고려 QK 0이고 분산 평균 것이다 0과 1 그들의 행렬 곱셈의 차이의 평균이 dk . 그래서의 제곱근 dk 관계없이 값의 일관성 분산을 얻을 수 있도록, 스케일링에 사용되는 dk . 분산이 너무 낮으면 출력이 너무 평평하여 효과적으로 최적화할 수 없습니다. 분산이 너무 높으면 softmax가 초기화 시 포화되어 학습하기 어려울 수 있습니다.

마스크에 -1e9를 곱합니다(음의 무한대에 가까움). 이것은 마스크가 Q와 K의 스케일된 행렬 곱으로 합산되고 softmax 직전에 적용되기 때문에 수행됩니다. 목표는 이러한 셀을 0으로 만드는 것이며 softmax에 대한 큰 음수 입력은 출력에서 ​​거의 0에 가깝습니다.

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

softmax normalization이 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)
2021-08-11 18:06:14.236081: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
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)
2021-08-11 18:06:14.623940: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
# 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)

멀티 헤드 주의

멀티 헤드 주의

다중 머리 주의는 네 부분으로 구성됩니다.

  • 선형 레이어 및 머리로 분할.
  • 확장된 내적 주의.
  • 머리 연결.
  • 최종 선형 레이어.

각 다중 헤드 주의 블록은 3개의 입력을 받습니다. Q(쿼리), K(키), V(값). 이들은 선형(밀도) 레이어를 통해 배치되고 여러 헤드로 분할됩니다.

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]))

포인트 와이즈 피드포워드 네트워크

포인트 와이즈 피드 포워드 네트워크는 사이에 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 시퀀스에서 각각의 토큰에 대한 출력을 생성하는 인코더 층.
  • 디코더는 인코더의 출력과 자체 입력(self-attention)에 주의하여 다음 단어를 예측합니다.

인코더 레이어

각 인코더 계층은 하위 계층으로 구성됩니다.

  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는 인코더 출력을 수신하므로 주의 가중치는 인코더의 출력을 기반으로 디코더의 입력에 주어진 중요도를 나타냅니다. 즉, 디코더는 인코더 출력을 보고 자체 출력에 자가 참여하여 다음 토큰을 예측합니다. 위의 Scaled Dot Product Attention 섹션에서 데모를 참조하세요.

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]))

변압기 만들기

Transformer는 인코더, 디코더 및 최종 선형 레이어로 구성됩니다. 디코더의 출력은 선형 레이어에 대한 입력이고 출력은 반환됩니다.

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_input , tar_real 예측되어야하는 다음의 토큰을 포함한다.

예를 들어, sentence = "정글에서 SOS 사자 EOS을 자고있다"

tar_inp = "정글에서 SOS 사자는 자고있다"

tar_real = "정글에서 사자 EOS을 자고있다"

변환기는 자동 회귀 모델입니다. 변환기는 한 번에 한 부분씩 예측하고 지금까지의 출력을 사용하여 다음에 수행할 작업을 결정합니다.

이 예제를 훈련하는 동안 교사 강요합니다 (처럼 사용하는 텍스트 생성 튜토리얼 ). 교사 강제는 모델이 현재 시간 단계에서 예측하는 것과 상관없이 실제 출력을 다음 시간 단계로 전달합니다.

변압기는 예측대로 각 토큰, 자기의 관심은 다음 토큰을 예측하는 더 나은에 입력 시퀀스의 이전 토큰 볼 수 있습니다.

모델이 예상 출력을 엿보는 것을 방지하기 위해 모델은 미리보기 마스크를 사용합니다.

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.8834 Accuracy 0.0000
Epoch 1 Batch 50 Loss 8.8171 Accuracy 0.0003
Epoch 1 Batch 100 Loss 8.7146 Accuracy 0.0117
Epoch 1 Batch 150 Loss 8.6025 Accuracy 0.0238
Epoch 1 Batch 200 Loss 8.4625 Accuracy 0.0317
Epoch 1 Batch 250 Loss 8.2914 Accuracy 0.0398
Epoch 1 Batch 300 Loss 8.1014 Accuracy 0.0487
Epoch 1 Batch 350 Loss 7.9027 Accuracy 0.0587
Epoch 1 Batch 400 Loss 7.7155 Accuracy 0.0669
Epoch 1 Batch 450 Loss 7.5463 Accuracy 0.0746
Epoch 1 Batch 500 Loss 7.3971 Accuracy 0.0814
Epoch 1 Batch 550 Loss 7.2641 Accuracy 0.0878
Epoch 1 Batch 600 Loss 7.1401 Accuracy 0.0944
Epoch 1 Batch 650 Loss 7.0245 Accuracy 0.1011
Epoch 1 Batch 700 Loss 6.9162 Accuracy 0.1077
Epoch 1 Batch 750 Loss 6.8175 Accuracy 0.1136
Epoch 1 Batch 800 Loss 6.7260 Accuracy 0.1192
Epoch 1 Loss 6.7104 Accuracy 0.1201
Time taken for 1 epoch: 63.51 secs

Epoch 2 Batch 0 Loss 5.0207 Accuracy 0.2346
Epoch 2 Batch 50 Loss 5.2307 Accuracy 0.2122
Epoch 2 Batch 100 Loss 5.2121 Accuracy 0.2158
Epoch 2 Batch 150 Loss 5.1723 Accuracy 0.2200
Epoch 2 Batch 200 Loss 5.1427 Accuracy 0.2231
Epoch 2 Batch 250 Loss 5.1162 Accuracy 0.2259
Epoch 2 Batch 300 Loss 5.0927 Accuracy 0.2283
Epoch 2 Batch 350 Loss 5.0732 Accuracy 0.2303
Epoch 2 Batch 400 Loss 5.0555 Accuracy 0.2322
Epoch 2 Batch 450 Loss 5.0329 Accuracy 0.2345
Epoch 2 Batch 500 Loss 5.0156 Accuracy 0.2357
Epoch 2 Batch 550 Loss 4.9974 Accuracy 0.2373
Epoch 2 Batch 600 Loss 4.9774 Accuracy 0.2391
Epoch 2 Batch 650 Loss 4.9573 Accuracy 0.2408
Epoch 2 Batch 700 Loss 4.9408 Accuracy 0.2422
Epoch 2 Batch 750 Loss 4.9237 Accuracy 0.2436
Epoch 2 Batch 800 Loss 4.9054 Accuracy 0.2451
Epoch 2 Loss 4.9014 Accuracy 0.2455
Time taken for 1 epoch: 50.09 secs

Epoch 3 Batch 0 Loss 4.4613 Accuracy 0.2930
Epoch 3 Batch 50 Loss 4.5732 Accuracy 0.2737
Epoch 3 Batch 100 Loss 4.5668 Accuracy 0.2750
Epoch 3 Batch 150 Loss 4.5608 Accuracy 0.2747
Epoch 3 Batch 200 Loss 4.5519 Accuracy 0.2754
Epoch 3 Batch 250 Loss 4.5469 Accuracy 0.2755
Epoch 3 Batch 300 Loss 4.5367 Accuracy 0.2761
Epoch 3 Batch 350 Loss 4.5232 Accuracy 0.2777
Epoch 3 Batch 400 Loss 4.5089 Accuracy 0.2794
Epoch 3 Batch 450 Loss 4.4975 Accuracy 0.2807
Epoch 3 Batch 500 Loss 4.4818 Accuracy 0.2827
Epoch 3 Batch 550 Loss 4.4671 Accuracy 0.2844
Epoch 3 Batch 600 Loss 4.4516 Accuracy 0.2862
Epoch 3 Batch 650 Loss 4.4376 Accuracy 0.2879
Epoch 3 Batch 700 Loss 4.4223 Accuracy 0.2897
Epoch 3 Batch 750 Loss 4.4060 Accuracy 0.2916
Epoch 3 Batch 800 Loss 4.3902 Accuracy 0.2936
Epoch 3 Loss 4.3880 Accuracy 0.2939
Time taken for 1 epoch: 49.94 secs

Epoch 4 Batch 0 Loss 4.0719 Accuracy 0.3241
Epoch 4 Batch 50 Loss 4.0570 Accuracy 0.3289
Epoch 4 Batch 100 Loss 4.0280 Accuracy 0.3336
Epoch 4 Batch 150 Loss 4.0128 Accuracy 0.3356
Epoch 4 Batch 200 Loss 3.9983 Accuracy 0.3381
Epoch 4 Batch 250 Loss 3.9811 Accuracy 0.3405
Epoch 4 Batch 300 Loss 3.9700 Accuracy 0.3419
Epoch 4 Batch 350 Loss 3.9590 Accuracy 0.3435
Epoch 4 Batch 400 Loss 3.9454 Accuracy 0.3455
Epoch 4 Batch 450 Loss 3.9319 Accuracy 0.3472
Epoch 4 Batch 500 Loss 3.9187 Accuracy 0.3488
Epoch 4 Batch 550 Loss 3.9056 Accuracy 0.3505
Epoch 4 Batch 600 Loss 3.8928 Accuracy 0.3523
Epoch 4 Batch 650 Loss 3.8805 Accuracy 0.3541
Epoch 4 Batch 700 Loss 3.8652 Accuracy 0.3561
Epoch 4 Batch 750 Loss 3.8496 Accuracy 0.3581
Epoch 4 Batch 800 Loss 3.8367 Accuracy 0.3598
Epoch 4 Loss 3.8342 Accuracy 0.3602
Time taken for 1 epoch: 50.11 secs

Epoch 5 Batch 0 Loss 3.3066 Accuracy 0.4257
Epoch 5 Batch 50 Loss 3.5243 Accuracy 0.3967
Epoch 5 Batch 100 Loss 3.4975 Accuracy 0.4005
Epoch 5 Batch 150 Loss 3.4915 Accuracy 0.4017
Epoch 5 Batch 200 Loss 3.4911 Accuracy 0.4016
Epoch 5 Batch 250 Loss 3.4790 Accuracy 0.4037
Epoch 5 Batch 300 Loss 3.4692 Accuracy 0.4048
Epoch 5 Batch 350 Loss 3.4599 Accuracy 0.4059
Epoch 5 Batch 400 Loss 3.4491 Accuracy 0.4074
Epoch 5 Batch 450 Loss 3.4356 Accuracy 0.4092
Epoch 5 Batch 500 Loss 3.4243 Accuracy 0.4106
Epoch 5 Batch 550 Loss 3.4159 Accuracy 0.4115
Epoch 5 Batch 600 Loss 3.4083 Accuracy 0.4124
Epoch 5 Batch 650 Loss 3.4002 Accuracy 0.4134
Epoch 5 Batch 700 Loss 3.3922 Accuracy 0.4146
Epoch 5 Batch 750 Loss 3.3824 Accuracy 0.4158
Epoch 5 Batch 800 Loss 3.3739 Accuracy 0.4168
Saving checkpoint for epoch 5 at ./checkpoints/train/ckpt-1
Epoch 5 Loss 3.3715 Accuracy 0.4171
Time taken for 1 epoch: 50.52 secs

Epoch 6 Batch 0 Loss 3.2623 Accuracy 0.4515
Epoch 6 Batch 50 Loss 3.1389 Accuracy 0.4400
Epoch 6 Batch 100 Loss 3.1121 Accuracy 0.4445
Epoch 6 Batch 150 Loss 3.0973 Accuracy 0.4471
Epoch 6 Batch 200 Loss 3.0844 Accuracy 0.4496
Epoch 6 Batch 250 Loss 3.0725 Accuracy 0.4519
Epoch 6 Batch 300 Loss 3.0648 Accuracy 0.4533
Epoch 6 Batch 350 Loss 3.0572 Accuracy 0.4545
Epoch 6 Batch 400 Loss 3.0523 Accuracy 0.4551
Epoch 6 Batch 450 Loss 3.0423 Accuracy 0.4568
Epoch 6 Batch 500 Loss 3.0327 Accuracy 0.4582
Epoch 6 Batch 550 Loss 3.0237 Accuracy 0.4594
Epoch 6 Batch 600 Loss 3.0123 Accuracy 0.4609
Epoch 6 Batch 650 Loss 3.0031 Accuracy 0.4622
Epoch 6 Batch 700 Loss 2.9950 Accuracy 0.4634
Epoch 6 Batch 750 Loss 2.9881 Accuracy 0.4646
Epoch 6 Batch 800 Loss 2.9792 Accuracy 0.4658
Epoch 6 Loss 2.9779 Accuracy 0.4660
Time taken for 1 epoch: 49.88 secs

Epoch 7 Batch 0 Loss 2.6813 Accuracy 0.5090
Epoch 7 Batch 50 Loss 2.7174 Accuracy 0.4964
Epoch 7 Batch 100 Loss 2.7045 Accuracy 0.4980
Epoch 7 Batch 150 Loss 2.6982 Accuracy 0.4991
Epoch 7 Batch 200 Loss 2.6947 Accuracy 0.5002
Epoch 7 Batch 250 Loss 2.6909 Accuracy 0.5007
Epoch 7 Batch 300 Loss 2.6822 Accuracy 0.5023
Epoch 7 Batch 350 Loss 2.6765 Accuracy 0.5036
Epoch 7 Batch 400 Loss 2.6743 Accuracy 0.5043
Epoch 7 Batch 450 Loss 2.6693 Accuracy 0.5050
Epoch 7 Batch 500 Loss 2.6641 Accuracy 0.5055
Epoch 7 Batch 550 Loss 2.6581 Accuracy 0.5063
Epoch 7 Batch 600 Loss 2.6516 Accuracy 0.5074
Epoch 7 Batch 650 Loss 2.6488 Accuracy 0.5080
Epoch 7 Batch 700 Loss 2.6465 Accuracy 0.5087
Epoch 7 Batch 750 Loss 2.6440 Accuracy 0.5091
Epoch 7 Batch 800 Loss 2.6428 Accuracy 0.5093
Epoch 7 Loss 2.6422 Accuracy 0.5094
Time taken for 1 epoch: 50.18 secs

Epoch 8 Batch 0 Loss 2.4922 Accuracy 0.5348
Epoch 8 Batch 50 Loss 2.4303 Accuracy 0.5361
Epoch 8 Batch 100 Loss 2.4228 Accuracy 0.5369
Epoch 8 Batch 150 Loss 2.4262 Accuracy 0.5373
Epoch 8 Batch 200 Loss 2.4359 Accuracy 0.5361
Epoch 8 Batch 250 Loss 2.4285 Accuracy 0.5373
Epoch 8 Batch 300 Loss 2.4315 Accuracy 0.5368
Epoch 8 Batch 350 Loss 2.4285 Accuracy 0.5368
Epoch 8 Batch 400 Loss 2.4265 Accuracy 0.5373
Epoch 8 Batch 450 Loss 2.4289 Accuracy 0.5371
Epoch 8 Batch 500 Loss 2.4252 Accuracy 0.5377
Epoch 8 Batch 550 Loss 2.4228 Accuracy 0.5382
Epoch 8 Batch 600 Loss 2.4201 Accuracy 0.5386
Epoch 8 Batch 650 Loss 2.4199 Accuracy 0.5388
Epoch 8 Batch 700 Loss 2.4177 Accuracy 0.5394
Epoch 8 Batch 750 Loss 2.4135 Accuracy 0.5400
Epoch 8 Batch 800 Loss 2.4100 Accuracy 0.5407
Epoch 8 Loss 2.4093 Accuracy 0.5407
Time taken for 1 epoch: 50.20 secs

Epoch 9 Batch 0 Loss 2.1292 Accuracy 0.5823
Epoch 9 Batch 50 Loss 2.2265 Accuracy 0.5628
Epoch 9 Batch 100 Loss 2.2201 Accuracy 0.5643
Epoch 9 Batch 150 Loss 2.2378 Accuracy 0.5617
Epoch 9 Batch 200 Loss 2.2386 Accuracy 0.5619
Epoch 9 Batch 250 Loss 2.2369 Accuracy 0.5620
Epoch 9 Batch 300 Loss 2.2367 Accuracy 0.5624
Epoch 9 Batch 350 Loss 2.2420 Accuracy 0.5618
Epoch 9 Batch 400 Loss 2.2416 Accuracy 0.5621
Epoch 9 Batch 450 Loss 2.2421 Accuracy 0.5620
Epoch 9 Batch 500 Loss 2.2397 Accuracy 0.5624
Epoch 9 Batch 550 Loss 2.2369 Accuracy 0.5631
Epoch 9 Batch 600 Loss 2.2350 Accuracy 0.5636
Epoch 9 Batch 650 Loss 2.2332 Accuracy 0.5640
Epoch 9 Batch 700 Loss 2.2332 Accuracy 0.5641
Epoch 9 Batch 750 Loss 2.2344 Accuracy 0.5641
Epoch 9 Batch 800 Loss 2.2331 Accuracy 0.5644
Epoch 9 Loss 2.2332 Accuracy 0.5644
Time taken for 1 epoch: 49.98 secs

Epoch 10 Batch 0 Loss 1.9345 Accuracy 0.6113
Epoch 10 Batch 50 Loss 2.0750 Accuracy 0.5826
Epoch 10 Batch 100 Loss 2.0660 Accuracy 0.5854
Epoch 10 Batch 150 Loss 2.0716 Accuracy 0.5848
Epoch 10 Batch 200 Loss 2.0771 Accuracy 0.5843
Epoch 10 Batch 250 Loss 2.0872 Accuracy 0.5827
Epoch 10 Batch 300 Loss 2.0928 Accuracy 0.5822
Epoch 10 Batch 350 Loss 2.0927 Accuracy 0.5824
Epoch 10 Batch 400 Loss 2.0932 Accuracy 0.5823
Epoch 10 Batch 450 Loss 2.0987 Accuracy 0.5815
Epoch 10 Batch 500 Loss 2.0972 Accuracy 0.5817
Epoch 10 Batch 550 Loss 2.0952 Accuracy 0.5821
Epoch 10 Batch 600 Loss 2.0951 Accuracy 0.5823
Epoch 10 Batch 650 Loss 2.0961 Accuracy 0.5824
Epoch 10 Batch 700 Loss 2.0953 Accuracy 0.5825
Epoch 10 Batch 750 Loss 2.0957 Accuracy 0.5826
Epoch 10 Batch 800 Loss 2.0964 Accuracy 0.5827
Saving checkpoint for epoch 10 at ./checkpoints/train/ckpt-2
Epoch 10 Loss 2.0967 Accuracy 0.5826
Time taken for 1 epoch: 50.31 secs

Epoch 11 Batch 0 Loss 1.8751 Accuracy 0.6013
Epoch 11 Batch 50 Loss 1.9732 Accuracy 0.5984
Epoch 11 Batch 100 Loss 1.9554 Accuracy 0.6015
Epoch 11 Batch 150 Loss 1.9659 Accuracy 0.6000
Epoch 11 Batch 200 Loss 1.9657 Accuracy 0.6003
Epoch 11 Batch 250 Loss 1.9708 Accuracy 0.5998
Epoch 11 Batch 300 Loss 1.9733 Accuracy 0.5998
Epoch 11 Batch 350 Loss 1.9698 Accuracy 0.6006
Epoch 11 Batch 400 Loss 1.9696 Accuracy 0.6006
Epoch 11 Batch 450 Loss 1.9692 Accuracy 0.6006
Epoch 11 Batch 500 Loss 1.9704 Accuracy 0.6008
Epoch 11 Batch 550 Loss 1.9720 Accuracy 0.6006
Epoch 11 Batch 600 Loss 1.9744 Accuracy 0.6002
Epoch 11 Batch 650 Loss 1.9782 Accuracy 0.5996
Epoch 11 Batch 700 Loss 1.9801 Accuracy 0.5993
Epoch 11 Batch 750 Loss 1.9810 Accuracy 0.5993
Epoch 11 Batch 800 Loss 1.9847 Accuracy 0.5988
Epoch 11 Loss 1.9847 Accuracy 0.5988
Time taken for 1 epoch: 50.20 secs

Epoch 12 Batch 0 Loss 1.8019 Accuracy 0.6165
Epoch 12 Batch 50 Loss 1.8706 Accuracy 0.6121
Epoch 12 Batch 100 Loss 1.8494 Accuracy 0.6170
Epoch 12 Batch 150 Loss 1.8620 Accuracy 0.6141
Epoch 12 Batch 200 Loss 1.8596 Accuracy 0.6152
Epoch 12 Batch 250 Loss 1.8639 Accuracy 0.6149
Epoch 12 Batch 300 Loss 1.8700 Accuracy 0.6141
Epoch 12 Batch 350 Loss 1.8721 Accuracy 0.6137
Epoch 12 Batch 400 Loss 1.8756 Accuracy 0.6137
Epoch 12 Batch 450 Loss 1.8741 Accuracy 0.6140
Epoch 12 Batch 500 Loss 1.8762 Accuracy 0.6135
Epoch 12 Batch 550 Loss 1.8781 Accuracy 0.6136
Epoch 12 Batch 600 Loss 1.8792 Accuracy 0.6137
Epoch 12 Batch 650 Loss 1.8813 Accuracy 0.6135
Epoch 12 Batch 700 Loss 1.8833 Accuracy 0.6132
Epoch 12 Batch 750 Loss 1.8870 Accuracy 0.6128
Epoch 12 Batch 800 Loss 1.8878 Accuracy 0.6127
Epoch 12 Loss 1.8877 Accuracy 0.6128
Time taken for 1 epoch: 50.11 secs

Epoch 13 Batch 0 Loss 1.7577 Accuracy 0.6166
Epoch 13 Batch 50 Loss 1.7580 Accuracy 0.6288
Epoch 13 Batch 100 Loss 1.7815 Accuracy 0.6261
Epoch 13 Batch 150 Loss 1.7886 Accuracy 0.6255
Epoch 13 Batch 200 Loss 1.7870 Accuracy 0.6266
Epoch 13 Batch 250 Loss 1.7852 Accuracy 0.6269
Epoch 13 Batch 300 Loss 1.7886 Accuracy 0.6266
Epoch 13 Batch 350 Loss 1.7887 Accuracy 0.6265
Epoch 13 Batch 400 Loss 1.7909 Accuracy 0.6263
Epoch 13 Batch 450 Loss 1.7928 Accuracy 0.6259
Epoch 13 Batch 500 Loss 1.7948 Accuracy 0.6257
Epoch 13 Batch 550 Loss 1.7940 Accuracy 0.6260
Epoch 13 Batch 600 Loss 1.7980 Accuracy 0.6255
Epoch 13 Batch 650 Loss 1.8034 Accuracy 0.6248
Epoch 13 Batch 700 Loss 1.8055 Accuracy 0.6246
Epoch 13 Batch 750 Loss 1.8079 Accuracy 0.6242
Epoch 13 Batch 800 Loss 1.8100 Accuracy 0.6240
Epoch 13 Loss 1.8095 Accuracy 0.6242
Time taken for 1 epoch: 50.46 secs

Epoch 14 Batch 0 Loss 1.5412 Accuracy 0.6549
Epoch 14 Batch 50 Loss 1.6754 Accuracy 0.6440
Epoch 14 Batch 100 Loss 1.6976 Accuracy 0.6404
Epoch 14 Batch 150 Loss 1.7039 Accuracy 0.6400
Epoch 14 Batch 200 Loss 1.7044 Accuracy 0.6393
Epoch 14 Batch 250 Loss 1.7092 Accuracy 0.6387
Epoch 14 Batch 300 Loss 1.7117 Accuracy 0.6381
Epoch 14 Batch 350 Loss 1.7155 Accuracy 0.6378
Epoch 14 Batch 400 Loss 1.7190 Accuracy 0.6373
Epoch 14 Batch 450 Loss 1.7239 Accuracy 0.6366
Epoch 14 Batch 500 Loss 1.7270 Accuracy 0.6363
Epoch 14 Batch 550 Loss 1.7268 Accuracy 0.6365
Epoch 14 Batch 600 Loss 1.7279 Accuracy 0.6364
Epoch 14 Batch 650 Loss 1.7310 Accuracy 0.6361
Epoch 14 Batch 700 Loss 1.7349 Accuracy 0.6356
Epoch 14 Batch 750 Loss 1.7368 Accuracy 0.6354
Epoch 14 Batch 800 Loss 1.7388 Accuracy 0.6352
Epoch 14 Loss 1.7391 Accuracy 0.6350
Time taken for 1 epoch: 50.06 secs

Epoch 15 Batch 0 Loss 1.4886 Accuracy 0.6655
Epoch 15 Batch 50 Loss 1.6380 Accuracy 0.6488
Epoch 15 Batch 100 Loss 1.6306 Accuracy 0.6508
Epoch 15 Batch 150 Loss 1.6376 Accuracy 0.6498
Epoch 15 Batch 200 Loss 1.6446 Accuracy 0.6488
Epoch 15 Batch 250 Loss 1.6529 Accuracy 0.6472
Epoch 15 Batch 300 Loss 1.6506 Accuracy 0.6480
Epoch 15 Batch 350 Loss 1.6529 Accuracy 0.6476
Epoch 15 Batch 400 Loss 1.6582 Accuracy 0.6466
Epoch 15 Batch 450 Loss 1.6600 Accuracy 0.6462
Epoch 15 Batch 500 Loss 1.6602 Accuracy 0.6461
Epoch 15 Batch 550 Loss 1.6621 Accuracy 0.6460
Epoch 15 Batch 600 Loss 1.6657 Accuracy 0.6455
Epoch 15 Batch 650 Loss 1.6684 Accuracy 0.6452
Epoch 15 Batch 700 Loss 1.6717 Accuracy 0.6447
Epoch 15 Batch 750 Loss 1.6751 Accuracy 0.6442
Epoch 15 Batch 800 Loss 1.6780 Accuracy 0.6438
Saving checkpoint for epoch 15 at ./checkpoints/train/ckpt-3
Epoch 15 Loss 1.6776 Accuracy 0.6439
Time taken for 1 epoch: 50.45 secs

Epoch 16 Batch 0 Loss 1.6809 Accuracy 0.6423
Epoch 16 Batch 50 Loss 1.5821 Accuracy 0.6579
Epoch 16 Batch 100 Loss 1.5793 Accuracy 0.6589
Epoch 16 Batch 150 Loss 1.5799 Accuracy 0.6592
Epoch 16 Batch 200 Loss 1.5882 Accuracy 0.6573
Epoch 16 Batch 250 Loss 1.5968 Accuracy 0.6562
Epoch 16 Batch 300 Loss 1.5993 Accuracy 0.6558
Epoch 16 Batch 350 Loss 1.6046 Accuracy 0.6549
Epoch 16 Batch 400 Loss 1.6066 Accuracy 0.6549
Epoch 16 Batch 450 Loss 1.6089 Accuracy 0.6543
Epoch 16 Batch 500 Loss 1.6086 Accuracy 0.6547
Epoch 16 Batch 550 Loss 1.6116 Accuracy 0.6542
Epoch 16 Batch 600 Loss 1.6148 Accuracy 0.6537
Epoch 16 Batch 650 Loss 1.6167 Accuracy 0.6534
Epoch 16 Batch 700 Loss 1.6182 Accuracy 0.6532
Epoch 16 Batch 750 Loss 1.6223 Accuracy 0.6526
Epoch 16 Batch 800 Loss 1.6257 Accuracy 0.6522
Epoch 16 Loss 1.6262 Accuracy 0.6521
Time taken for 1 epoch: 50.25 secs

Epoch 17 Batch 0 Loss 1.4921 Accuracy 0.6865
Epoch 17 Batch 50 Loss 1.5425 Accuracy 0.6633
Epoch 17 Batch 100 Loss 1.5382 Accuracy 0.6653
Epoch 17 Batch 150 Loss 1.5448 Accuracy 0.6641
Epoch 17 Batch 200 Loss 1.5442 Accuracy 0.6642
Epoch 17 Batch 250 Loss 1.5507 Accuracy 0.6631
Epoch 17 Batch 300 Loss 1.5498 Accuracy 0.6634
Epoch 17 Batch 350 Loss 1.5504 Accuracy 0.6633
Epoch 17 Batch 400 Loss 1.5554 Accuracy 0.6626
Epoch 17 Batch 450 Loss 1.5544 Accuracy 0.6627
Epoch 17 Batch 500 Loss 1.5573 Accuracy 0.6623
Epoch 17 Batch 550 Loss 1.5585 Accuracy 0.6621
Epoch 17 Batch 600 Loss 1.5618 Accuracy 0.6616
Epoch 17 Batch 650 Loss 1.5658 Accuracy 0.6610
Epoch 17 Batch 700 Loss 1.5685 Accuracy 0.6608
Epoch 17 Batch 750 Loss 1.5706 Accuracy 0.6605
Epoch 17 Batch 800 Loss 1.5733 Accuracy 0.6601
Epoch 17 Loss 1.5730 Accuracy 0.6602
Time taken for 1 epoch: 49.99 secs

Epoch 18 Batch 0 Loss 1.3174 Accuracy 0.7121
Epoch 18 Batch 50 Loss 1.4979 Accuracy 0.6729
Epoch 18 Batch 100 Loss 1.5023 Accuracy 0.6712
Epoch 18 Batch 150 Loss 1.4990 Accuracy 0.6719
Epoch 18 Batch 200 Loss 1.5051 Accuracy 0.6705
Epoch 18 Batch 250 Loss 1.5029 Accuracy 0.6709
Epoch 18 Batch 300 Loss 1.5063 Accuracy 0.6706
Epoch 18 Batch 350 Loss 1.5092 Accuracy 0.6701
Epoch 18 Batch 400 Loss 1.5103 Accuracy 0.6702
Epoch 18 Batch 450 Loss 1.5150 Accuracy 0.6692
Epoch 18 Batch 500 Loss 1.5157 Accuracy 0.6690
Epoch 18 Batch 550 Loss 1.5176 Accuracy 0.6686
Epoch 18 Batch 600 Loss 1.5211 Accuracy 0.6682
Epoch 18 Batch 650 Loss 1.5220 Accuracy 0.6681
Epoch 18 Batch 700 Loss 1.5251 Accuracy 0.6676
Epoch 18 Batch 750 Loss 1.5284 Accuracy 0.6671
Epoch 18 Batch 800 Loss 1.5310 Accuracy 0.6667
Epoch 18 Loss 1.5326 Accuracy 0.6664
Time taken for 1 epoch: 50.17 secs

Epoch 19 Batch 0 Loss 1.1448 Accuracy 0.7440
Epoch 19 Batch 50 Loss 1.4359 Accuracy 0.6841
Epoch 19 Batch 100 Loss 1.4299 Accuracy 0.6847
Epoch 19 Batch 150 Loss 1.4454 Accuracy 0.6812
Epoch 19 Batch 200 Loss 1.4525 Accuracy 0.6800
Epoch 19 Batch 250 Loss 1.4549 Accuracy 0.6792
Epoch 19 Batch 300 Loss 1.4585 Accuracy 0.6785
Epoch 19 Batch 350 Loss 1.4612 Accuracy 0.6780
Epoch 19 Batch 400 Loss 1.4655 Accuracy 0.6771
Epoch 19 Batch 450 Loss 1.4698 Accuracy 0.6762
Epoch 19 Batch 500 Loss 1.4731 Accuracy 0.6756
Epoch 19 Batch 550 Loss 1.4752 Accuracy 0.6754
Epoch 19 Batch 600 Loss 1.4789 Accuracy 0.6749
Epoch 19 Batch 650 Loss 1.4824 Accuracy 0.6743
Epoch 19 Batch 700 Loss 1.4861 Accuracy 0.6737
Epoch 19 Batch 750 Loss 1.4904 Accuracy 0.6730
Epoch 19 Batch 800 Loss 1.4922 Accuracy 0.6727
Epoch 19 Loss 1.4918 Accuracy 0.6728
Time taken for 1 epoch: 50.39 secs

Epoch 20 Batch 0 Loss 1.6377 Accuracy 0.6362
Epoch 20 Batch 50 Loss 1.4039 Accuracy 0.6865
Epoch 20 Batch 100 Loss 1.4086 Accuracy 0.6860
Epoch 20 Batch 150 Loss 1.4210 Accuracy 0.6838
Epoch 20 Batch 200 Loss 1.4186 Accuracy 0.6847
Epoch 20 Batch 250 Loss 1.4228 Accuracy 0.6839
Epoch 20 Batch 300 Loss 1.4270 Accuracy 0.6827
Epoch 20 Batch 350 Loss 1.4326 Accuracy 0.6817
Epoch 20 Batch 400 Loss 1.4357 Accuracy 0.6811
Epoch 20 Batch 450 Loss 1.4408 Accuracy 0.6804
Epoch 20 Batch 500 Loss 1.4422 Accuracy 0.6801
Epoch 20 Batch 550 Loss 1.4448 Accuracy 0.6797
Epoch 20 Batch 600 Loss 1.4451 Accuracy 0.6798
Epoch 20 Batch 650 Loss 1.4471 Accuracy 0.6796
Epoch 20 Batch 700 Loss 1.4501 Accuracy 0.6792
Epoch 20 Batch 750 Loss 1.4512 Accuracy 0.6792
Epoch 20 Batch 800 Loss 1.4548 Accuracy 0.6788
Saving checkpoint for epoch 20 at ./checkpoints/train/ckpt-4
Epoch 20 Loss 1.4550 Accuracy 0.6787
Time taken for 1 epoch: 50.33 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 to share some stories of some 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 triopters on the encyclopedia .
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 예측이 결정적한다. 그것에서 다시로드 원래 모델과 하나 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-08-11 18:23:29.706465: 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_fn, embedding_4_layer_call_and_return_conditional_losses, dropout_37_layer_call_fn, dropout_37_layer_call_and_return_conditional_losses, embedding_5_layer_call_fn 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 예술 모델 기차 상태. 또한 더 나은 예측을 위해 빔 검색을 구현할 수 있습니다.