Saltar al contenido

Entrenamiento del modelo de transformador

25 de octubre de 2022


Última actualización el 21 de octubre de 2022

Hemos reunido el modelo completo de Transformer y ahora estamos listos para entrenarlo para la traducción automática neuronal. Haremos uso de un conjunto de datos de entrenamiento para este propósito, que contiene pares de oraciones cortas en inglés y alemán. También revisaremos el papel del enmascaramiento en el cálculo de las métricas de precisión y pérdida durante el proceso de capacitación.

En este tutorial, descubrirá cómo entrenar el modelo de Transformer para la traducción automática neuronal.

Después de completar este tutorial, sabrás:

  • Cómo preparar el conjunto de datos de entrenamiento.
  • Cómo aplicar una máscara de relleno a los cálculos de pérdida y precisión.
  • Cómo entrenar el modelo Transformer.

Empecemos.

Entrenamiento del modelo de transformador
Foto de v2osk, algunos derechos reservados.

Descripción general del tutorial

Este tutorial se divide en cuatro partes; están:

  • Resumen de la arquitectura del transformador
  • Preparación del conjunto de datos de entrenamiento
  • Aplicación de una máscara de relleno a los cálculos de pérdida y precisión
  • Entrenamiento del modelo de transformador

requisitos previos

Para este tutorial, asumimos que ya está familiarizado con:

  • La teoría detrás del modelo Transformer
  • Una implementación del modelo Transformer

Resumen de la arquitectura del transformador

Recuerde haber visto que la arquitectura de Transformer sigue una estructura de codificador-decodificador: el codificador, en el lado izquierdo, tiene la tarea de mapear una secuencia de entrada a una secuencia de representaciones continuas; el decodificador, en el lado derecho, recibe la salida del codificador junto con la salida del decodificador en el paso de tiempo anterior, para generar una secuencia de salida.

La estructura del codificador-decodificador de la arquitectura del transformador
Tomado de “La atención es todo lo que necesitas“

Al generar una secuencia de salida, el Transformador no se basa en recurrencias ni circunvoluciones.

Hemos visto cómo implementar el modelo completo de Transformer, y ahora procederemos a entrenarlo para la traducción automática neuronal.

Comencemos primero preparando el conjunto de datos para el entrenamiento.

Preparación del conjunto de datos de entrenamiento

Para este propósito, nos referiremos a un tutorial anterior que cubre material relacionado con la preparación de los datos de texto para el entrenamiento.

También utilizaremos un conjunto de datos que contiene pares de oraciones cortas en inglés y alemán, que puede descargar aquí. Este conjunto de datos en particular ya se limpió eliminando los caracteres no imprimibles y no alfabéticos, y los caracteres de puntuación, y normalizando aún más todos los caracteres Unicode a ASCII y todas las letras mayúsculas a minúsculas. Por lo tanto, nos saltaremos el paso de limpieza que normalmente forma parte del proceso de preparación de datos. Sin embargo, si está utilizando un conjunto de datos que no se limpia fácilmente, puede consultar este tutorial anterior para aprender cómo hacerlo.

Procedamos creando el PrepareDataset clase que implementa los siguientes pasos:

  • Carga el conjunto de datos desde un nombre de archivo especificado.

clean_dataset = load(open(filename, ‘rb’))

  • Selecciona el número de oraciones a usar del conjunto de datos. Dado que el conjunto de datos es grande, reduciremos su tamaño para limitar el tiempo de entrenamiento. Sin embargo, puede explorar el uso del conjunto de datos completo como una extensión de este tutorial.

dataset = clean_dataset[:self.n_sentences, :]

  • Agrega tokens de inicio () y fin de cadena () a cada oración. Por ejemplo, la oración en inglés, i like to runahora se convierte en, <START> i like to run <EOS>. Esto también se aplica a su correspondiente traducción al alemán, ich gehe gerne joggenque ahora se convierte en, <START> ich gehe gerne joggen <EOS>.

for i in range(dataset[:, 0].size):
dataset[i, 0] = «<START> » + dataset[i, 0] + » <EOS>»
dataset[i, 1] = «<START> » + dataset[i, 1] + » <EOS>»

  • Mezcla aleatoriamente el conjunto de datos.

shuffle(dataset)

  • Divide el conjunto de datos mezclado en función de una proporción predefinida.

train = dataset[:int(self.n_sentences * self.train_split)]

  • Crea y entrena un tokenizador en las secuencias de texto que se introducirán en el codificador y encuentra la longitud de la secuencia más larga, así como el tamaño del vocabulario.

enc_tokenizer = self.create_tokenizer(train[:, 0])
enc_seq_length = self.find_seq_length(train[:, 0])
enc_vocab_size = self.find_vocab_size(enc_tokenizer, train[:, 0])

  • Tokeniza las secuencias de texto que se introducirán en el codificador, creando un vocabulario de palabras y reemplazando cada palabra por su índice de vocabulario correspondiente. Los tokens y también formarán parte de este vocabulario. Cada secuencia también se rellena hasta la longitud máxima de la frase.

trainX = enc_tokenizer.texts_to_sequences(train[:, 0])
trainX = pad_sequences(trainX, maxlen=enc_seq_length, padding=’post’)
trainX = convert_to_tensor(trainX, dtype=int64)

  • Crea y entrena un tokenizador en las secuencias de texto que se introducirán en el decodificador y encuentra la longitud de la secuencia más larga, así como el tamaño del vocabulario.

dec_tokenizer = self.create_tokenizer(train[:, 1])
dec_seq_length = self.find_seq_length(train[:, 1])
dec_vocab_size = self.find_vocab_size(dec_tokenizer, train[:, 1])

  • Repite un procedimiento similar de tokenización y relleno para las secuencias de texto que se introducirán en el decodificador.

trainY = dec_tokenizer.texts_to_sequences(train[:, 1])
trainY = pad_sequences(trainY, maxlen=dec_seq_length, padding=’post’)
trainY = convert_to_tensor(trainY, dtype=int64)

La lista completa de códigos es la siguiente (consulte este tutorial anterior para obtener más detalles):

from pickle import load
from numpy.random import shuffle
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from tensorflow import convert_to_tensor, int64

class PrepareDataset:
def __init__(self, **kwargs):
super(PrepareDataset, self).__init__(**kwargs)
self.n_sentences = 10000 # Number of sentences to include in the dataset
self.train_split = 0.9 # Ratio of the training data split

# Fit a tokenizer
def create_tokenizer(self, dataset):
tokenizer = Tokenizer()
tokenizer.fit_on_texts(dataset)

return tokenizer

def find_seq_length(self, dataset):
return max(len(seq.split()) for seq in dataset)

def find_vocab_size(self, tokenizer, dataset):
tokenizer.fit_on_texts(dataset)

return len(tokenizer.word_index) + 1

def __call__(self, filename, **kwargs):
# Load a clean dataset
clean_dataset = load(open(filename, ‘rb’))

# Reduce dataset size
dataset = clean_dataset[:self.n_sentences, :]

# Include start and end of string tokens
for i in range(dataset[:, 0].size):
dataset[i, 0] = «<START> » + dataset[i, 0] + » <EOS>»
dataset[i, 1] = «<START> » + dataset[i, 1] + » <EOS>»

# Random shuffle the dataset
shuffle(dataset)

# Split the dataset
train = dataset[:int(self.n_sentences * self.train_split)]

# Prepare tokenizer for the encoder input
enc_tokenizer = self.create_tokenizer(train[:, 0])
enc_seq_length = self.find_seq_length(train[:, 0])
enc_vocab_size = self.find_vocab_size(enc_tokenizer, train[:, 0])

# Encode and pad the input sequences
trainX = enc_tokenizer.texts_to_sequences(train[:, 0])
trainX = pad_sequences(trainX, maxlen=enc_seq_length, padding=’post’)
trainX = convert_to_tensor(trainX, dtype=int64)

# Prepare tokenizer for the decoder input
dec_tokenizer = self.create_tokenizer(train[:, 1])
dec_seq_length = self.find_seq_length(train[:, 1])
dec_vocab_size = self.find_vocab_size(dec_tokenizer, train[:, 1])

# Encode and pad the input sequences
trainY = dec_tokenizer.texts_to_sequences(train[:, 1])
trainY = pad_sequences(trainY, maxlen=dec_seq_length, padding=’post’)
trainY = convert_to_tensor(trainY, dtype=int64)

return trainX, trainY, train, enc_seq_length, dec_seq_length, enc_vocab_size, dec_vocab_size

Antes de pasar a entrenar el modelo Transformer, primero echemos un vistazo a la salida del PrepareDataset clase correspondiente a la primera oración en el conjunto de datos de entrenamiento:

# Prepare the training data
dataset = PrepareDataset()
trainX, trainY, train_orig, enc_seq_length, dec_seq_length, enc_vocab_size, dec_vocab_size = dataset(‘english-german-both.pkl’)

print(train_orig[0, 0], ‘n’, trainX[0, :])

<START> did tom tell you <EOS>
tf.Tensor([ 1 25 4 97 5 2 0], shape=(7,), dtype=int64)

(Nota: dado que el conjunto de datos se ha barajado aleatoriamente, es probable que vea un resultado diferente).

Podemos ver que, originalmente, teníamos una oración de tres palabras (Tom te dijo) al que hemos agregado los tokens de inicio y final de cadena, y que luego procedimos a vectorizar (puede notar que los tokens y tienen asignados los índices de vocabulario 1 y 2, respectivamente). El texto vectorizado también se rellenó con ceros, de modo que la longitud del resultado final coincida con la longitud máxima de secuencia del codificador:

print(‘Encoder sequence length:’, enc_seq_length)

Encoder sequence length: 7

De manera similar, podemos verificar los datos de destino correspondientes que se alimentan al decodificador:

print(train_orig[0, 1], ‘n’, trainY[0, :])

<START> hat tom es dir gesagt <EOS>
tf.Tensor([ 1 14 5 7 42 162 2 0 0 0 0 0], shape=(12,), dtype=int64)

Aquí, la longitud del resultado final coincide con la longitud máxima de secuencia del decodificador:

print(‘Decoder sequence length:’, dec_seq_length)

Decoder sequence length: 12

Aplicación de una máscara de relleno a los cálculos de pérdida y precisión

Recuerde ver que la importancia de tener una máscara de relleno en el codificador y decodificador es asegurarse de que los valores cero que acabamos de agregar a las entradas vectorizadas no se procesen junto con los valores de entrada reales.

Esto también es válido para el proceso de entrenamiento, donde se requiere una máscara de relleno para que los valores de relleno cero en los datos objetivo no se consideren en el cálculo de la pérdida y la precisión.

Echemos un vistazo al cálculo de la pérdida primero.

Esto se calculará por medio de una función de pérdida de entropía cruzada categórica escasa entre el objetivo y los valores predichos, y posteriormente se multiplicará por una máscara de relleno para que solo se consideren los valores válidos distintos de cero. La pérdida devuelta es la media de los valores desenmascarados:

def loss_fcn(target, prediction):
# Create mask so that the zero padding values are not included in the computation of loss
padding_mask = math.logical_not(equal(target, 0))
padding_mask = cast(padding_mask, float32)

# Compute a sparse categorical cross-entropy loss on the unmasked values
loss = sparse_categorical_crossentropy(target, prediction, from_logits=True) * padding_mask

# Compute the mean loss over the unmasked values
return reduce_sum(loss) / reduce_sum(padding_mask)

Para el cálculo de la precisión, primero se comparan los valores previstos y objetivo. La salida predicha es un tensor de tamaño, (tamaño del lote, dec_seq_longitud, dec_vocab_size) y contiene valores de probabilidad (generados por la función softmax en el lado del decodificador) para los tokens en la salida. Para poder realizar la comparación con los valores objetivo, solo se considera cada token con el mayor valor de probabilidad, recuperando su índice de diccionario a través de la operación: argmax(prediction, axis=2). Tras la aplicación de una máscara de relleno, la precisión devuelta es la media de los valores desenmascarados:

def accuracy_fcn(target, prediction):
# Create mask so that the zero padding values are not included in the computation of accuracy
padding_mask = math.logical_not(math.equal(target, 0))

# Find equal prediction and target values, and apply the padding mask
accuracy = equal(target, argmax(prediction, axis=2))
accuracy = math.logical_and(padding_mask, accuracy)

# Cast the True/False values to 32-bit-precision floating-point numbers
padding_mask = cast(padding_mask, float32)
accuracy = cast(accuracy, float32)

# Compute the mean accuracy over the unmasked values
return reduce_sum(accuracy) / reduce_sum(padding_mask)

Entrenamiento del modelo de transformador

Primero definamos el modelo y los parámetros de entrenamiento según lo especificado por Vaswani et al. (2017):

# Define the model parameters
h = 8 # Number of self-attention heads
d_k = 64 # Dimensionality of the linearly projected queries and keys
d_v = 64 # Dimensionality of the linearly projected values
d_model = 512 # Dimensionality of model layers’ outputs
d_ff = 2048 # Dimensionality of the inner fully connected layer
n = 6 # Number of layers in the encoder stack

# Define the training parameters
epochs = 2
batch_size = 64
beta_1 = 0.9
beta_2 = 0.98
epsilon = 1e-9
dropout_rate = 0.1

(Nota: aquí solo estamos considerando dos épocas para limitar el tiempo de entrenamiento. Sin embargo, puede explorar entrenar más el modelo como una extensión de este tutorial).

También necesitamos implementar un programador de tasa de aprendizaje que, inicialmente, aumente la tasa de aprendizaje linealmente para el primer calentamiento_pasos, y luego lo disminuye proporcionalmente a la raíz cuadrada inversa del número de paso. Vawsani et al. expresar esto mediante la siguiente fórmula:

$$text{índice_de_aprendizaje} = text{d_modelo}^{−0.5} cdot text{min}(text{paso}^{−0.5}, text{paso} cdot text{pasos_de_calentamiento}^ {−1.5})$$

 

class LRScheduler(LearningRateSchedule):
def __init__(self, d_model, warmup_steps=4000, **kwargs):
super(LRScheduler, self).__init__(**kwargs)

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

def __call__(self, step_num):

# Linearly increasing the learning rate for the first warmup_steps, and decreasing it thereafter
arg1 = step_num ** -0.5
arg2 = step_num * (self.warmup_steps ** -1.5)

return (self.d_model ** -0.5) * math.minimum(arg1, arg2)

Una instancia de la LRScheduler la clase se transmite posteriormente como el learning_rate argumento del optimizador de Adam:

optimizer = Adam(LRScheduler(d_model), beta_1, beta_2, epsilon)

A continuación, dividiremos el conjunto de datos en lotes, en preparación para el entrenamiento:

train_dataset = data.Dataset.from_tensor_slices((trainX, trainY))
train_dataset = train_dataset.batch(batch_size)

Seguido de la creación de una instancia de modelo:

training_model = TransformerModel(enc_vocab_size, dec_vocab_size, enc_seq_length, dec_seq_length, h, d_k, d_v, d_model, d_ff, n, dropout_rate)

Al entrenar el modelo de Transformer, escribiremos nuestro propio bucle de entrenamiento, que incorpora las funciones de pérdida y precisión que hemos implementado anteriormente.

El tiempo de ejecución predeterminado en Tensorflow 2.0 es ejecución ansiosa, lo que significa que las operaciones se ejecutan inmediatamente una tras otra. La ejecución ansiosa es simple e intuitiva y facilita la depuración. Sin embargo, su desventaja es que no puede aprovechar las optimizaciones de rendimiento global que vienen con la ejecución del código usando ejecución de gráficos. En la ejecución de gráficos, primero se construye un gráfico antes de que se puedan ejecutar los cálculos de tensor, lo que da lugar a una sobrecarga computacional. Por esta razón, el uso de la ejecución de gráficos se recomienda principalmente para el entrenamiento de modelos grandes, en lugar del entrenamiento de modelos pequeños, donde la ejecución rápida puede ser más adecuada para realizar operaciones más simples. Dado que el modelo de Transformador es lo suficientemente grande, aplicaremos la ejecución de gráficos para entrenarlo.

Para ello utilizaremos el @function decorador de la siguiente manera:

@function
def train_step(encoder_input, decoder_input, decoder_output):
with GradientTape() as tape:

# Run the forward pass of the model to generate a prediction
prediction = training_model(encoder_input, decoder_input, training=True)

# Compute the training loss
loss = loss_fcn(decoder_output, prediction)

# Compute the training accuracy
accuracy = accuracy_fcn(decoder_output, prediction)

# Retrieve gradients of the trainable variables with respect to the training loss
gradients = tape.gradient(loss, training_model.trainable_weights)

# Update the values of the trainable variables by gradient descent
optimizer.apply_gradients(zip(gradients, training_model.trainable_weights))

train_loss(loss)
train_accuracy(accuracy)

Con la adición de la @function decorador, una función que toma tensores como entrada se compilará en un gráfico. Si el @function decorador está comentado, la función, alternativamente, se ejecuta con una ejecución ansiosa.

El siguiente paso es implementar el ciclo de entrenamiento que llamará al train_step función de arriba. El ciclo de entrenamiento iterará sobre el número especificado de épocas y sobre los lotes de conjuntos de datos. Para cada lote, el train_step La función calcula la pérdida de entrenamiento y las medidas de precisión, y aplica el optimizador para actualizar los parámetros del modelo entrenable. También se incluye un administrador de puntos de control para guardar un punto de control después de cada cinco épocas:

train_loss = Mean(name=»train_loss»)
train_accuracy = Mean(name=»train_accuracy»)

# Create a checkpoint object and manager to manage multiple checkpoints
ckpt = train.Checkpoint(model=training_model, optimizer=optimizer)
ckpt_manager = train.CheckpointManager(ckpt, «./checkpoints», max_to_keep=3)

for epoch in range(epochs):

train_loss.reset_states()
train_accuracy.reset_states()

print(«nStart of epoch %d» % (epoch + 1))

# Iterate over the dataset batches
for step, (train_batchX, train_batchY) in enumerate(train_dataset):

# Define the encoder and decoder inputs, and the decoder output
encoder_input = train_batchX[:, 1:] decoder_input = train_batchY[:, :-1] decoder_output = train_batchY[:, 1:]

train_step(encoder_input, decoder_input, decoder_output)

if step % 50 == 0:
print(f’Epoch {epoch + 1} Step {step} Loss {train_loss.result():.4f} Accuracy {train_accuracy.result():.4f}’)

# Print epoch number and loss value at the end of every epoch
print(«Epoch %d: Training Loss %.4f, Training Accuracy %.4f» % (epoch + 1, train_loss.result(), train_accuracy.result()))

# Save a checkpoint after every five epochs
if (epoch + 1) % 5 == 0:
save_path = ckpt_manager.save()
print(«Saved checkpoint at epoch %d» % (epoch + 1))

Un punto importante a tener en cuenta es que la entrada al decodificador está desplazada una posición a la derecha con respecto a la entrada del codificador. La idea detrás de este desplazamiento, combinado con una máscara de anticipación en el primer bloque de atención de múltiples cabezales del decodificador, es garantizar que la predicción para el token actual solo pueda depender de los tokens anteriores.

Este enmascaramiento, combinado con el hecho de que las incrustaciones de salida están compensadas por una posición, asegura que las predicciones para la posición i puedan depender solo de las salidas conocidas en posiciones menores que i.

La atención es todo lo que necesitas, 2017.

Es por esta razón que las entradas del codificador y del decodificador se alimentan al modelo de Transformador de la siguiente manera:

encoder_input = train_batchX[:, 1:]

decoder_input = train_batchY[:, :-1]

Reunir la lista completa de códigos produce lo siguiente:

from tensorflow.keras.optimizers import Adam
from tensorflow.keras.optimizers.schedules import LearningRateSchedule
from tensorflow.keras.metrics import Mean
from tensorflow import data, train, math, reduce_sum, cast, equal, argmax, float32, GradientTape, TensorSpec, function, int64
from keras.losses import sparse_categorical_crossentropy
from model import TransformerModel
from prepare_dataset import PrepareDataset
from time import time

# Define the model parameters
h = 8 # Number of self-attention heads
d_k = 64 # Dimensionality of the linearly projected queries and keys
d_v = 64 # Dimensionality of the linearly projected values
d_model = 512 # Dimensionality of model layers’ outputs
d_ff = 2048 # Dimensionality of the inner fully connected layer
n = 6 # Number of layers in the encoder stack

# Define the training parameters
epochs = 2
batch_size = 64
beta_1 = 0.9
beta_2 = 0.98
epsilon = 1e-9
dropout_rate = 0.1

# Implementing a learning rate scheduler
class LRScheduler(LearningRateSchedule):
def __init__(self, d_model, warmup_steps=4000, **kwargs):
super(LRScheduler, self).__init__(**kwargs)

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

def __call__(self, step_num):

# Linearly increasing the learning rate for the first warmup_steps, and decreasing it thereafter
arg1 = step_num ** -0.5
arg2 = step_num * (self.warmup_steps ** -1.5)

return (self.d_model ** -0.5) * math.minimum(arg1, arg2)

# Instantiate an Adam optimizer
optimizer = Adam(LRScheduler(d_model), beta_1, beta_2, epsilon)

# Prepare the training and test splits of the dataset
dataset = PrepareDataset()
trainX, trainY, train_orig, enc_seq_length, dec_seq_length, enc_vocab_size, dec_vocab_size = dataset(‘english-german-both.pkl’)

# Prepare the dataset batches
train_dataset = data.Dataset.from_tensor_slices((trainX, trainY))
train_dataset = train_dataset.batch(batch_size)

# Create model
training_model = TransformerModel(enc_vocab_size, dec_vocab_size, enc_seq_length, dec_seq_length, h, d_k, d_v, d_model, d_ff, n, dropout_rate)

# Defining the loss function
def loss_fcn(target, prediction):
# Create mask so that the zero padding values are not included in the computation of loss
padding_mask = math.logical_not(equal(target, 0))
padding_mask = cast(padding_mask, float32)

# Compute a sparse categorical cross-entropy loss on the unmasked values
loss = sparse_categorical_crossentropy(target, prediction, from_logits=True) * padding_mask

# Compute the mean loss over the unmasked values
return reduce_sum(loss) / reduce_sum(padding_mask)

# Defining the accuracy function
def accuracy_fcn(target, prediction):
# Create mask so that the zero padding values are not included in the computation of accuracy
padding_mask = math.logical_not(equal(target, 0))

# Find equal prediction and target values, and apply the padding mask
accuracy = equal(target, argmax(prediction, axis=2))
accuracy = math.logical_and(padding_mask, accuracy)

# Cast the True/False values to 32-bit-precision floating-point numbers
padding_mask = cast(padding_mask, float32)
accuracy = cast(accuracy, float32)

# Compute the mean accuracy over the unmasked values
return reduce_sum(accuracy) / reduce_sum(padding_mask)

# Include metrics monitoring
train_loss = Mean(name=»train_loss»)
train_accuracy = Mean(name=»train_accuracy»)

# Create a checkpoint object and manager to manage multiple checkpoints
ckpt = train.Checkpoint(model=training_model, optimizer=optimizer)
ckpt_manager = train.CheckpointManager(ckpt, «./checkpoints», max_to_keep=3)

# Speeding up the training process
@function
def train_step(encoder_input, decoder_input, decoder_output):
with GradientTape() as tape:

# Run the forward pass of the model to generate a prediction
prediction = training_model(encoder_input, decoder_input, training=True)

# Compute the training loss
loss = loss_fcn(decoder_output, prediction)

# Compute the training accuracy
accuracy = accuracy_fcn(decoder_output, prediction)

# Retrieve gradients of the trainable variables with respect to the training loss
gradients = tape.gradient(loss, training_model.trainable_weights)

# Update the values of the trainable variables by gradient descent
optimizer.apply_gradients(zip(gradients, training_model.trainable_weights))

train_loss(loss)
train_accuracy(accuracy)

for epoch in range(epochs):

train_loss.reset_states()
train_accuracy.reset_states()

print(«nStart of epoch %d» % (epoch + 1))

start_time = time()

# Iterate over the dataset batches
for step, (train_batchX, train_batchY) in enumerate(train_dataset):

# Define the encoder and decoder inputs, and the decoder output
encoder_input = train_batchX[:, 1:] decoder_input = train_batchY[:, :-1] decoder_output = train_batchY[:, 1:]

train_step(encoder_input, decoder_input, decoder_output)

if step % 50 == 0:
print(f’Epoch {epoch + 1} Step {step} Loss {train_loss.result():.4f} Accuracy {train_accuracy.result():.4f}’)
# print(«Samples so far: %s» % ((step + 1) * batch_size))

# Print epoch number and loss value at the end of every epoch
print(«Epoch %d: Training Loss %.4f, Training Accuracy %.4f» % (epoch + 1, train_loss.result(), train_accuracy.result()))

# Save a checkpoint after every five epochs
if (epoch + 1) % 5 == 0:
save_path = ckpt_manager.save()
print(«Saved checkpoint at epoch %d» % (epoch + 1))

print(«Total time taken: %.2fs» % (time() – start_time))

Ejecutar el código produce un resultado similar al siguiente (probablemente verá diferentes valores de pérdida y precisión porque estamos entrenando desde cero, mientras que el tiempo de entrenamiento depende de los recursos computacionales que tenga disponibles para el entrenamiento):

Start of epoch 1
Epoch 1 Step 0 Loss 8.4525 Accuracy 0.0000
Epoch 1 Step 50 Loss 7.6768 Accuracy 0.1234
Epoch 1 Step 100 Loss 7.0360 Accuracy 0.1713
Epoch 1: Training Loss 6.7109, Training Accuracy 0.1924

Start of epoch 2
Epoch 2 Step 0 Loss 5.7323 Accuracy 0.2628
Epoch 2 Step 50 Loss 5.4360 Accuracy 0.2756
Epoch 2 Step 100 Loss 5.2638 Accuracy 0.2839
Epoch 2: Training Loss 5.1468, Training Accuracy 0.2908
Total time taken: 87.98s

Se necesitan 155,13 s para que el código se ejecute usando solo la ejecución ansiosa en la misma plataforma que usa solo una CPU, lo que muestra el beneficio de usar la ejecución gráfica.

Otras lecturas

Esta sección proporciona más recursos sobre el tema si desea profundizar más.

Libros

  • Aprendizaje profundo avanzado con Python, 2019.
  • Transformadores para el procesamiento del lenguaje natural, 2021.

Documentos

  • La atención es todo lo que necesitas, 2017.

sitios web

  • Escribir un ciclo de entrenamiento desde cero en Keras, https://keras.io/guides/writing_a_training_loop_from_scratch/

Resumen

En este tutorial, descubrió cómo entrenar el modelo de Transformer para la traducción automática neuronal.

Específicamente, aprendiste:

  • Cómo preparar el conjunto de datos de entrenamiento.
  • Cómo aplicar una máscara de relleno a los cálculos de pérdida y precisión.
  • Cómo entrenar el modelo Transformer.

¿Tiene usted alguna pregunta?
Haga sus preguntas en los comentarios a continuación y haré todo lo posible para responder.



La publicación Training the Transformer Model apareció primero en Machine Learning Mastery.

Recomendado:  ¿Es la IA el futuro del marketing de contenidos?