Modèles enregistrés de TF Hub dans TensorFlow 2

Le format de SavedModel de tensorflow 2 est la méthode recommandée pour les modèles pré-formés et part des pièces de modèle sur tensorflow Hub. Elle remplace l'ancienne forme TF1 Hub et est livré avec une nouvelle série d'API.

Cette page explique comment réutiliser TF2 SavedModels dans un programme tensorflow 2 avec le faible niveau hub.load() API et son hub.KerasLayer emballage. ( En règle générale, hub.KerasLayer est combiné avec d' autres tf.keras.layers pour construire un modèle Keras ou model_fn d'un estimateur TF2.) Ces API peuvent également charger les modèles existants au format TF1 Hub, dans certaines limites, voir le guide de compatibilité .

Les utilisateurs de TensorFlow 1 peuvent mettre à jour vers TF 1.15, puis utiliser les mêmes API. Les anciennes versions de TF1 ne fonctionnent pas.

Utilisation de SavedModels de TF Hub

Utilisation d'un modèle enregistré dans Keras

Keras est l'API de haut niveau de tensorflow pour la construction de modèles d' apprentissage en profondeur en composant KERAS objets de calque. La tensorflow_hub bibliothèque fournit la classe hub.KerasLayer qui obtient initialisé avec l'URL (ou le chemin système de fichiers) d'un SavedModel et fournit ensuite le calcul de la SavedModel, y compris les poids pré-formés.

Voici un exemple d'utilisation d'une intégration de texte pré-entraînée :

import tensorflow as tf
import tensorflow_hub as hub

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

À partir de là, un classificateur de texte peut être construit de la manière habituelle de Keras :

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

La classification du texte colab est un exemple complet comment former et évaluer un tel classificateur.

Les coefficients de pondération du modèle dans un hub.KerasLayer sont fixés à la non-entraînable par défaut. Voir la section sur le réglage fin ci-dessous pour savoir comment changer cela. Les poids sont partagés entre toutes les applications du même objet de couche, comme d'habitude dans Keras.

Utilisation d'un modèle enregistré dans un estimateur

Les utilisateurs de tensorflow de prévision de l' API pour la formation distribuée peuvent utiliser SavedModels de TF Hub en écrivant leur model_fn en termes de hub.KerasLayer entre autres tf.keras.layers .

Dans les coulisses : téléchargement et mise en cache de SavedModel

L' utilisation d' un SavedModel de tensorflow Hub (ou d' autres serveurs HTTPS qui mettent en œuvre son hébergement protocole) télécharge et décompresse au système de fichiers local si pas déjà présent. La variable d'environnement TFHUB_CACHE_DIR peut être réglé pour remplacer l'emplacement temporaire par défaut pour la mise en cache des SavedModels téléchargés et non compressés. Pour plus de détails, voir Mise en cache .

Utiliser un modèle enregistré dans TensorFlow de bas niveau

La fonction hub.load(handle) téléchargements et décompresse un SavedModel ( à moins que la handle est déjà un chemin de système de fichiers), puis renvoie le résultat de son chargement avec fonction intégrée de tensorflow tf.saved_model.load() . Par conséquent, hub.load() peut gérer toute SavedModel valide (contrairement à son prédécesseur hub.Module pour TF1).

Sujet avancé : à quoi s'attendre du SavedModel après le chargement

Selon le contenu du SavedModel, le résultat de obj = hub.load(...) peut être invoqué de diverses manières (comme expliqué beaucoup plus en détail dans de tensorflow SavedModel Guide :

  • Les signatures de desserte des SavedModel ( le cas échéant) sont représentés sous forme d' un dictionnaire de fonctions de béton et peuvent être appelés comme tensors_out = obj.signatures["serving_default"](**tensors_in) , avec les dictionnaires de tenseurs calées par l'entrée et la sortie respective noms et soumis aux contraintes de forme et de type de la signature.

  • Les @tf.function méthodes -decorated de l'objet enregistré ( le cas échéant) sont restaurés sous forme d' objets tf.function qui peuvent être appelées par toutes les combinaisons d'arguments Tensor et non Tensor pour lesquels le tf.function avait été tracé avant l'enregistrement. En particulier, s'il y a un obj.__call__ méthode avec des traces appropriées, obj lui - même peut être appelé comme une fonction Python. Un exemple simple pourrait ressembler à output_tensor = obj(input_tensor, training=False) .

Cela laisse une énorme liberté dans les interfaces que SavedModels peut implémenter. L' interface de obj hub.KerasLayer SavedModels réutilisables pour obj établit des conventions telles que le code client, y compris les adaptateurs comme hub.KerasLayer , savent comment utiliser le SavedModel.

Certains SavedModels peuvent ne pas suivre cette convention, en particulier les modèles entiers qui ne sont pas destinés à être réutilisés dans des modèles plus grands, et fournissent simplement des signatures de service.

Les variables trainable dans un SavedModel sont rechargés comme trainable et tf.GradientTape les regarderons par défaut. Voir la section sur le réglage fin ci-dessous pour quelques mises en garde, et envisagez d'éviter cela pour commencer. Même si vous voulez affiner, vous pouvez voir si obj.trainable_variables conseille de re-former un sous - ensemble des variables à l' origine trainable.

Création de modèles enregistrés pour TF Hub

Aperçu

SavedModel est le format de sérialisation standard de TensorFlow pour les modèles entraînés ou les pièces de modèle. Il stocke les poids entraînés du modèle avec les opérations TensorFlow exactes pour effectuer son calcul. Il peut être utilisé indépendamment du code qui l'a créé. En particulier, il peut être réutilisé dans différentes API de création de modèles de haut niveau comme Keras, car les opérations TensorFlow sont leur langage de base commun.

Sauver de Keras

A partir de tensorflow 2, tf.keras.Model.save() et tf.keras.models.save_model() par défaut au format SavedModel (non HDF5). Les SavedModels résultants qui peuvent être utilisés avec hub.load() , hub.KerasLayer et adaptateurs similaires pour d' autres API de haut niveau qu'ils deviennent disponibles.

Pour partager un modèle complet Keras, enregistrez avec include_optimizer=False .

Pour partager une pièce d'un modèle Keras, faites de la pièce un modèle en soi, puis enregistrez-la. Vous pouvez soit disposer le code comme ça dès le début....

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

...ou découpez la pièce à partager après coup (si elle s'aligne avec la superposition de votre modèle complet) :

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 modèles sur GitHub utilise l'ancienne approche pour BERT (voir NLP / outils / export_tfhub_lib.py , notez la scission entre core_model pour l' exportation et le pretrainer pour restaurer le point de contrôle) et la dernière approche pour ResNet (voir la vision / image_classification / tfhub_export. py ).

Enregistrement à partir de TensorFlow de bas niveau

Cela nécessite une bonne connaissance de tensorflow Guide SavedModel .

Si vous voulez fournir plus qu'une simple signature au service, vous devez implémenter l' interface de réutilisable SavedModel . Conceptuellement, cela ressemble à

class MyMulModel(tf.train.Checkpoint):
  def __init__(self, v_init):
    super().__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

Réglage fin

La formation des variables d'un SavedModel importé déjà formés en même temps que ceux du modèle autour d' elle est appelée réglage fin de la SavedModel. Cela peut entraîner une meilleure qualité, mais rend souvent la formation plus exigeante (peut prendre plus de temps, dépend davantage de l'optimiseur et de ses hyperparamètres, augmente le risque de surapprentissage et nécessite une augmentation de l'ensemble de données, en particulier pour les CNN). Nous conseillons aux consommateurs de SavedModel de n'envisager un réglage fin qu'après avoir établi un bon régime d'entraînement, et uniquement si l'éditeur de SavedModel le recommande.

Le réglage fin modifie les paramètres de modèle « continus » qui sont entraînés. Il ne modifie pas les transformations codées en dur, telles que la tokenisation de l'entrée de texte et le mappage des jetons sur leurs entrées correspondantes dans une matrice d'incorporation.

Pour les consommateurs de SavedModel

Création d' un hub.KerasLayer comme

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

permet d'affiner le SavedModel chargé par la couche. Il ajoute les poids entraînables et les régularisations de poids déclarés dans le SavedModel au modèle Keras, et exécute le calcul du SavedModel en mode d'entraînement (pensez à l'abandon, etc.).

La classification d'image colab contient un exemple de bout en bout avec réglage fin en option.

Réexporter le résultat du réglage fin

Les utilisateurs avancés peuvent vouloir enregistrer les résultats du réglage fin dans un SavedModel qui peut être utilisé à la place de celui chargé à l'origine. Cela peut être fait avec un code comme

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)

Pour les créateurs de SavedModel

Lors de la création d'un modèle enregistré à partager sur TensorFlow Hub, réfléchissez à l'avance si et comment ses utilisateurs doivent l'affiner, et fournissez des conseils dans la documentation.

Enregistrement à partir d' un modèle Keras doit faire tous les mécanismes de travail réglage fin (économie des pertes de régularisation de poids, la déclaration des variables trainable, le suivi __call__ à la fois la training=True et la training=False , etc.)

Choisissez une interface de modèle qui fonctionne bien avec le flux de gradient, par exemple, des logits de sortie au lieu des probabilités softmax ou des prédictions top-k.

Si le modèle utilise l'abandon, la normalisation par lots ou des techniques d'entraînement similaires impliquant des hyperparamètres, définissez-les sur des valeurs qui ont du sens pour de nombreux problèmes cibles et tailles de lots attendus. (Au moment d'écrire ces lignes, économiser de Keras ne permet pas aux consommateurs de les ajuster facilement.)

Poids sur des couches individuelles régularisations sont enregistrées (avec leurs coefficients de force de régularisation), mais la régularisation de poids de l'optimiseur (comme tf.keras.optimizers.Ftrl.l1_regularization_strength=...) ) est perdu. Informez les consommateurs de votre SavedModel en conséquence.