Preprocesar datos con TensorFlow Transform

El componente de ingeniería de características de TensorFlow Extended (TFX)

Este cuaderno de colaboración de ejemplo proporciona un ejemplo muy simple de cómo se puede usar TensorFlow Transform ( tf.Transform ) para preprocesar datos usando exactamente el mismo código para entrenar un modelo y entregar inferencias en producción.

TensorFlow Transform es una biblioteca para preprocesar datos de entrada para TensorFlow, incluida la creación de funciones que requieren un pase completo sobre el conjunto de datos de entrenamiento. Por ejemplo, al usar TensorFlow Transform podrías:

  • Normalizar un valor de entrada usando la media y la desviación estándar
  • Convierta cadenas en enteros generando un vocabulario sobre todos los valores de entrada
  • Convierta flotantes en números enteros asignándolos a depósitos, en función de la distribución de datos observada

TensorFlow tiene soporte integrado para manipulaciones en un solo ejemplo o en un lote de ejemplos. tf.Transform amplía estas capacidades para admitir pases completos en todo el conjunto de datos de entrenamiento.

La salida de tf.Transform se exporta como un gráfico de TensorFlow que puede usar tanto para entrenar como para servir. Usar el mismo gráfico tanto para el entrenamiento como para el servicio puede evitar sesgos, ya que se aplican las mismas transformaciones en ambas etapas.

Actualizar Pip

Para evitar actualizar Pip en un sistema cuando se ejecuta localmente, verifique que se esté ejecutando en Colab. Por supuesto, los sistemas locales se pueden actualizar por separado.

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

Instalar TensorFlow Transform

pip install -q -U tensorflow_transform

¿Reiniciaste el tiempo de ejecución?

Si está utilizando Google Colab, la primera vez que ejecute la celda anterior, debe reiniciar el tiempo de ejecución (Tiempo de ejecución > Reiniciar tiempo de ejecución...). Esto se debe a la forma en que Colab carga los paquetes.

Importaciones

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

Datos: crea algunos datos ficticios

Crearemos algunos datos ficticios simples para nuestro ejemplo simple:

  • raw_data son los datos sin procesar iniciales que vamos a preprocesar
  • raw_data_metadata contiene el esquema que nos dice los tipos de cada una de las columnas en raw_data . En este caso, es muy 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),
    }))

Transformar: crear una función de preprocesamiento

La función de preprocesamiento es el concepto más importante de tf.Transform. Una función de preprocesamiento es donde realmente ocurre la transformación del conjunto de datos. Acepta y devuelve un diccionario de tensores, donde un tensor significa un Tensor oSparseTensor . Hay dos grupos principales de llamadas API que normalmente forman el corazón de una función de preprocesamiento:

  1. TensorFlow Ops: cualquier función que acepte y devuelva tensores, lo que generalmente significa TensorFlow ops. Estos agregan operaciones de TensorFlow al gráfico que transforma los datos sin procesar en datos transformados, un vector de características a la vez. Estos se ejecutarán para cada ejemplo, tanto durante el entrenamiento como durante el servicio.
  2. Tensorflow Transform Analyzers/Mappers: cualquiera de los analizadores/mapeadores proporcionados por tf.Transform. Estos también aceptan y devuelven tensores y, por lo general, contienen una combinación de operaciones de Tensorflow y cálculo de Beam, pero, a diferencia de las operaciones de TensorFlow, solo se ejecutan en la canalización de Beam durante el análisis, lo que requiere un pase completo sobre todo el conjunto de datos de entrenamiento. El cálculo de Beam se ejecuta solo una vez, durante el entrenamiento y, por lo general, realiza un pase completo sobre todo el conjunto de datos de entrenamiento. Crean constantes de tensor, que se agregan a su gráfico. Por ejemplo, tft.min calcula el mínimo de un tensor sobre el conjunto de datos de entrenamiento mientras que tft.scale_by_min_max primero calcula el mínimo y el máximo de un tensor sobre el conjunto de datos de entrenamiento y luego escala el tensor para estar dentro de un rango especificado por el usuario, [output_min, salida_máx]. tf.Transform proporciona un conjunto fijo de dichos analizadores/mapeadores, pero esto se ampliará en futuras versiones.
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,
    }

Poniendolo todo junto

Ahora estamos listos para transformar nuestros datos. Usaremos Apache Beam con un corredor directo y proporcionaremos tres entradas:

  1. raw_data : los datos de entrada sin procesar que creamos anteriormente
  2. raw_data_metadata : el esquema de los datos sin procesar
  3. preprocessing_fn - La función que creamos para hacer nuestra transformación
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}]

¿Es esta la respuesta correcta?

Anteriormente, usamos tf.Transform para hacer esto:

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)

centrado en x

Con la entrada de [1, 2, 3] la media de x es 2, y la restamos de x para centrar nuestros valores de x en 0. Entonces, nuestro resultado de [-1.0, 0.0, 1.0] es correcto.

y_normalizado

Queríamos escalar nuestros valores de y entre 0 y 1. Nuestra entrada fue [1, 2, 3] por lo que nuestro resultado de [0.0, 0.5, 1.0] es correcto.

s_integrado

Queríamos asignar nuestras cadenas a índices en un vocabulario, y solo había 2 palabras en nuestro vocabulario ("hola" y "mundo"). Entonces, con la entrada de ["hello", "world", "hello"] nuestro resultado de [0, 1, 0] es correcto. Dado que "hola" aparece con mayor frecuencia en estos datos, será la primera entrada en el vocabulario.

x_centered_times_y_normalized

Queríamos crear una nueva función cruzando x_centered y y_normalized usando la multiplicación. Tenga en cuenta que esto multiplica los resultados, no los valores originales, y nuestro nuevo resultado de [-0.0, 0.0, 1.0] es correcto.