TensorFlow 2.x dans TFX

TensorFlow 2.0 a été publié en 2019 , avec une intégration étroite de Keras , une exécution rapide par défaut et une exécution de fonctions Pythonic , entre autres nouvelles fonctionnalités et améliorations .

Ce guide fournit un aperçu technique complet de TF 2.x dans TFX.

Quelle version utiliser ?

TFX est compatible avec TensorFlow 2.x et les API de haut niveau qui existaient dans TensorFlow 1.x (en particulier les estimateurs) continuent de fonctionner.

Démarrer de nouveaux projets dans TensorFlow 2.x

Étant donné que TensorFlow 2.x conserve les fonctionnalités de haut niveau de TensorFlow 1.x, il n'y a aucun avantage à utiliser l'ancienne version sur de nouveaux projets, même si vous ne prévoyez pas d'utiliser les nouvelles fonctionnalités.

Par conséquent, si vous démarrez un nouveau projet TFX, nous vous recommandons d'utiliser TensorFlow 2.x. Vous souhaiterez peut-être mettre à jour votre code plus tard, à mesure que la prise en charge complète de Keras et d'autres nouvelles fonctionnalités sera disponible, et la portée des modifications sera beaucoup plus limitée si vous démarrez avec TensorFlow 2.x, plutôt que d'essayer de mettre à niveau depuis TensorFlow 1.x dans l'avenir.

Conversion de projets existants vers TensorFlow 2.x

Le code écrit pour TensorFlow 1.x est largement compatible avec TensorFlow 2.x et continuera à fonctionner dans TFX.

Cependant, si vous souhaitez profiter des améliorations et des nouvelles fonctionnalités dès qu'elles seront disponibles dans TF 2.x, vous pouvez suivre les instructions de migration vers TF 2.x.

Estimateur

L'API Estimator a été conservée dans TensorFlow 2.x, mais ne fait pas l'objet de nouvelles fonctionnalités ni de développement. Le code écrit dans TensorFlow 1.x ou 2.x à l'aide d'estimateurs continuera à fonctionner comme prévu dans TFX.

Voici un exemple TFX de bout en bout utilisant un Estimateur pur : Exemple de taxi (Estimateur)

Keras avec model_to_estimator

Les modèles Keras peuvent être encapsulés avec la fonction tf.keras.estimator.model_to_estimator , qui leur permet de fonctionner comme s'il s'agissait d'estimateurs. Pour utiliser ceci :

  1. Construisez un modèle Keras.
  2. Transmettez le modèle compilé dans model_to_estimator .
  3. Utilisez le résultat de model_to_estimator dans Trainer, de la même manière que vous utiliseriez généralement un Estimator.
# Build a Keras model.
def _keras_model_builder():
  """Creates a Keras model."""
  ...

  model = tf.keras.Model(inputs=inputs, outputs=output)
  model.compile()

  return model


# Write a typical trainer function
def trainer_fn(trainer_fn_args, schema):
  """Build the estimator, using model_to_estimator."""
  ...

  # Model to estimator
  estimator = tf.keras.estimator.model_to_estimator(
      keras_model=_keras_model_builder(), config=run_config)

  return {
      'estimator': estimator,
      ...
  }

Hormis le fichier du module utilisateur de Trainer, le reste du pipeline reste inchangé.

Keras natif (c'est-à-dire Keras sans model_to_estimator )

Exemples et Colab

Voici plusieurs exemples avec Keras natif :

Nous avons également un Keras Colab par composant.

Composants TFX

Les sections suivantes expliquent comment les composants TFX associés prennent en charge Keras natif.

Transformer

Transform dispose actuellement d'un support expérimental pour les modèles Keras.

Le composant Transform lui-même peut être utilisé pour les Keras natifs sans modification. La définition preprocessing_fn reste la même, en utilisant les opérations TensorFlow et tf.Transform .

La fonction de service et la fonction d'évaluation sont modifiées pour Keras natif. Les détails seront discutés dans les sections suivantes du formateur et de l’évaluateur.

Entraîneur

Pour configurer Keras natif, le GenericExecutor doit être défini pour le composant Trainer afin de remplacer l'exécuteur par défaut basé sur l'estimateur. Pour plus de détails, veuillez vérifier ici .

Fichier du module Keras avec transformation

Le fichier du module de formation doit contenir un run_fn qui sera appelé par le GenericExecutor , un run_fn Keras typique ressemblerait à ceci :

def run_fn(fn_args: TrainerFnArgs):
  """Train the model based on given args.

  Args:
    fn_args: Holds args used to train the model as name/value pairs.
  """
  tf_transform_output = tft.TFTransformOutput(fn_args.transform_output)

  # Train and eval files contains transformed examples.
  # _input_fn read dataset based on transformed schema from tft.
  train_dataset = _input_fn(fn_args.train_files, fn_args.data_accessor,
                            tf_transform_output.transformed_metadata.schema)
  eval_dataset = _input_fn(fn_args.eval_files, fn_args.data_accessor,
                           tf_transform_output.transformed_metadata.schema)

  model = _build_keras_model()

  model.fit(
      train_dataset,
      steps_per_epoch=fn_args.train_steps,
      validation_data=eval_dataset,
      validation_steps=fn_args.eval_steps)

  signatures = {
      'serving_default':
          _get_serve_tf_examples_fn(model,
                                    tf_transform_output).get_concrete_function(
                                        tf.TensorSpec(
                                            shape=[None],
                                            dtype=tf.string,
                                            name='examples')),
  }
  model.save(fn_args.serving_model_dir, save_format='tf', signatures=signatures)

Dans le run_fn ci-dessus, une signature de service est nécessaire lors de l'exportation du modèle entraîné afin que le modèle puisse prendre des exemples bruts pour la prédiction. Une fonction de service typique ressemblerait à ceci :

def _get_serve_tf_examples_fn(model, tf_transform_output):
  """Returns a function that parses a serialized tf.Example."""

  # the layer is added as an attribute to the model in order to make sure that
  # the model assets are handled correctly when exporting.
  model.tft_layer = tf_transform_output.transform_features_layer()

  @tf.function
  def serve_tf_examples_fn(serialized_tf_examples):
    """Returns the output to be used in the serving signature."""
    feature_spec = tf_transform_output.raw_feature_spec()
    feature_spec.pop(_LABEL_KEY)
    parsed_features = tf.io.parse_example(serialized_tf_examples, feature_spec)

    transformed_features = model.tft_layer(parsed_features)

    return model(transformed_features)

  return serve_tf_examples_fn

Dans la fonction de service ci-dessus, les transformations tf.Transform doivent être appliquées aux données brutes à des fins d'inférence, à l'aide de la couche tft.TransformFeaturesLayer . Le précédent _serving_input_receiver_fn qui était requis pour les estimateurs ne sera plus nécessaire avec Keras.

Fichier du module Keras sans transformation

Ceci est similaire au fichier de module présenté ci-dessus, mais sans les transformations :

def _get_serve_tf_examples_fn(model, schema):

  @tf.function
  def serve_tf_examples_fn(serialized_tf_examples):
    feature_spec = _get_raw_feature_spec(schema)
    feature_spec.pop(_LABEL_KEY)
    parsed_features = tf.io.parse_example(serialized_tf_examples, feature_spec)
    return model(parsed_features)

  return serve_tf_examples_fn


def run_fn(fn_args: TrainerFnArgs):
  schema = io_utils.parse_pbtxt_file(fn_args.schema_file, schema_pb2.Schema())

  # Train and eval files contains raw examples.
  # _input_fn reads the dataset based on raw data schema.
  train_dataset = _input_fn(fn_args.train_files, fn_args.data_accessor, schema)
  eval_dataset = _input_fn(fn_args.eval_files, fn_args.data_accessor, schema)

  model = _build_keras_model()

  model.fit(
      train_dataset,
      steps_per_epoch=fn_args.train_steps,
      validation_data=eval_dataset,
      validation_steps=fn_args.eval_steps)

  signatures = {
      'serving_default':
          _get_serve_tf_examples_fn(model, schema).get_concrete_function(
              tf.TensorSpec(shape=[None], dtype=tf.string, name='examples')),
  }
  model.save(fn_args.serving_model_dir, save_format='tf', signatures=signatures)
tf.distribute.Stratégie

À l'heure actuelle, TFX ne prend en charge que les stratégies de travail unique (par exemple, MirroredStrategy , OneDeviceStrategy ).

Pour utiliser une stratégie de distribution, créez un tf.distribute.Strategy approprié et déplacez la création et la compilation du modèle Keras dans une portée de stratégie.

Par exemple, remplacez model = _build_keras_model() ci-dessus par :

  mirrored_strategy = tf.distribute.MirroredStrategy()
  with mirrored_strategy.scope():
    model = _build_keras_model()

  # Rest of the code can be unchanged.
  model.fit(...)

Pour vérifier le périphérique (CPU/GPU) utilisé par MirroredStrategy , activez la journalisation Tensorflow au niveau des informations :

import logging
logging.getLogger("tensorflow").setLevel(logging.INFO)

et vous devriez pouvoir voir Using MirroredStrategy with devices (...) dans le journal.

Évaluateur

Dans TFMA v0.2x, ModelValidator et Evaluator ont été combinés en un seul nouveau composant Evaluator . Le nouveau composant Evaluator peut effectuer à la fois une évaluation de modèle unique et également valider le modèle actuel par rapport aux modèles précédents. Avec ce changement, le composant Pusher consomme désormais un résultat de bénédiction d'Evaluator au lieu de ModelValidator.

Le nouvel Evaluator prend en charge les modèles Keras ainsi que les modèles Estimator. Les modèles enregistrés _eval_input_receiver_fn et eval qui étaient requis auparavant ne seront plus nécessaires avec Keras, car Evaluator est désormais basé sur le même SavedModel que celui utilisé pour le service.

Voir Évaluateur pour plus d'informations .