Ce document est destiné aux utilisateurs qui ont besoin d'une compatibilité descendante entre différentes versions de TensorFlow (pour le code ou les données) et aux développeurs qui souhaitent modifier TensorFlow tout en préservant la compatibilité.
Versionnement sémantique 2.0
TensorFlow suit Semantic Versioning 2.0 ( semver ) pour son API publique. Chaque version de TensorFlow se présente sous la forme MAJOR.MINOR.PATCH
. Par exemple, TensorFlow version 1.2.3 a la version MAJOR
1, la version MINOR
2 et la version PATCH
3. Les modifications apportées à chaque numéro ont la signification suivante :
MAJEUR : Modifications potentiellement rétrocompatibles. Le code et les données qui fonctionnaient avec une version majeure précédente ne fonctionneront pas nécessairement avec la nouvelle version. Cependant, dans certains cas, les graphiques et points de contrôle TensorFlow existants peuvent être migrés vers la version la plus récente ; voir Compatibilité des graphiques et des points de contrôle pour plus de détails sur la compatibilité des données.
MINEUR : fonctionnalités rétrocompatibles, améliorations de la vitesse, etc. Le code et les données qui fonctionnaient avec une version mineure précédente et qui ne dépendent que de l'API publique non expérimentale continueront de fonctionner sans changement. Pour plus de détails sur ce qui est et n'est pas l'API publique, voir Ce qui est couvert .
PATCH : corrections de bogues rétrocompatibles.
Par exemple, la version 1.0.0 a introduit des modifications incompatibles avec la version 0.12.1. Cependant, la version 1.1.1 était rétrocompatible avec la version 1.0.0.
Ce qui est couvert
Seules les API publiques de TensorFlow sont rétrocompatibles entre les versions mineures et les correctifs. Les API publiques consistent en
Toutes les fonctions et classes Python documentées dans le module
tensorflow
et ses sous-modules, à l'exception de- Symboles privés : toute fonction, classe, etc., dont le nom commence par
_
- Symboles expérimentaux et
tf.contrib
, voir ci- dessous pour plus de détails.
Notez que le code dans les répertoires
examples/
ettools/
n'est pas accessible via le module Pythontensorflow
et n'est donc pas couvert par la garantie de compatibilité.Si un symbole est disponible via le module Python
tensorflow
ou ses sous-modules, mais n'est pas documenté, il n'est pas considéré comme faisant partie de l'API publique.- Symboles privés : toute fonction, classe, etc., dont le nom commence par
L'API de compatibilité (en Python, le module
tf.compat
). Dans les versions majeures, nous pouvons publier des utilitaires et des points de terminaison supplémentaires pour aider les utilisateurs lors de la transition vers une nouvelle version majeure. Ces symboles d'API sont obsolètes et ne sont pas pris en charge (c'est-à-dire que nous n'ajouterons aucune fonctionnalité et que nous ne corrigerons les bogues que pour corriger les vulnérabilités), mais ils relèvent de nos garanties de compatibilité.L' API C.
Les fichiers tampons de protocole suivants :
Ce qui n'est pas couvert
Certaines parties de TensorFlow peuvent changer de manière rétrocompatible à tout moment. Ceux-ci inclus:
API expérimentales : Pour faciliter le développement, nous exemptons certains symboles d'API clairement marqués comme expérimentaux des garanties de compatibilité. En particulier, ne sont couverts par aucune garantie de compatibilité :
- tout symbole dans le module
tf.contrib
ou ses sous-modules ; - tout symbole (module, fonction, argument, propriété, classe ou constante) dont le nom contient
experimental
ouExperimental
; ou alors - tout symbole dont le nom pleinement qualifié inclut un module ou une classe qui est lui-même expérimental. Cela inclut les champs et les sous-messages de tout tampon de protocole appelé
experimental
.
- tout symbole dans le module
Autres langages : API TensorFlow dans des langages autres que Python et C, tels que :
- C++ (exposé via les fichiers d'en-tête dans
tensorflow/cc
). - Java ,
- Va
- Javascript
- C++ (exposé via les fichiers d'en-tête dans
Détails des opérations composites : de nombreuses fonctions publiques en Python s'étendent à plusieurs opérations primitives dans le graphique, et ces détails feront partie de tous les graphiques enregistrés sur le disque en tant que
GraphDef
s. Ces détails peuvent changer pour les versions mineures. En particulier, les tests de régression qui vérifient la correspondance exacte entre les graphiques sont susceptibles de casser les versions mineures, même si le comportement du graphique doit rester inchangé et que les points de contrôle existants fonctionneront toujours.Détails numériques en virgule flottante : les valeurs spécifiques en virgule flottante calculées par ops peuvent changer à tout moment. Les utilisateurs doivent se fier uniquement à la précision approximative et à la stabilité numérique, et non aux bits spécifiques calculés. Les modifications apportées aux formules numériques dans les versions mineures et correctives devraient entraîner une précision comparable ou améliorée, avec la mise en garde que dans l'apprentissage automatique, l'amélioration de la précision de formules spécifiques peut entraîner une diminution de la précision pour l'ensemble du système.
Nombres aléatoires : les nombres aléatoires spécifiques calculés peuvent changer à tout moment. Les utilisateurs doivent se fier uniquement aux distributions et à la force statistique approximativement correctes, et non aux bits spécifiques calculés. Voir le guide de génération de nombres aléatoires pour plus de détails.
Biais de version dans Tensorflow distribué : l' exécution de deux versions différentes de TensorFlow dans un seul cluster n'est pas prise en charge. Il n'y a aucune garantie quant à la rétrocompatibilité du protocole filaire.
Bogues : nous nous réservons le droit d'apporter des modifications de comportement rétrocompatibles (mais pas d'API) si l'implémentation actuelle est clairement cassée, c'est-à-dire si elle contredit la documentation ou si un comportement prévu bien connu et bien défini n'est pas correctement implémenté en raison à un bogue. Par exemple, si un optimiseur prétend implémenter un algorithme d'optimisation bien connu mais ne correspond pas à cet algorithme en raison d'un bogue, nous corrigerons l'optimiseur. Notre correctif peut casser le code en s'appuyant sur le mauvais comportement pour la convergence. Nous noterons ces changements dans les notes de version.
API inutilisée : nous nous réservons le droit d'apporter des modifications rétrocompatibles aux API pour lesquelles nous ne trouvons aucune utilisation documentée (en effectuant un audit de l'utilisation de TensorFlow via la recherche GitHub). Avant d'apporter de tels changements, nous annoncerons notre intention d'apporter le changement sur la liste de diffusion annonce@ , en fournissant des instructions sur la façon de traiter toute casse (le cas échéant), et attendrons deux semaines pour donner à notre communauté une chance de partager leurs commentaires .
Comportement d'erreur : nous pouvons remplacer les erreurs par un comportement sans erreur. Par exemple, nous pouvons modifier une fonction pour calculer un résultat au lieu de générer une erreur, même si cette erreur est documentée. Nous nous réservons également le droit de modifier le texte des messages d'erreur. De plus, le type d'une erreur peut changer à moins que le type d'exception pour une condition d'erreur spécifique ne soit spécifié dans la documentation.
Compatibilité des SavedModels, des graphiques et des points de contrôle
SavedModel est le format de sérialisation préféré à utiliser dans les programmes TensorFlow. Les SavedModels contiennent deux parties : un ou plusieurs graphiques encodés en tant que GraphDefs
et un point de contrôle. Les graphiques décrivent le flux de données des opérations à exécuter et les points de contrôle contiennent les valeurs de tenseur enregistrées des variables dans un graphique.
De nombreux utilisateurs de TensorFlow créent des SavedModels, puis les chargent et les exécutent avec une version ultérieure de TensorFlow. Conformément à semver , les SavedModels écrits avec une version de TensorFlow peuvent être chargés et évalués avec une version ultérieure de TensorFlow avec la même version majeure.
Nous offrons des garanties supplémentaires pour les SavedModels pris en charge. Nous appelons un SavedModel qui a été créé en utilisant uniquement des API non obsolètes, non expérimentales et non compatibles dans la version majeure N
de TensorFlow un SavedModel pris en charge dans la version N
. Tout SavedModel pris en charge dans TensorFlow version majeure N
peut être chargé et exécuté avec TensorFlow version majeure N+1
. Cependant, la fonctionnalité requise pour construire ou modifier un tel modèle peut ne plus être disponible, donc cette garantie ne s'applique qu'au SavedModel non modifié.
Nous nous efforcerons de préserver la rétrocompatibilité le plus longtemps possible, afin que les fichiers sérialisés soient utilisables sur de longues périodes.
Compatibilité GraphDef
Les graphiques sont sérialisés via le tampon de protocole GraphDef
. Pour faciliter les modifications rétrocompatibles des graphiques, chaque GraphDef
a un numéro de version distinct de la version de TensorFlow. Par exemple, la version 17 de GraphDef
a rendu obsolète l'op inv
en faveur de reciprocal
. La sémantique est :
Chaque version de TensorFlow prend en charge un intervalle de versions de
GraphDef
. Cet intervalle sera constant d'une version de correctif à l'autre et n'augmentera que pour les versions mineures. La suppression de la prise en charge d'une version deGraphDef
ne se produira que pour une version majeure de TensorFlow (et uniquement alignée sur la prise en charge de la version garantie pour SavedModels).Les graphiques nouvellement créés se voient attribuer le dernier numéro de version
GraphDef
.Si une version donnée de TensorFlow prend en charge la version
GraphDef
d'un graphique, elle se chargera et évaluera avec le même comportement que la version TensorFlow utilisée pour le générer (à l'exception des détails numériques à virgule flottante et des nombres aléatoires comme indiqué ci-dessus), quel que soit le principal version de TensorFlow. En particulier, un GraphDef qui est compatible avec un fichier de point de contrôle dans une version de TensorFlow (comme c'est le cas dans un SavedModel) restera compatible avec ce point de contrôle dans les versions suivantes, tant que le GraphDef est pris en charge.Notez que cela s'applique uniquement aux graphiques sérialisés dans GraphDefs (et SavedModels) : le code qui lit un point de contrôle peut ne pas être en mesure de lire les points de contrôle générés par le même code exécutant une version différente de TensorFlow.
Si la limite supérieure de
GraphDef
est augmentée à X dans une version (mineure), il y aura au moins six mois avant que la limite inférieure ne soit augmentée à X. Par exemple (nous utilisons ici des numéros de version hypothétiques) :- TensorFlow 1.2 peut prendre en charge les versions 4 à 7 de
GraphDef
. - TensorFlow 1.3 pourrait ajouter
GraphDef
version 8 et prendre en charge les versions 4 à 8. - Au moins six mois plus tard, TensorFlow 2.0.0 pourrait abandonner la prise en charge des versions 4 à 7, ne laissant que la version 8.
Notez que, comme les versions majeures de TensorFlow sont généralement publiées à plus de 6 mois d'intervalle, les garanties pour les SavedModels pris en charge détaillées ci-dessus sont beaucoup plus solides que la garantie de 6 mois pour GraphDefs.
- TensorFlow 1.2 peut prendre en charge les versions 4 à 7 de
Enfin, lorsque la prise en charge d'une version de GraphDef
sera abandonnée, nous essaierons de fournir des outils pour convertir automatiquement les graphiques vers une nouvelle version GraphDef
prise en charge.
Compatibilité des graphiques et des points de contrôle lors de l'extension de TensorFlow
Cette section n'est pertinente que lorsque vous apportez des modifications incompatibles au format GraphDef
, comme lors de l'ajout d'opérations, de la suppression d'opérations ou de la modification de la fonctionnalité d'opérations existantes. La section précédente devrait suffire à la plupart des utilisateurs.
Compatibilité descendante et partielle
Notre schéma de gestion des versions a trois exigences :
- Rétrocompatibilité pour prendre en charge le chargement des graphiques et des points de contrôle créés avec les anciennes versions de TensorFlow.
- Compatibilité ascendante pour prendre en charge les scénarios dans lesquels le producteur d'un graphique ou d'un point de contrôle est mis à niveau vers une version plus récente de TensorFlow avant le consommateur.
- Activez l'évolution de TensorFlow de manière incompatible. Par exemple, supprimer des ops, ajouter des attributs et supprimer des attributs.
Notez que bien que le mécanisme de version de GraphDef
soit distinct de la version de TensorFlow, les modifications rétrocompatibles du format GraphDef
sont toujours limitées par la gestion sémantique des versions. Cela signifie que les fonctionnalités ne peuvent être supprimées ou modifiées qu'entre les versions MAJOR
de TensorFlow (telles que 1.7
à 2.0
). De plus, la compatibilité ascendante est appliquée dans les versions de correctif ( 1.x.1
à 1.x.2
par exemple).
Pour assurer la compatibilité ascendante et descendante et savoir quand appliquer les changements de format, les graphiques et les points de contrôle ont des métadonnées qui décrivent quand ils ont été produits. Les sections ci-dessous détaillent la mise en œuvre de TensorFlow et les directives pour l'évolution des versions de GraphDef
.
Schémas de version de données indépendants
Il existe différentes versions de données pour les graphiques et les points de contrôle. Les deux formats de données évoluent à des rythmes différents l'un de l'autre et également à des rythmes différents de TensorFlow. Les deux systèmes de version sont définis dans core/public/version.h
. Chaque fois qu'une nouvelle version est ajoutée, une note est ajoutée à l'en-tête détaillant ce qui a changé et la date.
Données, producteurs et consommateurs
Nous distinguons les types d'informations de version de données suivants :
- producteurs : binaires qui produisent des données. Les producteurs ont une version (
producer
) et une version consommateur minimale avec lesquelles ils sont compatibles (min_consumer
). - consommateurs : binaires qui consomment des données. Les consommateurs ont une version (
consumer
) et une version minimale du producteur avec lesquelles ils sont compatibles (min_producer
).
Chaque élément de données versionnées a un champ de VersionDef versions
qui enregistre le producer
qui a créé les données, le min_consumer
lequel elles sont compatibles et une liste des versions bad_consumers
qui sont interdites.
Par défaut, lorsqu'un producteur crée des données, les données héritent des versions producer
et min_consumer
du producteur. bad_consumers
peut être défini si des versions grand public spécifiques sont connues pour contenir des bogues et doivent être évitées. Un consommateur peut accepter une donnée si les éléments suivants sont tous vrais :
-
consumer
>=min_consumer
des données -
producer
de données >= producteurmin_producer
du consommateur -
consumer
pas dans les donnéesbad_consumers
Étant donné que les producteurs et les consommateurs proviennent de la même base de code TensorFlow, core/public/version.h
contient une version de données principale qui est traitée comme producer
ou consumer
selon le contexte et à la fois min_consumer
et min_producer
(nécessaires respectivement aux producteurs et aux consommateurs) . Spécifiquement,
- Pour les versions de
GraphDef
, nous avonsTF_GRAPH_DEF_VERSION
,TF_GRAPH_DEF_VERSION_MIN_CONSUMER
etTF_GRAPH_DEF_VERSION_MIN_PRODUCER
. - Pour les versions de point de contrôle, nous avons
TF_CHECKPOINT_VERSION
,TF_CHECKPOINT_VERSION_MIN_CONSUMER
etTF_CHECKPOINT_VERSION_MIN_PRODUCER
.
Ajouter un nouvel attribut par défaut à une opération existante
Suivre les conseils ci-dessous vous donne une compatibilité ascendante uniquement si l'ensemble d'opérations n'a pas changé :
- Si la compatibilité ascendante est souhaitée, définissez
strip_default_attrs
surTrue
lors de l'exportation du modèle à l'aide des méthodestf.saved_model.SavedModelBuilder.add_meta_graph_and_variables
ettf.saved_model.SavedModelBuilder.add_meta_graph
de la classeSavedModelBuilder
outf.estimator.Estimator.export_saved_model
- Cela supprime les attributs de valeur par défaut au moment de la production/exportation des modèles. Cela garantit que le
tf.MetaGraphDef
exporté ne contient pas le nouvel attribut op lorsque la valeur par défaut est utilisée. - Le fait de disposer de ce contrôle pourrait permettre aux consommateurs obsolètes (par exemple, la diffusion de fichiers binaires en retard sur les fichiers binaires d'entraînement) de continuer à charger les modèles et d'éviter les interruptions dans la diffusion de modèles.
Évolution des versions de GraphDef
Cette section explique comment utiliser ce mécanisme de gestion des versions pour apporter différents types de modifications au format GraphDef
.
Ajouter une opération
Ajoutez la nouvelle opération aux consommateurs et aux producteurs en même temps, et ne modifiez aucune version de GraphDef
. Ce type de modification est automatiquement rétrocompatible et n'a pas d'incidence sur le plan de compatibilité ascendante puisque les scripts de producteurs existants n'utiliseront pas soudainement la nouvelle fonctionnalité.
Ajouter une opération et basculer les wrappers Python existants pour l'utiliser
- Implémentez de nouvelles fonctionnalités grand public et incrémentez la version de
GraphDef
. - S'il est possible de faire en sorte que les wrappers utilisent la nouvelle fonctionnalité uniquement dans les cas qui ne fonctionnaient pas auparavant, les wrappers peuvent être mis à jour maintenant.
- Modifiez les wrappers Python pour utiliser la nouvelle fonctionnalité. N'incrémentez pas
min_consumer
, car les modèles qui n'utilisent pas cette opération ne doivent pas se casser.
Supprimer ou restreindre la fonctionnalité d'une opération
- Corrigez tous les scripts de producteur (pas TensorFlow lui-même) pour ne pas utiliser l'opération ou la fonctionnalité interdite.
- Incrémentez la version de
GraphDef
et implémentez une nouvelle fonctionnalité grand public qui interdit l'op ou la fonctionnalité supprimée pour GraphDefs dans la nouvelle version et au-dessus. Si possible, faites en sorte que TensorFlow arrête de produire desGraphDefs
avec la fonctionnalité interdite. Pour ce faire, ajoutez leREGISTER_OP(...).Deprecated(deprecated_at_version, message)
. - Attendez une version majeure à des fins de rétrocompatibilité.
- Augmentez
min_producer
à la version GraphDef de (2) et supprimez entièrement la fonctionnalité.
Modifier la fonctionnalité d'une opération
- Ajoutez une nouvelle opération similaire nommée
SomethingV2
ou similaire et passez par le processus d'ajout et de changement des wrappers Python existants pour l'utiliser. Pour assurer la compatibilité ascendante, utilisez les vérifications suggérées dans compat.py lors de la modification des wrappers Python. - Supprimez l'ancien op (ne peut avoir lieu qu'avec un changement de version majeur en raison de la rétrocompatibilité).
- Augmentez
min_consumer
pour exclure les consommateurs avec l'ancien op, rajoutez l'ancien op en tant qu'alias pourSomethingV2
et suivez le processus pour changer les wrappers Python existants pour l'utiliser. - Suivez le processus pour supprimer
SomethingV2
.
Interdire une seule version grand public non sécurisée
- Augmentez la version de
GraphDef
et ajoutez la mauvaise version àbad_consumers
pour tous les nouveaux GraphDefs. Si possible, ajoutez àbad_consumers
uniquement pour les GraphDefs qui contiennent un certain op ou similaire. - Si les consommateurs existants ont la mauvaise version, sortez-les dès que possible.