Junte-se à comunidade SIG TFX-Addons e ajude a tornar o TFX ainda melhor! Junte-se ao SIG TFX-Addons

Pré-processar dados com TensorFlow Transform

O componente de engenharia de recursos do TensorFlow Extended (TFX)

Este exemplo de bloco de notas colab fornece um exemplo muito simples de como o TensorFlow Transform ( tf.Transform ) pode ser usado para pré-processar dados usando exatamente o mesmo código para treinar um modelo e servir inferências na produção.

TensorFlow Transform é uma biblioteca para pré-processamento de dados de entrada para TensorFlow, incluindo a criação de recursos que exigem uma passagem completa sobre o conjunto de dados de treinamento. Por exemplo, usando o TensorFlow Transform, você pode:

  • Normalize um valor de entrada usando a média e o desvio padrão
  • Converta strings em inteiros, gerando um vocabulário sobre todos os valores de entrada
  • Converta flutuantes em inteiros atribuindo-os a intervalos, com base na distribuição de dados observada

O TensorFlow tem suporte integrado para manipulações em um único exemplo ou lote de exemplos. tf.Transform estende esses recursos para oferecer suporte a passes completos sobre todo o conjunto de dados de treinamento.

A saída de tf.Transform é exportada como um gráfico do TensorFlow que pode ser usado para treinamento e disponibilização. Usar o mesmo gráfico para treinamento e serviço pode evitar distorções, uma vez que as mesmas transformações são aplicadas em ambos os estágios.

Atualizar Pip

Para evitar a atualização do Pip em um sistema quando executado localmente, verifique se estamos executando no Colab. É claro que os sistemas locais podem ser atualizados separadamente.

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

Instale o TensorFlow Transform

pip install -q -U tensorflow_transform==0.24.1

Você reiniciou o tempo de execução?

Se você estiver usando o Google Colab, na primeira vez que executar a célula acima, deverá reiniciar o tempo de execução (Tempo de execução> Reiniciar tempo de execução ...). Isso se deve à maneira como o Colab carrega os pacotes.

Importações

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

Dados: crie alguns dados fictícios

Criaremos alguns dados fictícios simples para nosso exemplo simples:

  • raw_data são os dados brutos iniciais que iremos pré-processar
  • raw_data_metadata contém o esquema que nos diz os tipos de cada uma das colunas em raw_data . Nesse caso, é muito simples.
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: criar uma função de pré-processamento

A função de pré-processamento é o conceito mais importante de tf.Transform. Uma função de pré-processamento é onde a transformação do conjunto de dados realmente acontece. Ele aceita e retorna um dicionário de tensores, onde um tensor significa um Tensor ouSparseTensor . Existem dois grupos principais de chamadas de API que normalmente formam o coração de uma função de pré-processamento:

  1. TensorFlow Ops: qualquer função que aceita e retorna tensores, o que geralmente significa operações do TensorFlow. Isso adiciona operações do TensorFlow ao gráfico que transforma os dados brutos em dados transformados, um vetor de recursos por vez. Eles serão executados para todos os exemplos, durante o treinamento e serviço.
  2. Analisadores / mapeadores do Tensorflow Transform: qualquer um dos analisadores / mapeadores fornecidos por tf.Transform. Eles também aceitam e retornam tensores e geralmente contêm uma combinação de operações do Tensorflow e computação do Beam, mas, ao contrário das operações do TensorFlow, eles só são executados no pipeline do Beam durante a análise que exige uma passagem completa sobre todo o conjunto de dados de treinamento. O cálculo do Beam é executado apenas uma vez, durante o treinamento, e normalmente faz uma passagem completa sobre todo o conjunto de dados de treinamento. Eles criam constantes de tensor, que são adicionadas ao seu gráfico. Por exemplo, tft.min calcula o mínimo de um tensor no conjunto de dados de treinamento, enquanto tft.scale_by_min_max primeiro calcula o mínimo e o máximo de um tensor no conjunto de dados de treinamento e, em seguida, dimensiona o tensor para estar dentro de um intervalo especificado pelo usuário, [output_min, output_max]. tf.Transform fornece um conjunto fixo de tais analisadores / mapeadores, mas isso será estendido em versões futuras.
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,
    }

Juntando tudo

Agora estamos prontos para transformar nossos dados. Usaremos o Apache Beam com um executor direto e forneceremos três entradas:

  1. raw_data - os dados de entrada brutos que criamos acima
  2. raw_data_metadata - O esquema para os dados brutos
  3. preprocessing_fn - a função que criamos para fazer nossa transformação
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:tensorflow:Tensorflow version (2.3.2) found. Note that Tensorflow Transform support for TF 2.0 is currently in beta, and features such as tf.function may not work as intended.
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:Tensorflow version (2.3.2) found. Note that Tensorflow Transform support for TF 2.0 is currently in beta, and features such as tf.function may not work as intended.
WARNING:tensorflow:Tensorflow version (2.3.2) found. Note that Tensorflow Transform support for TF 2.0 is currently in beta, and features such as tf.function may not work as intended.
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:218: 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:218: 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/python/saved_model/signature_def_utils_impl.py:201: build_tensor_info (from tensorflow.python.saved_model.utils_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This function will only be available through the v1 compatibility library as tf.compat.v1.saved_model.utils.build_tensor_info or tf.compat.v1.saved_model.build_tensor_info.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/saved_model/signature_def_utils_impl.py:201: build_tensor_info (from tensorflow.python.saved_model.utils_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This function will only be available through the v1 compatibility library as tf.compat.v1.saved_model.utils.build_tensor_info or tf.compat.v1.saved_model.build_tensor_info.
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:No assets to write.
WARNING:tensorflow:Issue encountered when serializing tft_analyzer_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
WARNING:tensorflow:Issue encountered when serializing tft_analyzer_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
WARNING:tensorflow:Issue encountered when serializing tft_mapper_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
WARNING:tensorflow:Issue encountered when serializing tft_mapper_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
INFO:tensorflow:SavedModel written to: /tmp/tmpyjqmd8zx/tftransform_tmp/a0812edd940447aeb9bd8cca86f19136/saved_model.pb
INFO:tensorflow:SavedModel written to: /tmp/tmpyjqmd8zx/tftransform_tmp/a0812edd940447aeb9bd8cca86f19136/saved_model.pb
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:No assets to write.
WARNING:tensorflow:Issue encountered when serializing tft_analyzer_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
WARNING:tensorflow:Issue encountered when serializing tft_analyzer_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
WARNING:tensorflow:Issue encountered when serializing tft_mapper_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
WARNING:tensorflow:Issue encountered when serializing tft_mapper_use.
Type is unsupported, or the types of the items don't match field type in CollectionDef. Note this is a warning and probably safe to ignore.
'Counter' object has no attribute 'name'
INFO:tensorflow:SavedModel written to: /tmp/tmpyjqmd8zx/tftransform_tmp/ec933f1f949d40dbb39bfadf8b963b3f/saved_model.pb
INFO:tensorflow:SavedModel written to: /tmp/tmpyjqmd8zx/tftransform_tmp/ec933f1f949d40dbb39bfadf8b963b3f/saved_model.pb
WARNING:tensorflow:Tensorflow version (2.3.2) found. Note that Tensorflow Transform support for TF 2.0 is currently in beta, and features such as tf.function may not work as intended.
WARNING:tensorflow:Tensorflow version (2.3.2) found. Note that Tensorflow Transform support for TF 2.0 is currently in beta, and features such as tf.function may not work as intended.
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: ['/home/kbuilder/.local/lib/python3.7/site-packages/ipykernel_launcher.py', '-f', '/tmp/tmpe_bjh6uw.json', '--HistoryManager.hist_file=:memory:']
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:Assets written to: /tmp/tmpyjqmd8zx/tftransform_tmp/2492704f81904b2e9d2b471e8e67103c/assets
INFO:tensorflow:Assets written to: /tmp/tmpyjqmd8zx/tftransform_tmp/2492704f81904b2e9d2b471e8e67103c/assets
INFO:tensorflow:SavedModel written to: /tmp/tmpyjqmd8zx/tftransform_tmp/2492704f81904b2e9d2b471e8e67103c/saved_model.pb
INFO:tensorflow:SavedModel written to: /tmp/tmpyjqmd8zx/tftransform_tmp/2492704f81904b2e9d2b471e8e67103c/saved_model.pb
WARNING:tensorflow:Expected binary or unicode string, got type_url: "type.googleapis.com/tensorflow.AssetFileDef"
value: "\n\013\n\tConst_3:0\022-vocab_compute_and_apply_vocabulary_vocabulary"
WARNING:tensorflow:Expected binary or unicode string, got type_url: "type.googleapis.com/tensorflow.AssetFileDef"
value: "\n\013\n\tConst_3:0\022-vocab_compute_and_apply_vocabulary_vocabulary"
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
WARNING:tensorflow:Expected binary or unicode string, got type_url: "type.googleapis.com/tensorflow.AssetFileDef"
value: "\n\013\n\tConst_3:0\022-vocab_compute_and_apply_vocabulary_vocabulary"
WARNING:tensorflow:Expected binary or unicode string, got type_url: "type.googleapis.com/tensorflow.AssetFileDef"
value: "\n\013\n\tConst_3:0\022-vocab_compute_and_apply_vocabulary_vocabulary"
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
INFO:tensorflow:Saver not created because there are no variables in the graph to restore
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}]

Esta é a resposta certa?

Anteriormente, tf.Transform para fazer isso:

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

Com a entrada de [1, 2, 3] a média de x é 2, e a subtraímos de x para centralizar nossos valores de x em 0. Portanto, nosso resultado de [-1.0, 0.0, 1.0] está correto.

y_normalizado

Queríamos dimensionar nossos valores de y entre 0 e 1. Nossa entrada foi [1, 2, 3] portanto, nosso resultado de [0.0, 0.5, 1.0] está correto.

s_integerized

Queríamos mapear nossas strings para índices em um vocabulário, e havia apenas 2 palavras em nosso vocabulário ("hello" e "world"). Assim, com a entrada de ["hello", "world", "hello"] nosso resultado de [0, 1, 0] está correto. Como "olá" ocorre com mais frequência nesses dados, será a primeira entrada no vocabulário.

x_centered_times_y_normalized

Queríamos criar um novo recurso cruzando x_centered e y_normalized usando multiplicação. Observe que isso multiplica os resultados, não os valores originais, e nosso novo resultado de [-0.0, 0.0, 1.0] está correto.