Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Modelos guardados de TF Hub en TensorFlow 2

El formato SavedModel de TensorFlow 2 es la forma recomendada de compartir modelos previamente entrenados y piezas de modelos en TensorFlow Hub. Reemplaza el formato TF1 Hub anterior y viene con un nuevo conjunto de API.

En esta página, se explica cómo reutilizar TF2 SavedModels en un programa de TensorFlow 2 con la API de bajo nivel hub.load() y su contenedor hub.KerasLayer . (Normalmente, hub.KerasLayer se combina con otros tf.keras.layers para construir un modelo Keras o el model_fn de un Estimador TF2). Estas API también pueden cargar los modelos heredados en formato TF1 Hub, dentro de los límites, consulte la guía de compatibilidad .

Los usuarios de TensorFlow 1 pueden actualizar a TF 1.15 y luego usar las mismas API. Las versiones anteriores de TF1 no funcionan.

Uso de modelos guardados de TF Hub

Usando un modelo guardado en Keras

Keras es la API de alto nivel de TensorFlow para crear modelos de aprendizaje profundo mediante la composición de objetos Keras Layer. La biblioteca tensorflow_hub proporciona la clase hub.KerasLayer que se inicializa con la URL (o la ruta del sistema de archivos) de un modelo guardado y luego proporciona el cálculo del modelo guardado, incluidos los pesos previamente entrenados.

A continuación, se muestra un ejemplo del uso de una inserción de texto previamente entrenada:

import tensorflow as tf
import tensorflow_hub as hub

hub_url = "https://tfhub.dev/google/tf2-preview/nnlm-en-dim128/1"
embed = hub.KerasLayer(hub_url)
embeddings = embed(["A long sentence.", "single-word", "http://example.com"])
print(embeddings.shape, embeddings.dtype)

A partir de esto, se puede construir un clasificador de texto de la forma habitual de Keras:

model = tf.keras.Sequential([
    embed,
    tf.keras.layers.Dense(16, activation="relu"),
    tf.keras.layers.Dense(1, activation="sigmoid"),
])

El laboratorio de clasificación de textos es un ejemplo completo de cómo entrenar y evaluar dicho clasificador.

Los pesos del modelo en un hub.KerasLayer están configurados como no entrenables de forma predeterminada. Consulte la sección de ajuste fino a continuación para saber cómo cambiar eso. Los pesos se comparten entre todas las aplicaciones del mismo objeto de capa, como es habitual en Keras.

Usar un modelo guardado en un estimador

Los usuarios de la API Estimator de TensorFlow para entrenamiento distribuido pueden usar SavedModels de TF Hub escribiendo su model_fn en términos de hub.KerasLayer entre otros tf.keras.layers .

Detrás de escena: descarga y almacenamiento en caché de modelos guardados

El uso de un modelo guardado de TensorFlow Hub (u otros servidores HTTPS que implementan su protocolo de alojamiento ) lo descarga y lo descomprime en el sistema de archivos local si aún no está presente. La variable de entorno TFHUB_CACHE_DIR se puede configurar para anular la ubicación temporal predeterminada para almacenar en caché los modelos guardados descargados y descomprimidos. Para obtener más información, consulte Almacenamiento en caché .

Usar un modelo guardado en TensorFlow de bajo nivel

La función hub.load(handle) descarga y descomprime un SavedModel (a menos que el handle ya sea una ruta del sistema de archivos) y luego devuelve el resultado de cargarlo con la función tf.saved_model.load() TensorFlow tf.saved_model.load() . Por lo tanto, hub.load() puede manejar cualquier modelo guardado válido (a diferencia de su predecesor hub.Module para TF1).

Tema avanzado: qué esperar del modelo guardado después de la carga

Dependiendo del contenido del modelo guardado, el resultado de obj = hub.load(...) se puede invocar de varias formas (como se explica con mucho más detalle en la Guía del modelo guardado de TensorFlow:

  • Las firmas de servicio del modelo guardado (si las hay) se representan como un diccionario de funciones concretas y se pueden llamar como tensors_out = obj.signatures["serving_default"](**tensors_in) , con diccionarios de tensores codificados por la entrada y salida respectivas nombres y sujeto a las restricciones de forma y tipo de la firma.

  • Los métodos @tf.function del objeto guardado (si los hay) se restauran como objetos tf.function que pueden ser llamados por todas las combinaciones de argumentos Tensor y no Tensor para los cuales se ha rastreado tf.function antes de guardar. En particular, si hay un método obj.__call__ con trazas adecuadas, obj sí mismo se puede llamar como una función de Python. Un ejemplo simple podría verse como output_tensor = obj(input_tensor, training=False) .

Esto deja una enorme libertad en las interfaces que pueden implementar SavedModels. La interfaz Reusable SavedModels para obj establece convenciones para que el código del cliente, incluidos los adaptadores como hub.KerasLayer , sepa cómo utilizar SavedModel.

Es posible que algunos modelos guardados no sigan esa convención, especialmente los modelos completos que no deben reutilizarse en modelos más grandes, y solo proporcionan firmas de servicio.

Las variables entrenables en un modelo guardado se vuelven a cargar como entrenables y tf.GradientTape verá de forma predeterminada. Consulte la sección sobre ajustes a continuación para ver algunas advertencias y, para empezar, considere evitar esto. Incluso si desea realizar un ajuste fino, es posible que desee ver si obj.trainable_variables aconseja volver a entrenar solo un subconjunto de las variables originalmente entrenables.

Creación de modelos guardados para TF Hub

Visión general

SavedModel es el formato de serialización estándar de TensorFlow para modelos entrenados o piezas de modelos. Almacena los pesos entrenados del modelo junto con las operaciones exactas de TensorFlow para realizar su cálculo. Se puede utilizar independientemente del código que lo creó. En particular, se puede reutilizar en diferentes API de creación de modelos de alto nivel como Keras, porque las operaciones de TensorFlow son su lenguaje básico común.

Ahorrando desde Keras

A partir de TensorFlow 2, tf.keras.Model.save() y tf.keras.models.save_model() forma predeterminada el formato SavedModel (no HDF5). Los modelos guardados resultantes que se pueden usar con hub.load() , hub.KerasLayer y adaptadores similares para otras API de alto nivel a medida que estén disponibles.

Para compartir un modelo completo de Keras, simplemente guárdelo con include_optimizer=False .

Para compartir una pieza de un modelo Keras, convierta la pieza en un modelo en sí mismo y luego guárdelo. Puede diseñar el código así desde el principio ...

piece_to_share = tf.keras.Model(...)
full_model = tf.keras.Sequential([piece_to_share, ...])
full_model.fit(...)
piece_to_share.save(...)

... o recorta la pieza para compartir después del hecho (si se alinea con las capas de tu modelo completo):

full_model = tf.keras.Model(...)
sharing_input = full_model.get_layer(...).get_output_at(0)
sharing_output = full_model.get_layer(...).get_output_at(0)
piece_to_share = tf.keras.Model(sharing_input, sharing_output)
piece_to_share.save(..., include_optimizer=False)

TensorFlow Modelos en GitHub utiliza el primer enfoque para el BERT (ver PNL / Bert / bert_models.py y PNL / Bert / export_tfhub.py , tenga en cuenta la división entre core_model y pretrain_model ) y el último enfoque para ResNet (ver la visión / image_classification / tfhub_export .py ).

Guardar desde TensorFlow de bajo nivel

Esto requiere una buena familiaridad con la Guía del modelo guardado de TensorFlow.

Si desea proporcionar algo más que una firma de publicación, debe implementar la interfaz Reutilizable SavedModel . Conceptualmente, esto parece

class MyMulModel(tf.train.Checkpoint):
  def __init__(self, v_init):
    super(MyMulModel, self).__init__()
    self.v = tf.Variable(v_init)
    self.variables = [self.v]
    self.trainable_variables = [self.v]
    self.regularization_losses = [
        tf.function(input_signature=[])(lambda: 0.001 * self.v**2),
    ]

  @tf.function(input_signature=[tf.TensorSpec(shape=None, dtype=tf.float32)])
  def __call__(self, inputs):
    return tf.multiply(inputs, self.v)

tf.saved_model.save(MyMulModel(2.0), "/tmp/my_mul")

layer = hub.KerasLayer("/tmp/my_mul")
print(layer([10., 20.]))  # [20., 40.]
layer.trainable = True
print(layer.trainable_weights)  # [2.]
print(layer.losses)  # 0.004

El código en tensorflow / examples / Saved_model / integration_tests / contiene ejemplos más grandes, esp. el par export_mnist.py y use_mnist.py .

Sintonia FINA

El entrenamiento de las variables ya entrenadas de un modelo guardado importado junto con las del modelo que lo rodea se denomina ajuste fino del modelo guardado. Esto puede resultar en una mejor calidad, pero a menudo hace que el entrenamiento sea más exigente (puede llevar más tiempo, depender más del optimizador y sus hiperparámetros, aumentar el riesgo de sobreajuste y requerir un aumento del conjunto de datos, especialmente para CNN). Aconsejamos a los consumidores de SavedModel que consideren el ajuste fino solo después de haber establecido un buen régimen de capacitación, y solo si el editor de SavedModel lo recomienda.

El ajuste fino cambia los parámetros del modelo "continuo" que se entrenan. No cambia las transformaciones codificadas de forma rígida, como la creación de tokens de entrada de texto y la asignación de tokens a sus entradas correspondientes en una matriz de incrustación.

Para consumidores de SavedModel

Creando un hub.KerasLayer como

layer = hub.KerasLayer(..., trainable=True)

habilita el ajuste fino del modelo guardado cargado por la capa. Agrega los pesos entrenables y los regularizadores de peso declarados en el modelo guardado al modelo de Keras y ejecuta el cálculo del modelo guardado en modo de entrenamiento (piense en la deserción, etc.).

El laboratorio de clasificación de imágenes contiene un ejemplo de un extremo a otro con un ajuste fino opcional.

Reexportar el resultado del ajuste fino

Los usuarios avanzados pueden querer guardar los resultados del ajuste fino nuevamente en un modelo guardado que se puede usar en lugar del que se cargó originalmente. Esto se puede hacer con código como

loaded_obj = hub.load("https://tfhub.dev/...")
hub_layer = hub.KerasLayer(loaded_obj, trainable=True, ...)

model = keras.Sequential([..., hub_layer, ...])
model.compile(...)
model.fit(...)

export_module_dir = os.path.join(os.getcwd(), "finetuned_model_export")
tf.saved_model.save(loaded_obj, export_module_dir)

Para creadores de modelos guardados

Al crear un modelo guardado para compartir en TensorFlow Hub, piense en el futuro si sus consumidores deberían ajustarlo y en qué forma, y ​​brinde orientación en la documentación.

Guardar desde un modelo de Keras debería hacer que todos los mecanismos de ajuste fino funcionen (ahorrar pérdidas de regularización de peso, declarar variables entrenables, rastrear __call__ tanto para training=True como para training=False , etc.)

Elija una interfaz de modelo que funcione bien con el flujo de gradiente, por ejemplo, logits de salida en lugar de probabilidades softmax o predicciones top-k.

Si el modelo usa abandono, normalización de lotes o técnicas de entrenamiento similares que involucran hiperparámetros, configúrelos en valores que tengan sentido en muchos problemas de destino esperados y tamaños de lote. (Al momento de escribir estas líneas, guardar desde Keras no facilita que los consumidores los ajusten, pero consulte tensorflow / examples / Saved_model / integration_tests / export_mnist_cnn.py para conocer algunas soluciones crudas).

Los regularizadores de peso en capas individuales se guardan (con sus coeficientes de fuerza de regularización), pero se pierde la regularización de peso desde el optimizador (como tf.keras.optimizers.Ftrl.l1_regularization_strength=...) ). Avise a los consumidores de su modelo guardado en consecuencia.