Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/guide/basic_training_loops.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Bucles de entrenamiento básico

En los guías anteriores, ha aprendido sobre tensores, variables, cinta de gradiente, y módulos. En esta guía, los combinará todos para entrenar modelos.

TensorFlow también incluye la API tf.Keras, una API de redes neuronales de alto nivel que ofrece abstracciones útiles para reducir el lenguaje repetitivo. Sin embargo, en esta guía, usted usará clases básicas.

Preparación

import tensorflow as tf import matplotlib.pyplot as plt colors = plt.rcParams['axes.prop_cycle'].by_key()['color']

Cómo resolver problemas de aprendizaje automático

Para resolver un problema de aprendizaje automático se suelen seguir los siguientes pasos:

  • Obtener datos de entrenamiento.

  • Definir el modelo.

  • Definir una función de pérdida.

  • Recorrer los datos del entrenamiento, calculando la pérdida con respecto al valor ideal

  • Calcular gradientes para esa pérdida y usar un optimizador para ajustar las variables a los datos.

  • Evaluar sus resultados.

A modo de ilustración, en esta guía desarrollará un modelo lineal sencillo, f(x)=xW+bf(x) = x * W + b, que tiene dos variables: WW (ponderaciones) y bb (sesgo).

Este es el más básico de los problemas de aprendizaje automático: Dados xx e yy, intente encontrar la pendiente y el desplazamiento de una línea mediante regresión lineal simple.

Datos

El aprendizaje supervisado usa entradas (normalmente denotadas como x) y salidas (denotadas como y, a menudo llamadas etiquetas). La meta es aprender a partir de entradas y salidas asociadas para poder predecir el valor de una salida a partir de una entrada.

Cada entrada de sus datos, en TensorFlow, está casi siempre representada por un tensor, y a menudo es un vector. En el entrenamiento supervisado, la salida (o valor que le gustaría predecir) es también un tensor.

He aquí algunos datos sintetizados añadiendo ruido gaussiano (normal) a los puntos a lo largo de una línea.

# The actual line TRUE_W = 3.0 TRUE_B = 2.0 NUM_EXAMPLES = 201 # A vector of random x values x = tf.linspace(-2,2, NUM_EXAMPLES) x = tf.cast(x, tf.float32) def f(x): return x * TRUE_W + TRUE_B # Generate some noise noise = tf.random.normal(shape=[NUM_EXAMPLES]) # Calculate y y = f(x) + noise
# Plot all the data plt.plot(x, y, '.') plt.show()

Los tensores suelen reunirse en lotes, o grupos de entradas y salidas apiladas. El agrupamiento por lotes puede suponer beneficios para el entrenamiento y funciona bien con aceleradores y computación vectorizada. Dado lo pequeño que es este conjunto de datos, puede tratarlo en su totalidad como un único lote.

Definir el modelo

Use tf.Variable para representar todas las ponderaciones de un modelo. Una tf.Variable almacena un valor y lo muestra en forma de tensor según sea necesario. Consulte la guía de variables para saber más.

Use tf.Module para encapsular las variables y el cálculo. Usted podría usar cualquier objeto de Python, pero de esta manera se puede guardar fácilmente.

Aquí se definen w y b como variables.

class MyModel(tf.Module): def __init__(self, **kwargs): super().__init__(**kwargs) # Initialize the weights to `5.0` and the bias to `0.0` # In practice, these should be randomly initialized self.w = tf.Variable(5.0) self.b = tf.Variable(0.0) def __call__(self, x): return self.w * x + self.b model = MyModel() # List the variables tf.modules's built-in variable aggregation. print("Variables:", model.variables) # Verify the model works assert model(3.0).numpy() == 15.0

Las variables iniciales se configuran aquí de forma fija, pero Keras viene con cualquiera de un número de inicializadores que usted puede usar, con o sin el resto de Keras.

Definir una función de pérdida

Una función de pérdida mide en qué medida la salida de un modelo para una entrada dada coincide con la salida objetivo. La meta es minimizar esta diferencia durante el entrenamiento. Defina la pérdida estándar L2, también conocida como error "cuadrático medio":

# This computes a single loss value for an entire batch def loss(target_y, predicted_y): return tf.reduce_mean(tf.square(target_y - predicted_y))

Antes de entrenar el modelo, puede visualizar el valor de la pérdida trazando las predicciones del modelo en rojo y los datos de entrenamiento en azul:

plt.plot(x, y, '.', label="Data") plt.plot(x, f(x), label="Ground truth") plt.plot(x, model(x), label="Predictions") plt.legend() plt.show() print("Current loss: %1.6f" % loss(y, model(x)).numpy())

Definir un bucle de entrenamiento

El bucle de entrenamiento consiste en realizar repetidamente tres tareas en orden:

  • Envío de un lote de entradas a través del modelo para generar salidas

  • Calcular la pérdida comparando las salidas con la salida (o etiqueta)

  • Usar cinta de gradiente para encontrar los gradientes

  • Optimizar las variables con esos gradientes

Para este ejemplo, puede entrenar el modelo usando descenso de gradiente.

Hay muchas variantes del esquema de descenso de gradiente que se capturan en tf.keras.optimizers. Pero con el ánimo de construir desde los fundamentos, aquí implementará usted mismo las matemáticas básicas con la ayuda de tf.GradientTape para la diferenciación automática y tf.assign_sub para decrementar un valor (que combina tf.assign y tf.sub):

# Given a callable model, inputs, outputs, and a learning rate... def train(model, x, y, learning_rate): with tf.GradientTape() as t: # Trainable variables are automatically tracked by GradientTape current_loss = loss(y, model(x)) # Use GradientTape to calculate the gradients with respect to W and b dw, db = t.gradient(current_loss, [model.w, model.b]) # Subtract the gradient scaled by the learning rate model.w.assign_sub(learning_rate * dw) model.b.assign_sub(learning_rate * db)

Para echar un vistazo al entrenamiento, puede enviar el mismo lote de x y y a través del bucle de entrenamiento, y ver cómo evolucionan W y b.

model = MyModel() # Collect the history of W-values and b-values to plot later weights = [] biases = [] epochs = range(10) # Define a training loop def report(model, loss): return f"W = {model.w.numpy():1.2f}, b = {model.b.numpy():1.2f}, loss={loss:2.5f}" def training_loop(model, x, y): for epoch in epochs: # Update the model with the single giant batch train(model, x, y, learning_rate=0.1) # Track this before I update weights.append(model.w.numpy()) biases.append(model.b.numpy()) current_loss = loss(y, model(x)) print(f"Epoch {epoch:2d}:") print(" ", report(model, current_loss))

Realizar el entrenamiento

current_loss = loss(y, model(x)) print(f"Starting:") print(" ", report(model, current_loss)) training_loop(model, x, y)

Grafique la evolución de las ponderaciones a lo largo del tiempo:

plt.plot(epochs, weights, label='Weights', color=colors[0]) plt.plot(epochs, [TRUE_W] * len(epochs), '--', label = "True weight", color=colors[0]) plt.plot(epochs, biases, label='bias', color=colors[1]) plt.plot(epochs, [TRUE_B] * len(epochs), "--", label="True bias", color=colors[1]) plt.legend() plt.show()

Visualice el rendimiento del modelo entrenado

plt.plot(x, y, '.', label="Data") plt.plot(x, f(x), label="Ground truth") plt.plot(x, model(x), label="Predictions") plt.legend() plt.show() print("Current loss: %1.6f" % loss(model(x), y).numpy())

La misma solución, pero con Keras

Es útil contrastar el código anterior con el equivalente en Keras.

La definición del modelo es exactamente la misma si hace una subclase a tf.keras.Model. Recuerde que los modelos Keras heredan del módulo de forma definitiva.

class MyModelKeras(tf.keras.Model): def __init__(self, **kwargs): super().__init__(**kwargs) # Initialize the weights to `5.0` and the bias to `0.0` # In practice, these should be randomly initialized self.w = tf.Variable(5.0) self.b = tf.Variable(0.0) def call(self, x): return self.w * x + self.b keras_model = MyModelKeras() # Reuse the training loop with a Keras model training_loop(keras_model, x, y) # You can also save a checkpoint using Keras's built-in support keras_model.save_weights("my_checkpoint")

En lugar de escribir nuevos bucles de entrenamiento cada vez que cree un modelo, puede usar las funciones integradas de Keras como atajo. Puede ser útil cuando no desee escribir o depurar bucles de entrenamiento en Python.

Si lo hace, tendrá que usar model.compile() para configurar los parámetros, y model.fit() para el entrenamiento. Puede ser menos código usar las implementaciones Keras de la pérdida L2 y el descenso de gradiente, también como atajo. Las pérdidas y los optimizadores de Keras también pueden usarse fuera de estas funciones de conveniencia, y el ejemplo anterior podría haberlos usado.

keras_model = MyModelKeras() # compile sets the training parameters keras_model.compile( # By default, fit() uses tf.function(). You can # turn that off for debugging, but it is on now. run_eagerly=False, # Using a built-in optimizer, configuring as an object optimizer=tf.keras.optimizers.SGD(learning_rate=0.1), # Keras comes with built-in MSE error # However, you could use the loss function # defined above loss=tf.keras.losses.mean_squared_error, )

fit de Keras espera datos por lotes o un conjunto de datos completo como un arreglo NumPy. Los arreglos NumPy se trocean en lotes y por defecto tienen un tamaño de lote de 32.

En este caso, para que coincida con el comportamiento del bucle escrito a mano, debe pasar x como un único lote de tamaño 1000.

print(x.shape[0]) keras_model.fit(x, y, epochs=10, batch_size=1000)

Tenga en cuenta que Keras imprime la pérdida después del entrenamiento, no antes, por lo que la primera pérdida parece menor, pero en lo demás esto muestra esencialmente el mismo rendimiento en el entrenamiento.

Siguientes pasos

En esta guía, ha visto cómo usar las clases básicas de tensores, variables, módulos y cinta de gradiente para construir y entrenar un modelo, y además cómo esas ideas se mapean a Keras.

Sin embargo, se trata de un problema extremadamente sencillo. Para una introducción más práctica, véase Recorrido de entrenamiento personalizado.

Para más información sobre cómo usar los bucles de entrenamiento incorporados de Keras, consulte esta guía. Para más información sobre los bucles de entrenamiento y Keras, consulte esta guía. Para escribir bucles de entrenamiento distribuidos personalizados, consulte esta guía.