Introduction
TensorFlow Hub héberge SavedModels pour TensorFlow 2, entre autres actifs. Ils peuvent être rechargés dans un programme Python avec obj = hub.load(url)
[en savoir plus ]. L' obj
renvoyé est le résultat de tf.saved_model.load()
(voir le guide SavedModel de TensorFlow). Cet objet peut avoir des attributs arbitraires qui sont tf.functions, tf.Variables (initialisés à partir de leurs valeurs pré-formées), d'autres ressources et, récursivement, d'autres objets de ce type.
Cette page décrit une interface à implémenter par l'objet chargé obj
d'être réutilisée dans un programme TensorFlow Python. Les SavedModels conformes à cette interface sont appelés Reusable SavedModels .
Réutiliser signifie construire un modèle plus grand autour de obj
, y compris la possibilité de l'affiner. Le réglage fin signifie un entraînement supplémentaire des poids dans l'objet chargé obj
le cadre du modèle environnant. La fonction de perte et l'optimiseur sont déterminés par le modèle environnant ; obj
définit uniquement le mappage des activations d'entrée à sortie (la "passe avant"), incluant éventuellement des techniques telles que l'abandon ou la normalisation par lots.
L'équipe TensorFlow Hub recommande d'implémenter l'interface Reusable SavedModel dans tous les SavedModels destinés à être réutilisés dans le sens ci-dessus. De nombreux utilitaires de la bibliothèque tensorflow_hub
, notamment hub.KerasLayer
, nécessitent SavedModels pour l'implémenter.
Relation avec SignatureDefs
Cette interface en termes de tf.functions et d'autres fonctionnalités de TF2 est distincte des signatures de SavedModel, qui sont disponibles depuis TF1 et continuent d'être utilisées dans TF2 pour l'inférence (comme le déploiement de SavedModels sur TF Serving ou TF Lite). Les signatures pour l'inférence ne sont pas assez expressives pour prendre en charge le réglage fin, et tf.function
fournit une API Python plus naturelle et expressive pour le modèle réutilisé.
Relation avec les bibliothèques de création de modèles
Un SavedModel réutilisable utilise uniquement des primitives TensorFlow 2, indépendamment de toute bibliothèque de création de modèles particulière comme Keras ou Sonnet. Cela facilite la réutilisation dans les bibliothèques de création de modèles, sans dépendances vis-à-vis du code de création de modèles d'origine.
Une certaine quantité d'adaptation sera nécessaire pour charger les modèles enregistrés réutilisables ou les enregistrer à partir de n'importe quelle bibliothèque de création de modèles donnée. Pour Keras, hub.KerasLayer fournit le chargement, et la sauvegarde intégrée de Keras au format SavedModel a été repensée pour TF2 dans le but de fournir un sur-ensemble de cette interface (voir la RFC de mai 2019).
Relation avec les "API SavedModel communes" spécifiques à la tâche
La définition d'interface sur cette page permet n'importe quel nombre et type d'entrées et de sorties. Les API Common SavedModel pour TF Hub affinent cette interface générale avec des conventions d'utilisation pour des tâches spécifiques afin de rendre les modèles facilement interchangeables.
Définition des interfaces
Les attributs
Un SavedModel réutilisable est un SavedModel TensorFlow 2 tel que obj = tf.saved_model.load(...)
renvoie un objet qui a les attributs suivants
__call__
. Obligatoire. Une fonction tf.implémentant le calcul du modèle (la "passe avant") soumise à la spécification ci-dessous.variables
: une liste d'objets tf.Variable , répertoriant toutes les variables utilisées par toute invocation possible de__call__
, y compris celles pouvant être entraînées et non entraînées.Cette liste peut être omise si elle est vide.
trainable_variables
: une liste d'objets tf.Variable tels quev.trainable
est vrai pour tous les éléments. Ces variables doivent être un sous-ensemble devariables
. Ce sont les variables à former lors du réglage fin de l'objet. Le créateur de SavedModel peut choisir d'omettre ici certaines variables qui étaient à l'origine formables pour indiquer qu'elles ne doivent pas être modifiées lors du réglage fin.Cette liste peut être omise si elle est vide, en particulier si le SavedModel ne prend pas en charge le réglage fin.
regularization_losses
: une liste de tf.functions, chacune prenant zéro entrée et renvoyant un seul tenseur flottant scalaire. Pour un réglage fin, il est conseillé à l'utilisateur de SavedModel de les inclure en tant que termes de régularisation supplémentaires dans la perte (dans le cas le plus simple, sans mise à l'échelle supplémentaire). Généralement, ceux-ci sont utilisés pour représenter des régularisateurs de poids. (Par manque d'entrées, ces tf.functions ne peuvent pas exprimer de régularisateurs d'activité.)Cette liste peut être omise si elle est vide, en particulier si le SavedModel ne prend pas en charge le réglage fin ou ne souhaite pas prescrire de régularisation du poids.
La fonction __call__
Un objet SavedModel restauré a un attribut obj
obj.__call__
qui est une fonction tf.restaurée et permet à obj
d'être appelé comme suit.
Synopsis (pseudo-code):
outputs = obj(inputs, trainable=..., **kwargs)
Arguments
Les arguments sont les suivants.
Il existe un argument positionnel obligatoire avec un lot d'activations d'entrée du modèle enregistré. Son type est l'un des
- un seul Tenseur pour une seule entrée,
- une liste de Tenseurs pour une séquence ordonnée d'entrées sans nom,
- un dict de Tensors indexé par un ensemble particulier de noms d'entrée.
(Les futures révisions de cette interface peuvent autoriser des nids plus généraux.) Le créateur de SavedModel choisit l'un de ceux-ci ainsi que les formes et les dtypes du tenseur. Lorsque cela est utile, certaines dimensions de la forme doivent être indéfinies (notamment la taille du lot).
Il peut y avoir une
training
argument de mot clé facultative qui accepte un booléen Python,True
ouFalse
. La valeur par défaut estFalse
. Si le modèle prend en charge le réglage fin et si son calcul diffère entre les deux (par exemple, comme dans l'abandon et la normalisation par lots), cette distinction est implémentée avec cet argument. Sinon, cet argument peut être absent.Il n'est pas nécessaire que
__call__
accepte un argumenttraining
à valeur Tensor. Il incombe à l'appelant d'utilisertf.cond()
si nécessaire pour se répartir entre eux.Le créateur de SavedModel peut choisir d'accepter plus de
kwargs
facultatifs de noms particuliers.Pour les arguments à valeur Tensor, le créateur de SavedModel définit leurs dtypes et formes autorisés.
tf.function
accepte une valeur Python par défaut sur un argument tracé avec une entrée tf.TensorSpec. De tels arguments peuvent être utilisés pour permettre la personnalisation des hyperparamètres numériques impliqués dans__call__
(par exemple, le taux d'abandon).Pour les arguments à valeur Python, le créateur de SavedModel définit leurs valeurs autorisées. De tels arguments peuvent être utilisés comme drapeaux pour faire des choix discrets dans la fonction tracée (mais attention à l'explosion combinatoire des traces).
La fonction __call__
restaurée doit fournir des traces pour toutes les combinaisons d'arguments autorisées. L'inversion training
entre True
et False
ne doit pas modifier la licéité des arguments.
Résultat
Les outputs
de l'appel d' obj
peuvent être
- un seul Tenseur pour une seule sortie,
- une liste de Tenseurs pour une séquence ordonnée de sorties sans nom,
- un dict de Tensors indexé par un ensemble particulier de noms de sortie.
(Les futures révisions de cette interface peuvent autoriser des imbrications plus générales.) Le type de retour peut varier en fonction des kwargs à valeur Python. Cela permet aux drapeaux de produire des sorties supplémentaires. Le créateur SavedModel définit les dtypes et les formes de sortie et leur dépendance aux entrées.
Appelables nommés
Un SavedModel réutilisable peut fournir plusieurs pièces de modèle de la manière décrite ci-dessus en les plaçant dans des sous-objets nommés, par exemple, obj.foo
, obj.bar
et ainsi de suite. Chaque sous-objet fournit une méthode __call__
et des attributs de support sur les variables, etc. spécifiques à cette pièce de modèle. Pour l'exemple ci-dessus, il y aurait obj.foo.__call__
, obj.foo.variables
et ainsi de suite.
Notez que cette interface ne couvre pas l'approche consistant à ajouter une fonction nue tf.function directement en tant que tf.foo
.
Les utilisateurs de Reusable SavedModels ne sont censés gérer qu'un seul niveau d'imbrication ( obj.bar
mais pas obj.bar.baz
). (Les révisions futures de cette interface peuvent permettre une imbrication plus profonde et peuvent supprimer l'exigence que l'objet de niveau supérieur soit lui-même appelable.)
Remarques de clôture
Relation avec les API en cours de processus
Ce document décrit une interface d'une classe Python composée de primitives telles que tf.function et tf.Variable qui survivent à un aller-retour via la sérialisation via tf.saved_model.save()
et tf.saved_model.load()
. Cependant, l'interface était déjà présente sur l'objet d'origine qui a été passé à tf.saved_model.save()
. L'adaptation à cette interface permet l'échange d'éléments de modèle entre les API de création de modèles au sein d'un seul programme TensorFlow.