Format Hub TF1

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Lors de son lancement en 2018, TensorFlow Hub proposait un seul type d'asset : le format TF1 Hub pour l'import dans les programmes TensorFlow 1.

Cette page explique comment utiliser le format TF1 Hub dans TF1 (ou le mode de compatibilité TF1 de TF2) avec la classe hub.Module et les API associées. (L'utilisation typique est de construire un tf.Graph , éventuellement à l'intérieur d'un TF1 Estimator , en combinant un ou plusieurs modèles au format TF1 Hub avec tf.compat.layers ou tf.layers ).

Les utilisateurs de TensorFlow 2 (hors mode de compatibilité TF1) doivent utiliser la nouvelle API avec hub.load() ou hub.KerasLayer . La nouvelle API charge le nouveau type d'actif TF2 SavedModel, mais offre également une prise en charge limitée du chargement du format TF1 Hub dans TF2 .

Utiliser un modèle au format TF1 Hub

Instanciation d'un modèle au format TF1 Hub

Un modèle au format TF1 Hub est importé dans un programme TensorFlow en créant un objet hub.Module à partir d'une chaîne avec son URL ou son chemin de système de fichiers, par exemple :

m = hub.Module("path/to/a/module_dir")

Remarque : Pour plus d'informations sur les autres types de descripteurs valides, cliquez ici .

Cela ajoute les variables du module au graphique TensorFlow actuel. L'exécution de leurs initialiseurs lira leurs valeurs pré-formées à partir du disque. De même, des tables et d'autres états sont ajoutés au graphique.

Modules de mise en cache

Lors de la création d'un module à partir d'une URL, le contenu du module est téléchargé et mis en cache dans le répertoire temporaire du système local. L'emplacement où les modules sont mis en cache peut être remplacé à l'aide de la variable d'environnement TFHUB_CACHE_DIR . Pour plus de détails, consultez Mise en cache .

Appliquer un module

Une fois instancié, un module m peut être appelé zéro ou plusieurs fois comme une fonction Python des entrées du tenseur aux sorties du tenseur :

y = m(x)

Chacun de ces appels ajoute des opérations au graphe TensorFlow actuel pour calculer y à partir de x . Si cela implique des variables avec des poids formés, ceux-ci sont partagés entre toutes les applications.

Les modules peuvent définir plusieurs signatures nommées afin de permettre leur application de plusieurs manières (similaire à la façon dont les objets Python ont des méthodes ). La documentation d'un module doit décrire les signatures disponibles. L'appel ci-dessus applique la signature nommée "default" . Toute signature peut être sélectionnée en passant son nom à l'argument facultatif signature= .

Si une signature a plusieurs entrées, elles doivent être transmises sous forme de dict, avec les clés définies par la signature. De même, si une signature a plusieurs sorties, celles-ci peuvent être récupérées sous forme de dict en passant as_dict=True , sous les clés définies par la signature (la clé "default" est pour la sortie unique renvoyée si as_dict=False ). Ainsi, la forme la plus générale d'application d'un module ressemble à :

outputs = m(dict(apples=x1, oranges=x2), signature="fruit_to_pet", as_dict=True)
y1 = outputs["cats"]
y2 = outputs["dogs"]

Un appelant doit fournir toutes les entrées définies par une signature, mais il n'est pas nécessaire d'utiliser toutes les sorties d'un module. TensorFlow n'exécutera que les parties du module qui finissent comme dépendances d'une cible dans tf.Session.run() . En effet, les éditeurs de modules peuvent choisir de fournir diverses sorties pour des usages avancés (comme des activations de couches intermédiaires) en plus des sorties principales. Les consommateurs de modules doivent gérer les sorties supplémentaires avec élégance.

Tester des modules alternatifs

Chaque fois qu'il existe plusieurs modules pour la même tâche, TensorFlow Hub encourage à les équiper de signatures (interfaces) compatibles, de sorte qu'en essayer différentes est aussi simple que de modifier le descripteur de module en tant qu'hyperparamètre à valeur de chaîne.

À cette fin, nous maintenons une collection de signatures communes recommandées pour les tâches courantes.

Création d'un nouveau module

Remarque sur la compatibilité

Le format TF1 Hub est orienté vers TensorFlow 1. Il n'est que partiellement pris en charge par TF Hub dans TensorFlow 2. Veuillez plutôt envisager de publier au nouveau format TF2 SavedModel .

Le format TF1 Hub est similaire au format SavedModel de TensorFlow 1 sur le plan syntaxique (mêmes noms de fichiers et messages de protocole) mais sémantiquement différent pour permettre la réutilisation, la composition et le réapprentissage des modules (par exemple, stockage différent des initialiseurs de ressources, étiquetage différent conventions pour les métagraphes). Le moyen le plus simple de les différencier sur le disque est la présence ou l'absence du fichier tfhub_module.pb .

Approche générale

Pour définir un nouveau module, un éditeur appelle hub.create_module_spec() avec une fonction module_fn . Cette fonction construit un graphe représentant la structure interne du module, en utilisant tf.placeholder() pour les entrées à fournir par l'appelant. Ensuite, il définit les signatures en appelant hub.add_signature(name, inputs, outputs) une ou plusieurs fois.

Par exemple:

def module_fn():
  inputs = tf.placeholder(dtype=tf.float32, shape=[None, 50])
  layer1 = tf.layers.dense(inputs, 200)
  layer2 = tf.layers.dense(layer1, 100)
  outputs = dict(default=layer2, hidden_activations=layer1)
  # Add default signature.
  hub.add_signature(inputs=inputs, outputs=outputs)

...
spec = hub.create_module_spec(module_fn)

Le résultat de hub.create_module_spec() peut être utilisé, au lieu d'un chemin, pour instancier un objet module dans un graphique TensorFlow particulier. Dans ce cas, il n'y a pas de point de contrôle et l'instance de module utilisera les initialiseurs de variables à la place.

Toute instance de module peut être sérialisée sur disque via sa méthode export(path, session) . L'exportation d'un module sérialise sa définition avec l'état actuel de ses variables en session dans le chemin transmis. Cela peut être utilisé lors de l'exportation d'un module pour la première fois, ainsi que lors de l'exportation d'un module affiné.

Pour assurer la compatibilité avec TensorFlow Estimators, hub.LatestModuleExporter exporte les modules à partir du dernier point de contrôle, tout comme tf.estimator.LatestExporter exporte l'intégralité du modèle à partir du dernier point de contrôle.

Les éditeurs de modules doivent implémenter une signature commune lorsque cela est possible, afin que les consommateurs puissent facilement échanger des modules et trouver celui qui convient le mieux à leur problème.

Exemple réel

Jetez un œil à notre exportateur de module d'intégration de texte pour un exemple concret de création d'un module à partir d'un format d'intégration de texte courant.

Réglage fin

L'entraînement des variables d'un module importé avec celles du modèle qui l'entoure est appelé réglage fin . Un réglage fin peut entraîner une meilleure qualité, mais ajoute de nouvelles complications. Nous conseillons aux consommateurs de se pencher sur le réglage fin uniquement après avoir exploré des réglages de qualité plus simples, et uniquement si l'éditeur du module le recommande.

Pour les consommateurs

Pour activer le réglage fin, instanciez le module avec hub.Module(..., trainable=True) pour rendre ses variables entraînables et importez REGULARIZATION_LOSSES de TensorFlow. Si le module comporte plusieurs variantes de graphique, assurez-vous de choisir celle qui convient à la formation. Habituellement, c'est celui avec les balises {"train"} .

Choisissez un régime d'entraînement qui ne ruine pas les poids pré-entraînés, par exemple, un taux d'apprentissage inférieur à celui d'un entraînement à partir de zéro.

Pour les éditeurs

Afin de faciliter le réglage fin pour les consommateurs, veuillez tenir compte des points suivants :

  • Le réglage fin nécessite une régularisation. Votre module est exporté avec la collection REGULARIZATION_LOSSES , qui place votre choix de tf.layers.dense(..., kernel_regularizer=...) etc. dans ce que le consommateur obtient de tf.losses.get_regularization_losses() . Préférez cette façon de définir les pertes de régularisation L1/L2.

  • Dans le modèle d'éditeur, évitez de définir la régularisation L1/L2 via les paramètres l1_ et l2_regularization_strength de tf.train.FtrlOptimizer , tf.train.ProximalGradientDescentOptimizer et d'autres optimiseurs proximaux. Ceux-ci ne sont pas exportés avec le module, et la définition globale des forces de régularisation peut ne pas convenir au consommateur. À l'exception de la régularisation L1 dans les modèles larges (c'est-à-dire linéaires creux) ou larges et profonds, il devrait être possible d'utiliser à la place des pertes de régularisation individuelles.

  • Si vous utilisez l'abandon, la normalisation par lots ou des techniques de formation similaires, définissez leurs hyperparamètres sur des valeurs qui ont du sens pour de nombreuses utilisations attendues. Le taux d'abandon peut devoir être ajusté à la propension du problème cible au surapprentissage. Dans la normalisation par lots, la quantité de mouvement (c'est-à-dire le coefficient de décroissance) doit être suffisamment petite pour permettre un réglage fin avec de petits ensembles de données et/ou de grands lots. Pour les consommateurs avancés, envisagez d'ajouter une signature qui expose le contrôle sur les hyperparamètres critiques.

,

Lors de son lancement en 2018, TensorFlow Hub proposait un seul type d'asset : le format TF1 Hub pour l'import dans les programmes TensorFlow 1.

Cette page explique comment utiliser le format TF1 Hub dans TF1 (ou le mode de compatibilité TF1 de TF2) avec la classe hub.Module et les API associées. (L'utilisation typique est de construire un tf.Graph , éventuellement à l'intérieur d'un TF1 Estimator , en combinant un ou plusieurs modèles au format TF1 Hub avec tf.compat.layers ou tf.layers ).

Les utilisateurs de TensorFlow 2 (hors mode de compatibilité TF1) doivent utiliser la nouvelle API avec hub.load() ou hub.KerasLayer . La nouvelle API charge le nouveau type d'actif TF2 SavedModel, mais offre également une prise en charge limitée du chargement du format TF1 Hub dans TF2 .

Utiliser un modèle au format TF1 Hub

Instanciation d'un modèle au format TF1 Hub

Un modèle au format TF1 Hub est importé dans un programme TensorFlow en créant un objet hub.Module à partir d'une chaîne avec son URL ou son chemin de système de fichiers, par exemple :

m = hub.Module("path/to/a/module_dir")

Remarque : Pour plus d'informations sur les autres types de descripteurs valides, cliquez ici .

Cela ajoute les variables du module au graphique TensorFlow actuel. L'exécution de leurs initialiseurs lira leurs valeurs pré-formées à partir du disque. De même, des tables et d'autres états sont ajoutés au graphique.

Modules de mise en cache

Lors de la création d'un module à partir d'une URL, le contenu du module est téléchargé et mis en cache dans le répertoire temporaire du système local. L'emplacement où les modules sont mis en cache peut être remplacé à l'aide de la variable d'environnement TFHUB_CACHE_DIR . Pour plus de détails, consultez Mise en cache .

Appliquer un module

Une fois instancié, un module m peut être appelé zéro ou plusieurs fois comme une fonction Python des entrées du tenseur aux sorties du tenseur :

y = m(x)

Chacun de ces appels ajoute des opérations au graphe TensorFlow actuel pour calculer y à partir de x . Si cela implique des variables avec des poids formés, ceux-ci sont partagés entre toutes les applications.

Les modules peuvent définir plusieurs signatures nommées afin de permettre leur application de plusieurs manières (similaire à la façon dont les objets Python ont des méthodes ). La documentation d'un module doit décrire les signatures disponibles. L'appel ci-dessus applique la signature nommée "default" . Toute signature peut être sélectionnée en passant son nom à l'argument facultatif signature= .

Si une signature a plusieurs entrées, elles doivent être transmises sous forme de dict, avec les clés définies par la signature. De même, si une signature a plusieurs sorties, celles-ci peuvent être récupérées sous forme de dict en passant as_dict=True , sous les clés définies par la signature (la clé "default" est pour la sortie unique renvoyée si as_dict=False ). Ainsi, la forme la plus générale d'application d'un module ressemble à :

outputs = m(dict(apples=x1, oranges=x2), signature="fruit_to_pet", as_dict=True)
y1 = outputs["cats"]
y2 = outputs["dogs"]

Un appelant doit fournir toutes les entrées définies par une signature, mais il n'est pas nécessaire d'utiliser toutes les sorties d'un module. TensorFlow n'exécutera que les parties du module qui finissent comme dépendances d'une cible dans tf.Session.run() . En effet, les éditeurs de modules peuvent choisir de fournir diverses sorties pour des usages avancés (comme des activations de couches intermédiaires) en plus des sorties principales. Les consommateurs de modules doivent gérer les sorties supplémentaires avec élégance.

Tester des modules alternatifs

Chaque fois qu'il existe plusieurs modules pour la même tâche, TensorFlow Hub encourage à les équiper de signatures (interfaces) compatibles, de sorte qu'en essayer différentes est aussi simple que de modifier le descripteur de module en tant qu'hyperparamètre à valeur de chaîne.

À cette fin, nous maintenons une collection de signatures communes recommandées pour les tâches courantes.

Création d'un nouveau module

Remarque sur la compatibilité

Le format TF1 Hub est orienté vers TensorFlow 1. Il n'est que partiellement pris en charge par TF Hub dans TensorFlow 2. Veuillez plutôt envisager de publier au nouveau format TF2 SavedModel .

Le format TF1 Hub est similaire au format SavedModel de TensorFlow 1 sur le plan syntaxique (mêmes noms de fichiers et messages de protocole) mais sémantiquement différent pour permettre la réutilisation, la composition et le réapprentissage des modules (par exemple, stockage différent des initialiseurs de ressources, étiquetage différent conventions pour les métagraphes). Le moyen le plus simple de les différencier sur le disque est la présence ou l'absence du fichier tfhub_module.pb .

Approche générale

Pour définir un nouveau module, un éditeur appelle hub.create_module_spec() avec une fonction module_fn . Cette fonction construit un graphe représentant la structure interne du module, en utilisant tf.placeholder() pour les entrées à fournir par l'appelant. Ensuite, il définit les signatures en appelant hub.add_signature(name, inputs, outputs) une ou plusieurs fois.

Par exemple:

def module_fn():
  inputs = tf.placeholder(dtype=tf.float32, shape=[None, 50])
  layer1 = tf.layers.dense(inputs, 200)
  layer2 = tf.layers.dense(layer1, 100)
  outputs = dict(default=layer2, hidden_activations=layer1)
  # Add default signature.
  hub.add_signature(inputs=inputs, outputs=outputs)

...
spec = hub.create_module_spec(module_fn)

Le résultat de hub.create_module_spec() peut être utilisé, au lieu d'un chemin, pour instancier un objet module dans un graphique TensorFlow particulier. Dans ce cas, il n'y a pas de point de contrôle et l'instance de module utilisera les initialiseurs de variable à la place.

Toute instance de module peut être sérialisée sur disque via sa méthode export(path, session) . L'exportation d'un module sérialise sa définition avec l'état actuel de ses variables en session dans le chemin transmis. Cela peut être utilisé lors de l'exportation d'un module pour la première fois, ainsi que lors de l'exportation d'un module affiné.

Pour assurer la compatibilité avec TensorFlow Estimators, hub.LatestModuleExporter exporte les modules à partir du dernier point de contrôle, tout comme tf.estimator.LatestExporter exporte l'intégralité du modèle à partir du dernier point de contrôle.

Les éditeurs de modules doivent implémenter une signature commune lorsque cela est possible, afin que les consommateurs puissent facilement échanger des modules et trouver celui qui convient le mieux à leur problème.

Exemple réel

Jetez un œil à notre exportateur de module d'intégration de texte pour un exemple concret de création d'un module à partir d'un format d'intégration de texte courant.

Réglage fin

L'entraînement des variables d'un module importé avec celles du modèle qui l'entoure est appelé réglage fin . Un réglage fin peut entraîner une meilleure qualité, mais ajoute de nouvelles complications. Nous conseillons aux consommateurs de se pencher sur le réglage fin uniquement après avoir exploré des réglages de qualité plus simples, et uniquement si l'éditeur du module le recommande.

Pour les consommateurs

Pour activer le réglage fin, instanciez le module avec hub.Module(..., trainable=True) pour rendre ses variables entraînables et importez REGULARIZATION_LOSSES de TensorFlow. Si le module comporte plusieurs variantes de graphique, assurez-vous de choisir celle qui convient à la formation. Habituellement, c'est celui avec les balises {"train"} .

Choisissez un régime d'entraînement qui ne ruine pas les poids pré-entraînés, par exemple, un taux d'apprentissage inférieur à celui d'un entraînement à partir de zéro.

Pour les éditeurs

Afin de faciliter le réglage fin pour les consommateurs, veuillez tenir compte des points suivants :

  • Le réglage fin nécessite une régularisation. Votre module est exporté avec la collection REGULARIZATION_LOSSES , qui place votre choix de tf.layers.dense(..., kernel_regularizer=...) etc. dans ce que le consommateur obtient de tf.losses.get_regularization_losses() . Préférez cette façon de définir les pertes de régularisation L1/L2.

  • Dans le modèle d'éditeur, évitez de définir la régularisation L1/L2 via les paramètres l1_ et l2_regularization_strength de tf.train.FtrlOptimizer , tf.train.ProximalGradientDescentOptimizer et d'autres optimiseurs proximaux. Ceux-ci ne sont pas exportés avec le module, et la définition globale des forces de régularisation peut ne pas convenir au consommateur. À l'exception de la régularisation L1 dans les modèles larges (c'est-à-dire linéaires creux) ou larges et profonds, il devrait être possible d'utiliser à la place des pertes de régularisation individuelles.

  • Si vous utilisez l'abandon, la normalisation par lots ou des techniques de formation similaires, définissez leurs hyperparamètres sur des valeurs qui ont du sens pour de nombreuses utilisations attendues. Le taux d'abandon peut devoir être ajusté à la propension du problème cible au surapprentissage. Dans la normalisation par lots, la quantité de mouvement (c'est-à-dire le coefficient de décroissance) doit être suffisamment petite pour permettre un réglage fin avec de petits ensembles de données et/ou de grands lots. Pour les consommateurs avancés, envisagez d'ajouter une signature qui expose le contrôle sur les hyperparamètres critiques.