Ver en TensorFlow.org | Ejecutar en Google Colab | Ver fuente en GitHub | Descargar libreta |
El progreso del modelo se puede guardar durante y después del entrenamiento. Esto significa que un modelo puede reanudar donde lo dejó y evitar largos tiempos de entrenamiento. Guardar también significa que puede compartir su modelo y otros pueden recrear su trabajo. Al publicar modelos y técnicas de investigación, la mayoría de los profesionales del aprendizaje automático comparten:
- código para crear el modelo, y
- los pesos entrenados, o parámetros, para el modelo
Compartir estos datos ayuda a otros a comprender cómo funciona el modelo y probarlo ellos mismos con nuevos datos.
Opciones
Hay diferentes formas de guardar modelos de TensorFlow según la API que estés usando. Esta guía usa tf.keras , una API de alto nivel para crear y entrenar modelos en TensorFlow. Para conocer otros enfoques, consulte la guía Guardar y restaurar de TensorFlow o Guardar en entusiasta .
Configuración
Instalaciones e importaciones
Instala e importa TensorFlow y dependencias:
pip install pyyaml h5py # Required to save models in HDF5 format
import os
import tensorflow as tf
from tensorflow import keras
print(tf.version.VERSION)
2.8.0-rc1
Obtener un conjunto de datos de ejemplo
Para demostrar cómo guardar y cargar pesos, utilizará el conjunto de datos MNIST . Para acelerar estas ejecuciones, use los primeros 1000 ejemplos:
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()
train_labels = train_labels[:1000]
test_labels = test_labels[:1000]
train_images = train_images[:1000].reshape(-1, 28 * 28) / 255.0
test_images = test_images[:1000].reshape(-1, 28 * 28) / 255.0
Definir un modelo
Comience por construir un modelo secuencial simple:
# Define a simple sequential model
def create_model():
model = tf.keras.models.Sequential([
keras.layers.Dense(512, activation='relu', input_shape=(784,)),
keras.layers.Dropout(0.2),
keras.layers.Dense(10)
])
model.compile(optimizer='adam',
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[tf.metrics.SparseCategoricalAccuracy()])
return model
# Create a basic model instance
model = create_model()
# Display the model's architecture
model.summary()
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense (Dense) (None, 512) 401920 dropout (Dropout) (None, 512) 0 dense_1 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
Guardar puntos de control durante el entrenamiento
Puede usar un modelo entrenado sin tener que volver a entrenarlo o retomar el entrenamiento donde lo dejó en caso de que se interrumpiera el proceso de entrenamiento. La devolución de llamada tf.keras.callbacks.ModelCheckpoint
le permite guardar continuamente el modelo durante y al final del entrenamiento.
Uso de devolución de llamada de punto de control
Cree una devolución de llamada tf.keras.callbacks.ModelCheckpoint
que guarde pesos solo durante el entrenamiento:
checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
# Create a callback that saves the model's weights
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
save_weights_only=True,
verbose=1)
# Train the model with the new callback
model.fit(train_images,
train_labels,
epochs=10,
validation_data=(test_images, test_labels),
callbacks=[cp_callback]) # Pass callback to training
# This may generate warnings related to saving the state of the optimizer.
# These warnings (and similar warnings throughout this notebook)
# are in place to discourage outdated usage, and can be ignored.
Epoch 1/10 23/32 [====================>.........] - ETA: 0s - loss: 1.3666 - sparse_categorical_accuracy: 0.6060 Epoch 1: saving model to training_1/cp.ckpt 32/32 [==============================] - 1s 10ms/step - loss: 1.1735 - sparse_categorical_accuracy: 0.6690 - val_loss: 0.7180 - val_sparse_categorical_accuracy: 0.7750 Epoch 2/10 24/32 [=====================>........] - ETA: 0s - loss: 0.4238 - sparse_categorical_accuracy: 0.8789 Epoch 2: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.4201 - sparse_categorical_accuracy: 0.8810 - val_loss: 0.5621 - val_sparse_categorical_accuracy: 0.8150 Epoch 3/10 24/32 [=====================>........] - ETA: 0s - loss: 0.2795 - sparse_categorical_accuracy: 0.9336 Epoch 3: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.2815 - sparse_categorical_accuracy: 0.9310 - val_loss: 0.4790 - val_sparse_categorical_accuracy: 0.8430 Epoch 4/10 24/32 [=====================>........] - ETA: 0s - loss: 0.2027 - sparse_categorical_accuracy: 0.9427 Epoch 4: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.2016 - sparse_categorical_accuracy: 0.9440 - val_loss: 0.4361 - val_sparse_categorical_accuracy: 0.8610 Epoch 5/10 24/32 [=====================>........] - ETA: 0s - loss: 0.1739 - sparse_categorical_accuracy: 0.9583 Epoch 5: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.1683 - sparse_categorical_accuracy: 0.9610 - val_loss: 0.4640 - val_sparse_categorical_accuracy: 0.8580 Epoch 6/10 23/32 [====================>.........] - ETA: 0s - loss: 0.1116 - sparse_categorical_accuracy: 0.9796 Epoch 6: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.1125 - sparse_categorical_accuracy: 0.9780 - val_loss: 0.4420 - val_sparse_categorical_accuracy: 0.8580 Epoch 7/10 24/32 [=====================>........] - ETA: 0s - loss: 0.0978 - sparse_categorical_accuracy: 0.9831 Epoch 7: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.0989 - sparse_categorical_accuracy: 0.9820 - val_loss: 0.4163 - val_sparse_categorical_accuracy: 0.8590 Epoch 8/10 21/32 [==================>...........] - ETA: 0s - loss: 0.0669 - sparse_categorical_accuracy: 0.9911 Epoch 8: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 6ms/step - loss: 0.0690 - sparse_categorical_accuracy: 0.9910 - val_loss: 0.4411 - val_sparse_categorical_accuracy: 0.8600 Epoch 9/10 22/32 [===================>..........] - ETA: 0s - loss: 0.0495 - sparse_categorical_accuracy: 0.9972 Epoch 9: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.0516 - sparse_categorical_accuracy: 0.9950 - val_loss: 0.4064 - val_sparse_categorical_accuracy: 0.8650 Epoch 10/10 24/32 [=====================>........] - ETA: 0s - loss: 0.0436 - sparse_categorical_accuracy: 0.9948 Epoch 10: saving model to training_1/cp.ckpt 32/32 [==============================] - 0s 5ms/step - loss: 0.0437 - sparse_categorical_accuracy: 0.9960 - val_loss: 0.4061 - val_sparse_categorical_accuracy: 0.8770 <keras.callbacks.History at 0x7eff8d865390>
Esto crea una única colección de archivos de puntos de control de TensorFlow que se actualizan al final de cada época:
os.listdir(checkpoint_dir)
['checkpoint', 'cp.ckpt.index', 'cp.ckpt.data-00000-of-00001']
Siempre que dos modelos compartan la misma arquitectura, puede compartir pesos entre ellos. Por lo tanto, cuando restaure un modelo de solo pesos, cree un modelo con la misma arquitectura que el modelo original y luego establezca sus pesos.
Ahora reconstruya un modelo nuevo, no entrenado y evalúelo en el conjunto de prueba. Un modelo no entrenado se desempeñará en niveles de probabilidad (~10 % de precisión):
# Create a basic model instance
model = create_model()
# Evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Untrained model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 2.4473 - sparse_categorical_accuracy: 0.0980 - 145ms/epoch - 5ms/step Untrained model, accuracy: 9.80%
Luego cargue los pesos desde el punto de control y vuelva a evaluar:
# Loads the weights
model.load_weights(checkpoint_path)
# Re-evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4061 - sparse_categorical_accuracy: 0.8770 - 65ms/epoch - 2ms/step Restored model, accuracy: 87.70%
Opciones de devolución de llamada del punto de control
La devolución de llamada ofrece varias opciones para proporcionar nombres únicos para los puntos de control y ajustar la frecuencia de los puntos de control.
Entrena un nuevo modelo y guarda puntos de control con nombres exclusivos una vez cada cinco épocas:
# Include the epoch in the file name (uses `str.format`)
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
batch_size = 32
# Create a callback that saves the model's weights every 5 epochs
cp_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_path,
verbose=1,
save_weights_only=True,
save_freq=5*batch_size)
# Create a new model instance
model = create_model()
# Save the weights using the `checkpoint_path` format
model.save_weights(checkpoint_path.format(epoch=0))
# Train the model with the new callback
model.fit(train_images,
train_labels,
epochs=50,
batch_size=batch_size,
callbacks=[cp_callback],
validation_data=(test_images, test_labels),
verbose=0)
Epoch 5: saving model to training_2/cp-0005.ckpt Epoch 10: saving model to training_2/cp-0010.ckpt Epoch 15: saving model to training_2/cp-0015.ckpt Epoch 20: saving model to training_2/cp-0020.ckpt Epoch 25: saving model to training_2/cp-0025.ckpt Epoch 30: saving model to training_2/cp-0030.ckpt Epoch 35: saving model to training_2/cp-0035.ckpt Epoch 40: saving model to training_2/cp-0040.ckpt Epoch 45: saving model to training_2/cp-0045.ckpt Epoch 50: saving model to training_2/cp-0050.ckpt <keras.callbacks.History at 0x7eff807703d0>
Ahora, mire los puntos de control resultantes y elija el último:
os.listdir(checkpoint_dir)
['cp-0005.ckpt.data-00000-of-00001', 'cp-0050.ckpt.index', 'checkpoint', 'cp-0010.ckpt.index', 'cp-0035.ckpt.data-00000-of-00001', 'cp-0000.ckpt.data-00000-of-00001', 'cp-0050.ckpt.data-00000-of-00001', 'cp-0010.ckpt.data-00000-of-00001', 'cp-0020.ckpt.data-00000-of-00001', 'cp-0035.ckpt.index', 'cp-0040.ckpt.index', 'cp-0025.ckpt.data-00000-of-00001', 'cp-0045.ckpt.index', 'cp-0020.ckpt.index', 'cp-0025.ckpt.index', 'cp-0030.ckpt.data-00000-of-00001', 'cp-0030.ckpt.index', 'cp-0000.ckpt.index', 'cp-0045.ckpt.data-00000-of-00001', 'cp-0015.ckpt.index', 'cp-0015.ckpt.data-00000-of-00001', 'cp-0005.ckpt.index', 'cp-0040.ckpt.data-00000-of-00001']
latest = tf.train.latest_checkpoint(checkpoint_dir)
latest
'training_2/cp-0050.ckpt'
Para probar, reinicie el modelo y cargue el último punto de control:
# Create a new model instance
model = create_model()
# Load the previously saved weights
model.load_weights(latest)
# Re-evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4996 - sparse_categorical_accuracy: 0.8770 - 150ms/epoch - 5ms/step Restored model, accuracy: 87.70%
¿Qué son estos archivos?
El código anterior almacena los pesos en una colección de archivos con formato de punto de control que contienen solo los pesos entrenados en un formato binario. Los puntos de control contienen:
- Uno o más fragmentos que contienen los pesos de su modelo.
- Un archivo de índice que indica qué pesos se almacenan en qué fragmento.
Si está entrenando un modelo en una sola máquina, tendrá un fragmento con el sufijo: .data-00000-of-00001
Guardar pesos manualmente
Guardar pesos manualmente con el método Model.save_weights
. De forma predeterminada, tf.keras
, y save_weights
en particular, usa el formato de punto de control de TensorFlow con una extensión .ckpt
(el guardado en HDF5 con una extensión .h5
se trata en la guía Guardar y serializar modelos ):
# Save the weights
model.save_weights('./checkpoints/my_checkpoint')
# Create a new model instance
model = create_model()
# Restore the weights
model.load_weights('./checkpoints/my_checkpoint')
# Evaluate the model
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100 * acc))
32/32 - 0s - loss: 0.4996 - sparse_categorical_accuracy: 0.8770 - 143ms/epoch - 4ms/step Restored model, accuracy: 87.70%
Guardar todo el modelo
Llame a model.save
para guardar la arquitectura, los pesos y la configuración de entrenamiento de un modelo en un solo archivo/carpeta. Esto le permite exportar un modelo para que pueda usarse sin acceso al código original de Python*. Dado que se recupera el estado del optimizador, puede reanudar el entrenamiento exactamente desde donde lo dejó.
Un modelo completo se puede guardar en dos formatos de archivo diferentes ( SavedModel
y HDF5
). El formato de SavedModel
TensorFlow es el formato de archivo predeterminado en TF2.x. Sin embargo, los modelos se pueden guardar en formato HDF5
. A continuación se describen más detalles sobre cómo guardar modelos completos en los dos formatos de archivo.
Guardar un modelo completamente funcional es muy útil: puede cargarlo en TensorFlow.js ( Modelo guardado , HDF5 ) y luego entrenarlo y ejecutarlo en navegadores web, o convertirlo para ejecutarlo en dispositivos móviles usando TensorFlow Lite ( Modelo guardado , HDF5 ). )
*Los objetos personalizados (p. ej., modelos o capas subclasificados) requieren una atención especial al guardarlos y cargarlos. Consulte la sección Guardar objetos personalizados a continuación.
Formato de modelo guardado
El formato de modelo guardado es otra forma de serializar modelos. Los modelos guardados en este formato se pueden restaurar usando tf.keras.models.load_model
y son compatibles con TensorFlow Serving. La guía del modelo guardado detalla cómo servir/inspeccionar el modelo guardado. La siguiente sección ilustra los pasos para guardar y restaurar el modelo.
# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)
# Save the entire model as a SavedModel.
!mkdir -p saved_model
model.save('saved_model/my_model')
Epoch 1/5 32/32 [==============================] - 0s 2ms/step - loss: 1.1988 - sparse_categorical_accuracy: 0.6550 Epoch 2/5 32/32 [==============================] - 0s 2ms/step - loss: 0.4180 - sparse_categorical_accuracy: 0.8930 Epoch 3/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2900 - sparse_categorical_accuracy: 0.9220 Epoch 4/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2070 - sparse_categorical_accuracy: 0.9540 Epoch 5/5 32/32 [==============================] - 0s 2ms/step - loss: 0.1593 - sparse_categorical_accuracy: 0.9630 2022-01-26 07:30:22.888387: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. WARNING:tensorflow:Detecting that an object or model or tf.train.Checkpoint is being deleted with unrestored values. See the following logs for the specific values in question. To silence these warnings, use `status.expect_partial()`. See https://www.tensorflow.org/api_docs/python/tf/train/Checkpoint#restorefor details about the status object returned by the restore function. WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.iter WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_1 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_2 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.decay WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.learning_rate WARNING:tensorflow:Detecting that an object or model or tf.train.Checkpoint is being deleted with unrestored values. See the following logs for the specific values in question. To silence these warnings, use `status.expect_partial()`. See https://www.tensorflow.org/api_docs/python/tf/train/Checkpoint#restorefor details about the status object returned by the restore function. WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.iter WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_1 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.beta_2 WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.decay WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer.learning_rate INFO:tensorflow:Assets written to: saved_model/my_model/assets
El formato de modelo guardado es un directorio que contiene un binario protobuf y un punto de control de TensorFlow. Inspeccione el directorio del modelo guardado:
# my_model directory
ls saved_model
# Contains an assets folder, saved_model.pb, and variables folder.
ls saved_model/my_model
my_model assets keras_metadata.pb saved_model.pb variables
Vuelva a cargar un modelo Keras nuevo desde el modelo guardado:
new_model = tf.keras.models.load_model('saved_model/my_model')
# Check its architecture
new_model.summary()
Model: "sequential_5" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_10 (Dense) (None, 512) 401920 dropout_5 (Dropout) (None, 512) 0 dense_11 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
El modelo restaurado se compila con los mismos argumentos que el modelo original. Intente ejecutar evaluar y predecir con el modelo cargado:
# Evaluate the restored model
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))
print(new_model.predict(test_images).shape)
32/32 - 0s - loss: 0.4577 - sparse_categorical_accuracy: 0.8430 - 156ms/epoch - 5ms/step Restored model, accuracy: 84.30% (1000, 10)
formato HDF5
Keras proporciona un formato de guardado básico utilizando el estándar HDF5 .
# Create and train a new model instance.
model = create_model()
model.fit(train_images, train_labels, epochs=5)
# Save the entire model to a HDF5 file.
# The '.h5' extension indicates that the model should be saved to HDF5.
model.save('my_model.h5')
Epoch 1/5 32/32 [==============================] - 0s 2ms/step - loss: 1.1383 - sparse_categorical_accuracy: 0.6970 Epoch 2/5 32/32 [==============================] - 0s 2ms/step - loss: 0.4094 - sparse_categorical_accuracy: 0.8920 Epoch 3/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2936 - sparse_categorical_accuracy: 0.9160 Epoch 4/5 32/32 [==============================] - 0s 2ms/step - loss: 0.2050 - sparse_categorical_accuracy: 0.9460 Epoch 5/5 32/32 [==============================] - 0s 2ms/step - loss: 0.1485 - sparse_categorical_accuracy: 0.9690
Ahora, vuelva a crear el modelo a partir de ese archivo:
# Recreate the exact same model, including its weights and the optimizer
new_model = tf.keras.models.load_model('my_model.h5')
# Show the model architecture
new_model.summary()
Model: "sequential_6" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_12 (Dense) (None, 512) 401920 dropout_6 (Dropout) (None, 512) 0 dense_13 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
Comprueba su precisión:
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))
32/32 - 0s - loss: 0.4266 - sparse_categorical_accuracy: 0.8620 - 141ms/epoch - 4ms/step Restored model, accuracy: 86.20%
Keras guarda modelos al inspeccionar sus arquitecturas. Esta técnica guarda todo:
- Los valores de peso
- La arquitectura del modelo.
- La configuración de entrenamiento del modelo (lo que pasa al método
.compile()
) - El optimizador y su estado, si lo hay (esto le permite reiniciar el entrenamiento donde lo dejó)
Keras no puede guardar los optimizadores v1.x
(de tf.compat.v1.train
) ya que no son compatibles con los puntos de control. Para los optimizadores v1.x, debe volver a compilar el modelo después de cargarlo, perdiendo el estado del optimizador.
Guardar objetos personalizados
Si está utilizando el formato de modelo guardado, puede omitir esta sección. La diferencia clave entre HDF5 y SavedModel es que HDF5 usa configuraciones de objetos para guardar la arquitectura del modelo, mientras que SavedModel guarda el gráfico de ejecución. Por lo tanto, los modelos guardados pueden guardar objetos personalizados, como modelos subclasificados y capas personalizadas, sin necesidad del código original.
Para guardar objetos personalizados en HDF5, debe hacer lo siguiente:
- Defina un método
get_config
en su objeto y, opcionalmente, un método defrom_config
.-
get_config(self)
devuelve un diccionario serializable JSON de parámetros necesarios para recrear el objeto. -
from_config(cls, config)
usa la configuración devuelta deget_config
para crear un nuevo objeto. De forma predeterminada, esta función utilizará la configuración como kwargs de inicialización (return cls(**config)
).
-
- Pase el objeto al argumento
custom_objects
al cargar el modelo. El argumento debe ser un diccionario que mapee el nombre de la clase de cadena a la clase de Python. Por ejemplotf.keras.models.load_model(path, custom_objects={'CustomLayer': CustomLayer})
Consulte el tutorial Escribir capas y modelos desde cero para ver ejemplos de objetos personalizados y get_config
.
# MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.