مساعدة في حماية الحاجز المرجاني العظيم مع TensorFlow على Kaggle تاريخ التحدي

نموذج المحولات لفهم اللغة

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثبتحميل دفتر

هذا البرنامج التعليمي القطارات و نموذج محول لترجمة البرتغالية إلى الإنجليزية مجموعة البيانات . وهذا مثال المتقدمة التي يفترض معرفة الجيل النص و الاهتمام .

الفكرة الأساسية وراء نموذج محول هو الاهتمام بالنفس، والقدرة على حضور إلى مواقع مختلفة من تسلسل المدخلات لحساب تمثيل هذا التسلسل. محول يخلق أكوام من طبقات الاهتمام الذاتي وهو موضح أدناه في الأقسام مقيس الاهتمام نقطة المنتج والاهتمام متعدد الرأس.

ومقابض نموذج محول المدخلات متغير الحجم باستخدام أكوام من طبقات الاهتمام الذاتي بدلا من 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
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 .

ترميز النص وكشفه

لا يمكنك تدريب النموذج مباشرة على النص. يجب تحويل النص إلى بعض التمثيل الرقمي أولاً. عادةً ما تقوم بتحويل النص إلى تسلسلات من معرفات الرمز المميز ، والتي تُستخدم كفهارس في عملية دمج.

ويتجلى واحدة لتنفيذ شعبية في Subword tokenizer تعليمي يبني tokenizers subword ( 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 يحتوي على اثنين من 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 طريقة تحويل مجموعة من السلاسل ل-دفعة مبطن من معرفات رمزية. تقسم هذه الطريقة علامات الترقيم والأحرف الصغيرة و unicode - تطبيع الإدخال قبل الرمز المميز. هذا التوحيد غير مرئي هنا لأن بيانات الإدخال موحدة بالفعل.

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 محاولات طريقة لتحويل هذه معرفات رمزية إلى نص مقروء الإنسان:

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 المتحولين طريقة من معرفات رمزية إلى نص رمزي:

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 حيث تكون الرموز المميزة ذات المعنى المماثل أقرب إلى بعضها البعض. لكن الزخارف لا تشفر الموضع النسبي للرموز في الجملة. حتى بعد إضافة الترميز الموضعية، الرموز سوف يكون أقرب إلى بعضها البعض على أساس التشابه في معناها ومكانتها في الحكم، في الفضاء د الأبعاد.

صيغة حساب الترميز الموضعي هي كما يلي:

\[\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)

بي إن جي

قناع

قم بإخفاء جميع رموز اللوحة في مجموعة التسلسل. يضمن أن النموذج لا يتعامل مع الحشو كإدخال. يشير القناع حيث القيمة وسادة 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_dot_product_attention

تأخذ وظيفة الانتباه التي يستخدمها المحول ثلاثة مدخلات: Q (استعلام) ، K (مفتاح) ، V (قيمة). المعادلة المستخدمة لحساب أوزان الانتباه هي:

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

يتم قياس انتباه المنتج النقطي بواسطة عامل الجذر التربيعي للعمق. يتم إجراء ذلك نظرًا لقيم العمق الكبيرة ، حيث ينمو المنتج النقطي بشكل كبير مما يدفع وظيفة softmax حيث تحتوي على تدرجات صغيرة مما يؤدي إلى الحصول على softmax شديد الصلابة.

على سبيل المثال، نرى أن Q و K لديها متوسط 0 والتباين 1. منها ضرب المصفوفات سيكون متوسط 0 والتباين من dk . لذلك الجذر التربيعي ل dk يستخدم لتوسيع نطاق، حتى تحصل على تباين ثابت بغض النظر عن قيمة dk . إذا كان التباين منخفضًا جدًا ، فقد يكون الناتج مسطحًا جدًا للتحسين بشكل فعال. إذا كان التباين مرتفعًا جدًا ، فقد يتشبع softmax عند التهيئة مما يجعل من الصعب التعلم.

يتم ضرب القناع بـ -1e9 (قريب من اللانهاية السالبة). يتم ذلك لأن القناع يتم تلخيصه بمضاعفة المصفوفة المقاسة لـ Q و K ويتم تطبيقه على الفور قبل softmax. الهدف هو التخلص من هذه الخلايا ، وتكون المدخلات السلبية الكبيرة لـ 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

نظرًا لأن تطبيع softmax يتم على 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)

متعدد الرؤوس الانتباه

متعدد الرؤوس الانتباه

يتكون الاهتمام متعدد الرؤوس من أربعة أجزاء:

  • طبقات خطية.
  • تحجيم الانتباه إلى المنتج النقطي.
  • الطبقة الخطية النهائية.

كل كتلة انتباه متعددة الرؤوس تحصل على ثلاثة مدخلات ؛ 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 طبقة لمحاولة الخروج. في كل موقع في التسلسل، y ، و MultiHeadAttention تدير جميع رؤساء الاهتمام 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 طبقات التشفير الذي يولد يبلغ حجم انتاجها لكل رمز في التسلسل.
  • تهتم وحدة فك التشفير بإخراج جهاز التشفير ومدخلاته الخاصة (الاهتمام الذاتي) للتنبؤ بالكلمة التالية.

طبقة التشفير

تتكون كل طبقة تشفير من طبقات فرعية:

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

بي إن جي

الخسارة والمقاييس

نظرًا لأن التسلسلات المستهدفة مبطنة ، فمن المهم تطبيق قناع حشو عند حساب الخسارة.

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

تشغيل الاستدلال

يتم استخدام الخطوات التالية للاستدلال:

  • ترميز الجملة المدخلات باستخدام tokenizer البرتغالية ( 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)

بي إن جي

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

بي إن جي

النموذج لا بأس به على الكلمات غير المألوفة. لا توجد "triceratops" أو "encyclopedia" في مجموعة بيانات الإدخال ويكاد النموذج يتعلم ترجمتها صوتيًا ، حتى بدون استخدام مفردات مشتركة:

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.

بي إن جي

يصدر

يعمل هذا النموذج الاستدلال، لذلك القادم سوف تصديره باعتباره 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-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 عن طريق تغيير المعلمات التشعبية أعلاه. يمكنك أيضا استخدام طبقات محددة هنا لإنشاء بيرت والقطار دولة من نماذج الفن. علاوة على ذلك ، يمكنك تنفيذ البحث بالحزمة للحصول على تنبؤات أفضل.