Prétraiter les données avec TensorFlow Transform

Le composant d'ingénierie de fonctionnalités de TensorFlow Extended (TFX)

Cet exemple de bloc-notes Colab fournit un exemple très simple de la façon dont TensorFlow Transform ( tf.Transform ) peut être utilisé pour prétraiter des données en utilisant exactement le même code pour former un modèle et servir des inférences en production.

TensorFlow Transform est une bibliothèque de prétraitement des données d'entrée pour TensorFlow, y compris la création de fonctionnalités qui nécessitent un passage complet sur l'ensemble de données d'entraînement. Par exemple, en utilisant TensorFlow Transform, vous pouvez :

  • Normaliser une valeur d'entrée en utilisant la moyenne et l'écart type
  • Convertir des chaînes en nombres entiers en générant un vocabulaire sur toutes les valeurs d'entrée
  • Convertissez des flottants en nombres entiers en les attribuant à des compartiments, en fonction de la distribution des données observées

TensorFlow a une prise en charge intégrée des manipulations sur un seul exemple ou un lot d'exemples. tf.Transform étend ces fonctionnalités pour prendre en charge des passes complètes sur l'ensemble du jeu de données d'entraînement.

La sortie de tf.Transform est exportée sous la forme d'un graphique TensorFlow que vous pouvez utiliser à la fois pour l'entraînement et la diffusion. L'utilisation du même graphique pour l'entraînement et le service peut éviter le biais, car les mêmes transformations sont appliquées aux deux étapes.

Mettre à jour le pip

Pour éviter la mise à niveau de Pip dans un système lors d'une exécution locale, vérifiez que nous exécutons Colab. Les systèmes locaux peuvent bien sûr être mis à niveau séparément.

try:
  import colab
  !pip install --upgrade pip
except:
  pass

Installer la transformation TensorFlow

pip install -q -U tensorflow_transform

As-tu redémarré le runtime ?

Si vous utilisez Google Colab, la première fois que vous exécutez la cellule ci-dessus, vous devez redémarrer le runtime (Runtime > Redémarrer le runtime...). Cela est dû à la façon dont Colab charge les packages.

Importations

import pprint
import tempfile

import tensorflow as tf
import tensorflow_transform as tft

import tensorflow_transform.beam as tft_beam
from tensorflow_transform.tf_metadata import dataset_metadata
from tensorflow_transform.tf_metadata import schema_utils

Données : créer des données factices

Nous allons créer quelques données factices simples pour notre exemple simple :

  • raw_data est les données brutes initiales que nous allons prétraiter
  • raw_data_metadata contient le schéma qui nous indique les types de chacune des colonnes de raw_data . Dans ce cas, c'est très simple.
raw_data = [
      {'x': 1, 'y': 1, 's': 'hello'},
      {'x': 2, 'y': 2, 's': 'world'},
      {'x': 3, 'y': 3, 's': 'hello'}
  ]

raw_data_metadata = dataset_metadata.DatasetMetadata(
    schema_utils.schema_from_feature_spec({
        'y': tf.io.FixedLenFeature([], tf.float32),
        'x': tf.io.FixedLenFeature([], tf.float32),
        's': tf.io.FixedLenFeature([], tf.string),
    }))

Transform : créer une fonction de prétraitement

La fonction de prétraitement est le concept le plus important de tf.Transform. Une fonction de prétraitement est l'endroit où la transformation de l'ensemble de données se produit réellement. Il accepte et renvoie un dictionnaire de tenseurs, où un tenseur signifie un Tensor ou unSparseTensor . Il existe deux principaux groupes d'appels d'API qui forment généralement le cœur d'une fonction de prétraitement :

  1. TensorFlow Ops : toute fonction qui accepte et renvoie des tenseurs, ce qui signifie généralement des opérations TensorFlow. Ceux-ci ajoutent des opérations TensorFlow au graphique qui transforme les données brutes en données transformées, un vecteur de caractéristiques à la fois. Ceux-ci seront exécutés pour chaque exemple, pendant l'entraînement et le service.
  2. Tensorflow Transform Analyzers/Mappers : tous les analyseurs/mappers fournis par tf.Transform. Ceux-ci acceptent et renvoient également des tenseurs, et contiennent généralement une combinaison d'opérations Tensorflow et de calcul Beam, mais contrairement aux opérations TensorFlow, ils ne s'exécutent que dans le pipeline Beam pendant l'analyse nécessitant un passage complet sur l'ensemble de données d'entraînement. Le calcul Beam ne s'exécute qu'une seule fois, pendant l'entraînement, et effectue généralement un passage complet sur l'ensemble de données d'entraînement. Ils créent des constantes tensorielles, qui sont ajoutées à votre graphique. Par exemple, tft.min calcule le minimum d'un tenseur sur l'ensemble de données d'apprentissage tandis que tft.scale_by_min_max calcule d'abord le minimum et le maximum d'un tenseur sur l'ensemble de données d'apprentissage, puis redimensionne le tenseur pour qu'il se situe dans une plage spécifiée par l'utilisateur, [output_min, sortie_max]. tf.Transform fournit un ensemble fixe de tels analyseurs/mappeurs, mais cela sera étendu dans les futures versions.
def preprocessing_fn(inputs):
    """Preprocess input columns into transformed columns."""
    x = inputs['x']
    y = inputs['y']
    s = inputs['s']
    x_centered = x - tft.mean(x)
    y_normalized = tft.scale_to_0_1(y)
    s_integerized = tft.compute_and_apply_vocabulary(s)
    x_centered_times_y_normalized = (x_centered * y_normalized)
    return {
        'x_centered': x_centered,
        'y_normalized': y_normalized,
        's_integerized': s_integerized,
        'x_centered_times_y_normalized': x_centered_times_y_normalized,
    }

Mettre tous ensemble

Nous sommes maintenant prêts à transformer nos données. Nous allons utiliser Apache Beam avec un exécuteur direct et fournir trois entrées :

  1. raw_data - Les données d'entrée brutes que nous avons créées ci-dessus
  2. raw_data_metadata - Le schéma des données brutes
  3. preprocessing_fn - La fonction que nous avons créée pour effectuer notre transformation
def main():
  # Ignore the warnings
  with tft_beam.Context(temp_dir=tempfile.mkdtemp()):
    transformed_dataset, transform_fn = (  # pylint: disable=unused-variable
        (raw_data, raw_data_metadata) | tft_beam.AnalyzeAndTransformDataset(
            preprocessing_fn))

  transformed_data, transformed_metadata = transformed_dataset  # pylint: disable=unused-variable

  print('\nRaw data:\n{}\n'.format(pprint.pformat(raw_data)))
  print('Transformed data:\n{}'.format(pprint.pformat(transformed_data)))

if __name__ == '__main__':
  main()
WARNING:apache_beam.runners.interactive.interactive_environment:Dependencies required for Interactive Beam PCollection visualization are not available, please use: `pip install apache-beam[interactive]` to install necessary dependencies to enable all data visualization features.
WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch).
WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch).
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_transform/tf_utils.py:289: Tensor.experimental_ref (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use ref() instead.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_transform/tf_utils.py:289: Tensor.experimental_ref (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use ref() instead.
WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch).
WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch).
WARNING:apache_beam.options.pipeline_options:Discarding unparseable args: ['/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py', '-f', '/tmp/tmp8aif_7w8.json', '--HistoryManager.hist_file=:memory:']
WARNING:root:Make sure that locally built Python SDK docker image has Python 3.7 interpreter.
INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/319450c9d7da4ab08741bc79e129ac38/assets
2022-02-03 10:18:41.378629: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/319450c9d7da4ab08741bc79e129ac38/assets
INFO:tensorflow:tensorflow_text is not available.
INFO:tensorflow:tensorflow_text is not available.
INFO:tensorflow:tensorflow_decision_forests is not available.
INFO:tensorflow:tensorflow_decision_forests is not available.
INFO:tensorflow:struct2tensor is not available.
INFO:tensorflow:struct2tensor is not available.
INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/1f79865adbdd4ede9a3768fcac29949c/assets
INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/1f79865adbdd4ede9a3768fcac29949c/assets
INFO:tensorflow:tensorflow_text is not available.
INFO:tensorflow:tensorflow_text is not available.
INFO:tensorflow:tensorflow_decision_forests is not available.
INFO:tensorflow:tensorflow_decision_forests is not available.
INFO:tensorflow:struct2tensor is not available.
INFO:tensorflow:struct2tensor is not available.
Raw data:
[{'s': 'hello', 'x': 1, 'y': 1},
 {'s': 'world', 'x': 2, 'y': 2},
 {'s': 'hello', 'x': 3, 'y': 3}]

Transformed data:
[{'s_integerized': 0,
  'x_centered': -1.0,
  'x_centered_times_y_normalized': -0.0,
  'y_normalized': 0.0},
 {'s_integerized': 1,
  'x_centered': 0.0,
  'x_centered_times_y_normalized': 0.0,
  'y_normalized': 0.5},
 {'s_integerized': 0,
  'x_centered': 1.0,
  'x_centered_times_y_normalized': 1.0,
  'y_normalized': 1.0}]

Est-ce la bonne réponse ?

Auparavant, nous tf.Transform pour faire ceci :

x_centered = x - tft.mean(x)
y_normalized = tft.scale_to_0_1(y)
s_integerized = tft.compute_and_apply_vocabulary(s)
x_centered_times_y_normalized = (x_centered * y_normalized)

x_centered

Avec l'entrée de [1, 2, 3] la moyenne de x est 2, et nous la soustrayons de x pour centrer nos valeurs de x sur 0. Donc, notre résultat de [-1.0, 0.0, 1.0] est correct.

y_normalisé

Nous voulions mettre à l'échelle nos valeurs y entre 0 et 1. Notre entrée était [1, 2, 3] donc notre résultat de [0.0, 0.5, 1.0] est correct.

s_entierisé

Nous voulions mapper nos chaînes sur des index dans un vocabulaire, et il n'y avait que 2 mots dans notre vocabulaire ("bonjour" et "monde"). Donc, avec l'entrée de ["hello", "world", "hello"] notre résultat de [0, 1, 0] est correct. Étant donné que "bonjour" apparaît le plus fréquemment dans ces données, ce sera la première entrée du vocabulaire.

x_centered_times_y_normalized

Nous voulions créer une nouvelle fonctionnalité en croisant x_centered et y_normalized en utilisant la multiplication. Notez que cela multiplie les résultats, pas les valeurs d'origine, et notre nouveau résultat de [-0.0, 0.0, 1.0] est correct.