Unisciti alla comunità SIG TFX-Addons e contribuisci a rendere TFX ancora migliore!

Inizia con TensorFlow Transform

Questa guida introduce i concetti di base di tf.Transform e come usarli. Lo farà:

  • Definisci una funzione di pre-elaborazione , una descrizione logica della pipeline che trasforma i dati grezzi nei dati utilizzati per addestrare un modello di apprendimento automatico.
  • Mostra l'implementazione di Apache Beam utilizzata per trasformare i dati convertendo la funzione di pre - elaborazione in una pipeline Beam .
  • Mostra altri esempi di utilizzo.

Definisci una funzione di preelaborazione

La funzione di pre-elaborazione è il concetto più importante di tf.Transform . La funzione di pre-elaborazione è una descrizione logica di una trasformazione del set di dati. La funzione di preelaborazione accetta e restituisce un dizionario di tensori, dove un tensore significa Tensor o SparseTensor . Esistono due tipi di funzioni utilizzate per definire la funzione di preelaborazione:

  1. Qualsiasi funzione che accetta e restituisce tensori. Questi aggiungono operazioni TensorFlow al grafico che trasformano i dati grezzi in dati trasformati.
  2. Uno qualsiasi degli analizzatori forniti da tf.Transform . Gli analizzatori accettano e restituiscono anche tensori, ma a differenza delle funzioni TensorFlow, non aggiungono operazioni al grafico. Invece, gli analizzatori tf.Transform in modo che tf.Transform calcoli un'operazione full-pass al di fuori di TensorFlow. Usano i valori del tensore di input sull'intero set di dati per generare un tensore costante che viene restituito come output. Ad esempio, tft.min calcola il minimo di un tensore sul set di dati. tf.Transform fornisce un set fisso di analizzatori, ma verrà esteso nelle versioni future.

Esempio di funzione di pre-elaborazione

Combinando analizzatori e normali funzioni TensorFlow, gli utenti possono creare pipeline flessibili per la trasformazione dei dati. La seguente funzione di pre-elaborazione trasforma ciascuna delle tre funzionalità in modi diversi e combina due delle funzionalità:

import tensorflow as tf
import tensorflow_transform as tft
import tensorflow_transform.beam as tft_beam

def preprocessing_fn(inputs):
  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,
      'x_centered_times_y_normalized': x_centered_times_y_normalized,
      's_integerized': s_integerized
  }

Qui, x , y e s sono i Tensor che rappresentano le caratteristiche di input. Il primo nuovo tensore che viene creato, x_centered , viene costruito applicando tft.mean a x e sottraendo questo da x . tft.mean(x) restituisce un tensore che rappresenta la media del tensore x . x_centered è il tensore x con la media sottratta.

Il secondo nuovo tensore, y_normalized , viene creato in modo simile ma utilizzando il metodo conveniente tft.scale_to_0_1 . Questo metodo fa qualcosa di simile al calcolo x_centered , vale a dire calcolare un massimo e un minimo e x_centered per scalare y .

Il tensore s_integerized mostra un esempio di manipolazione delle stringhe. In questo caso, prendiamo una stringa e la mappiamo a un numero intero. Questo utilizza la funzione di convenienzatft.compute_and_apply_vocabulary . Questa funzione utilizza un analizzatore per calcolare i valori univoci presi dalle stringhe di input, quindi utilizza le operazioni TensorFlow per convertire le stringhe di input in indici nella tabella dei valori univoci.

L'ultima colonna mostra che è possibile utilizzare le operazioni TensorFlow per creare nuove funzionalità combinando i tensori.

La funzione di pre-elaborazione definisce una pipeline di operazioni su un set di dati. Per applicare la pipeline, ci affidiamo a un'implementazione concreta dell'API tf.Transform . L'implementazione di Apache Beam fornisce PTransform che applica la funzione di pre-elaborazione di un utente ai dati. Il flusso di lavoro tipico di un utente tf.Transform costruirà una funzione di pre-elaborazione, quindi la incorporerà in una pipeline Beam più grande, creando i dati per l'addestramento.

Dosaggio

Il batch è una parte importante di TensorFlow. Poiché uno degli obiettivi di tf.Transform è fornire un grafico TensorFlow per la preelaborazione che può essere incorporato nel grafico di pubblicazione (e, facoltativamente, nel grafico di addestramento), anche il tf.Transform è un concetto importante in tf.Transform .

Sebbene non sia ovvio nell'esempio precedente, alla funzione di pre-elaborazione definita dall'utente vengono passati tensori che rappresentano batch e non singole istanze, come accade durante l'addestramento e l'elaborazione con TensorFlow. D'altra parte, gli analizzatori eseguono un calcolo sull'intero set di dati che restituisce un singolo valore e non un batch di valori. x è un Tensor con una forma di (batch_size,) , mentre tft.mean(x) è un Tensor con una forma di () . La sottrazione x - tft.mean(x) trasmette dove il valore di tft.mean(x) viene sottratto da ogni elemento del batch rappresentato da x .

Implementazione di Apache Beam

Sebbene la funzione di pre - elaborazione sia intesa come una descrizione logica di una pipeline di pre-elaborazione implementata su più framework di elaborazione dati, tf.Transform fornisce un'implementazione canonica utilizzata su Apache Beam. Questa implementazione dimostra la funzionalità richiesta da un'implementazione. Non esiste un'API formale per questa funzionalità, quindi ogni implementazione può utilizzare un'API idiomatica per il suo particolare framework di elaborazione dei dati.

L'implementazione di Apache Beam fornisce due PTransform utilizzati per elaborare i dati per una funzione di pre-elaborazione. Di seguito viene illustrato l'utilizzo per il PTransform AnalyzeAndTransformDataset composite PTransform AnalyzeAndTransformDataset :

raw_data = [
    {'x': 1, 'y': 1, 's': 'hello'},
    {'x': 2, 'y': 2, 's': 'world'},
    {'x': 3, 'y': 3, 's': 'hello'}
]

raw_data_metadata = ...
transformed_dataset, transform_fn = (
    (raw_data, raw_data_metadata) | tft_beam.AnalyzeAndTransformDataset(
        preprocessing_fn))
transformed_data, transformed_metadata = transformed_dataset

Il contenuto transformed_data è mostrato di seguito e contiene le colonne trasformate nello stesso formato dei dati grezzi. In particolare, i valori di s_integerized sono [0, 1, 0] valori dipendono da come le parole hello e world sono state mappate a numeri interi, il che è deterministico. Per la colonna x_centered , abbiamo sottratto la media in modo che i valori della colonna x , che erano [1.0, 2.0, 3.0] , diventassero [-1.0, 0.0, 1.0] . Allo stesso modo, il resto delle colonne corrisponde ai valori previsti.

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

Sia raw_data che transformed_data sono set di dati. Le due sezioni successive mostrano come l'implementazione di Beam rappresenti i set di dati e come leggere e scrivere i dati su disco. L'altro valore restituito, transform_fn , rappresenta la trasformazione applicata ai dati, trattata in dettaglio di seguito.

AnalyzeAndTransformDataset è la composizione delle due trasformazioni fondamentali fornite dall'implementazione AnalyzeDataset e TransformDataset . Quindi i seguenti due frammenti di codice sono equivalenti:

transformed_data, transform_fn = (
    my_data | tft_beam.AnalyzeAndTransformDataset(preprocessing_fn))
transform_fn = my_data | tft_beam.AnalyzeDataset(preprocessing_fn)
transformed_data = (my_data, transform_fn) | tft_beam.TransformDataset()

transform_fn è una funzione pura che rappresenta un'operazione che viene applicata a ogni riga del set di dati. In particolare, i valori dell'analizzatore sono già calcolati e trattati come costanti. Nell'esempio, transform_fn contiene come costanti la media della colonna x , il minimo e il massimo della colonna y e il vocabolario utilizzato per mappare le stringhe a numeri interi.

Una caratteristica importante di tf.Transform è che transform_fn rappresenta una mappa su righe: è una funzione pura applicata a ciascuna riga separatamente. Tutto il calcolo per l'aggregazione delle righe viene eseguito in AnalyzeDataset . Inoltre, transform_fn è rappresentato come un Graph TensorFlow che può essere incorporato nel grafico di servizio.

AnalyzeAndTransformDataset viene fornito per le ottimizzazioni in questo caso speciale. Questo è lo stesso modello utilizzato in scikit-learn , che fornisce i metodi fit , transform e fit_transform .

Formati di dati e schema

L'implementazione di TFT Beam accetta due diversi formati di dati di input. Il formato "instance dict" (come mostrato nell'esempio sopra e in simple_example.py ) è un formato intuitivo ed è adatto per piccoli set di dati mentre il formato TFXIO ( Apache Arrow ) fornisce prestazioni migliorate ed è adatto per grandi set di dati.

L'implementazione Beam indica in quale formato sarebbe l'input PCollection dai "metadati" che accompagnano PCollection:

(raw_data, raw_data_metadata) | tft.AnalyzeDataset(...)
  • Se raw_data_metadata è un dataset_metadata.DatasetMetadata (vedi sotto, sezione "Il formato 'instance dict'"), allora raw_data dovrebbe essere nel formato "instance dict".
  • Se raw_data_metadata è un tfxio.TensorAdapterConfig (vedi sotto, sezione "Il formato TFXIO"), allora raw_data dovrebbe essere nel formato TFXIO.

Il formato "istanza dict"

Negli esempi di codice precedenti, il codice che definisce raw_data_metadata viene omesso. I metadati contengono lo schema che definisce il layout dei dati in modo che vengano letti e scritti in vari formati. Anche il formato in memoria mostrato nell'ultima sezione non si autodefinisce e richiede lo schema per essere interpretato come tensori.

Ecco la definizione dello schema per i dati di esempio:

from tensorflow_transform.tf_metadata import dataset_metadata
from tensorflow_transform.tf_metadata import schema_utils

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

Il Schema contiene le informazioni necessarie per analizzare i dati dal suo formato su disco o in memoria, in tensori. Viene in genere costruito chiamando schema_utils.schema_from_feature_spec con una funzione di mappatura dict chiavi ai tf.io.FixedLenFeature , tf.io.VarLenFeature e tf.io.SparseFeature . Vedere la documentazione per tf.parse_example per maggiori dettagli.

Sopra usiamo tf.io.FixedLenFeature per indicare che ogni caratteristica contiene un numero fisso di valori, in questo caso un singolo valore scalare. Poiché tf.Transform batch di istanze, il Tensor effettivo che rappresenta la caratteristica avrà una forma (None,) dove la dimensione sconosciuta è la dimensione del batch.

Il formato TFXIO

Con questo formato, i dati dovrebbero essere contenuti in un pyarrow.RecordBatch . Per i dati tabulari, la nostra implementazione Apache Beam accetta Arrow RecordBatch es che consistono in colonne dei seguenti tipi:

  • pa.list_(<primitive>) , dove <primitive> è pa.int64() , pa.float32() pa.binary() o pa.large_binary() .

  • pa.large_list(<primitive>)

Il set di dati di input del giocattolo che abbiamo usato sopra, quando rappresentato come RecordBatch , ha il seguente aspetto:

raw_data = [
    pa.record_batch([
        pa.array([[1], [2], [3]], pa.list_(pa.float32())),
        pa.array([[1], [2], [3]], pa.list_(pa.float32())),
        pa.array([['hello'], ['world'], ['hello']], pa.list_(pa.binary())),
    ], ['x', 'y', 's'])
]

Simile a DatasetMetadata necessario per accompagnare il formato "instance dict", è necessario un tfxio.TensorAdapterConfig per accompagnare RecordBatch es. Consiste nello schema Arrow dei RecordBatch es e TensorRepresentations per determinare in modo univoco come le colonne in RecordBatch es possono essere interpretate come TensorFlow Tensors (incluso ma non limitato a tf.Tensor, tf.SparseTensor).

TensorRepresentations è un Dict[Text, TensorRepresentation] che stabilisce la relazione tra un Tensor accettato da preprocessing_fn e le colonne in RecordBatch es. Per esempio:

tensor_representation = {
    'x': text_format.Parse(
        """dense_tensor { column_name: "col1" shape { dim { size: 2 } } }"""
        schema_pb2.TensorRepresentation())
}

Significa che gli inputs['x'] in preprocessing_fn dovrebbero essere un tf.Tensor denso, i cui valori provengono da una colonna di nome 'col1' nell'input RecordBatch es e la sua forma (batch) dovrebbe essere [batch_size, 2] .

TensorRepresentation è un Protobuf definito in TensorFlow Metadata .

Compatibilità con TensorFlow

tf.Transform fornisce il supporto per esportare il transform_fn sopra come TF 1.x o TF 2.x SavedModel. Il comportamento predefinito prima della versione 0.30 esportava un file TF 1.x SavedModel. A partire dalla versione 0.30 , il comportamento predefinito è esportare un TF 2.x SavedModel a meno che i comportamenti di TF 2.x non siano esplicitamente disabilitati (chiamando tf.compat.v1.disable_v2_behavior() per esempio).

Se si utilizzano concetti TF 1.x come Estimators e Sessions , è possibile mantenere il comportamento precedente passando force_tf_compat_v1=True a tft_beam.Context se si utilizza tf.Transform come libreria autonoma o al componente Transform in TFX.

Quando si esporta transform_fn come TF 2.x SavedModel, ci si aspetta che preprocessing_fn sia tracciabile utilizzando tf.function . Inoltre, se si esegue la pipeline in remoto (ad esempio con DataflowRunner ), assicurarsi che preprocessing_fn ed eventuali dipendenze siano impacchettati correttamente come descritto qui .

I problemi noti con l'utilizzo di tf.Transform per esportare un TF 2.x SavedModel sono documentati qui .

Input e output con Apache Beam

Finora, abbiamo visto dati di input e output in elenchi di Python (di RecordBatch es o dizionari di istanza). Si tratta di una semplificazione che si basa sulla capacità di Apache Beam di lavorare con gli elenchi e sulla sua principale rappresentazione di dati, PCollection .

Una PCollection è una rappresentazione dei dati che fa parte di una pipeline Beam. Una pipeline Beam viene formata applicando vari PTransform , inclusi AnalyzeDataset e TransformDataset , ed eseguendo la pipeline. Una PCollection non viene creata nella memoria del binario principale, ma viene invece distribuita tra i worker (sebbene questa sezione utilizzi la modalità di esecuzione in memoria).

Pre-scatola PCollection Sources ( TFXIO )

Il formato RecordBatch nostra implementazione è un formato comune accettato da altre librerie TFX. Pertanto TFX offre comode "sorgenti" (aka TFXIO ) che leggono file di vari formati su disco e producono RecordBatch es e possono anche fornire TensorAdapterConfig , comprese TensorRepresentations inferite.

Questi TFXIO possono essere trovati nel pacchetto tfx_bsl ( tfx_bsl.public.tfxio ).

Esempio: set di dati "Reddito censimento"

L'esempio seguente richiede sia la lettura che la scrittura di dati su disco e la rappresentazione dei dati come PCollection (non un elenco), vedere: census_example.py . Di seguito mostriamo come scaricare i dati ed eseguire questo esempio. Il set di dati "Census Income" è fornito dall'UCI Machine Learning Repository . Questo set di dati contiene dati sia categoriali che numerici.

I dati sono in formato CSV, ecco le prime due righe:

39, State-gov, 77516, Bachelors, 13, Never-married, Adm-clerical, Not-in-family, White, Male, 2174, 0, 40, United-States, <=50K
50, Self-emp-not-inc, 83311, Bachelors, 13, Married-civ-spouse, Exec-managerial, Husband, White, Male, 0, 0, 13, United-States, <=50K

Le colonne del set di dati sono categoriali o numeriche. Questo set di dati descrive un problema di classificazione: la previsione dell'ultima colonna in cui l'individuo guadagna più o meno di 50.000 all'anno. Tuttavia, dal punto di vista di tf.Transform , questa etichetta è solo un'altra colonna categoriale.

Usiamo un TFXIO , BeamRecordCsvTFXIO per tradurre le linee CSV in RecordBatches . TFXIO richiede due importanti informazioni:

  • uno schema di metadati TensorFlow che contiene informazioni sul tipo e sulla forma di ciascuna colonna CSV. TensorRepresentation sono una parte facoltativa dello schema; se non forniti (come in questo esempio), verranno dedotti dalle informazioni sul tipo e sulla forma. È possibile ottenere lo schema utilizzando una funzione di supporto che forniamo per tradurre dalle specifiche di analisi TF (mostrate in questo esempio) o eseguendo TensorFlow Data Validation .

  • un elenco di nomi di colonne, nell'ordine in cui appaiono nel file CSV. Notare che quei nomi devono corrispondere ai nomi delle funzionalità nello schema.

In questo esempio permettiamo che la funzione education-num manchi. Ciò significa che è rappresentato come tf.io.VarLenFeature in feature_spec e come tf.SparseTensor in preprocessing_fn . Altre caratteristiche diventeranno tf.Tensor con lo stesso nome in preprocessing_fn .

csv_tfxio = tfxio.BeamRecordCsvTFXIO(
    physical_format='text', column_names=ordered_columns, schema=SCHEMA)

record_batches = (
    p
    | 'ReadTrainData' >> textio.ReadFromText(train_data_file)
    | ...  # fix up csv lines
    | 'ToRecordBatches' >> csv_tfxio.BeamSource())

tensor_adapter_config = csv_tfxio.TensorAdapterConfig()

Nota che abbiamo dovuto fare alcune correzioni aggiuntive dopo che le righe CSV sono state lette. Altrimenti, potremmo fare affidamento su CsvTFXIO per gestire sia la lettura dei file che la traduzione in RecordBatch es:

csv_tfxio = tfxio.CsvTFXIO(train_data_file, column_name=ordered_columns,
                           schema=SCHEMA)
record_batches = p | 'TFXIORead' >> csv_tfxio.BeamSource()
tensor_adapter_config = csv_tfxio.TensorAdapterConfig()

La pre-elaborazione è simile all'esempio precedente, ad eccezione della funzione di pre-elaborazione generata a livello di codice invece di specificare manualmente ogni colonna. Nella funzione di pre-elaborazione di seguito, NUMERICAL_COLUMNS e CATEGORICAL_COLUMNS sono elenchi che contengono i nomi delle colonne numeriche e categoriali:

def preprocessing_fn(inputs):
  """Preprocess input columns into transformed columns."""
  # Since we are modifying some features and leaving others unchanged, we
  # start by setting `outputs` to a copy of `inputs.
  outputs = inputs.copy()

  # Scale numeric columns to have range [0, 1].
  for key in NUMERIC_FEATURE_KEYS:
    outputs[key] = tft.scale_to_0_1(outputs[key])

  for key in OPTIONAL_NUMERIC_FEATURE_KEYS:
    # This is a SparseTensor because it is optional. Here we fill in a default
    # value when it is missing.
      sparse = tf.sparse.SparseTensor(outputs[key].indices, outputs[key].values,
                                      [outputs[key].dense_shape[0], 1])
      dense = tf.sparse.to_dense(sp_input=sparse, default_value=0.)
    # Reshaping from a batch of vectors of size 1 to a batch to scalars.
    dense = tf.squeeze(dense, axis=1)
    outputs[key] = tft.scale_to_0_1(dense)

  # For all categorical columns except the label column, we generate a
  # vocabulary but do not modify the feature.  This vocabulary is instead
  # used in the trainer, by means of a feature column, to convert the feature
  # from a string to an integer id.
  for key in CATEGORICAL_FEATURE_KEYS:
    tft.vocabulary(inputs[key], vocab_filename=key)

  # For the label column we provide the mapping from string to index.
  initializer = tf.lookup.KeyValueTensorInitializer(
      keys=['>50K', '<=50K'],
      values=tf.cast(tf.range(2), tf.int64),
      key_dtype=tf.string,
      value_dtype=tf.int64)
  table = tf.lookup.StaticHashTable(initializer, default_value=-1)

  outputs[LABEL_KEY] = table.lookup(outputs[LABEL_KEY])

  return outputs

Una differenza rispetto all'esempio precedente è che la colonna dell'etichetta specifica manualmente la mappatura dalla stringa a un indice. Quindi '>50' viene mappato a 0 e '<=50K' a 1 perché è utile sapere quale indice nel modello addestrato corrisponde a quale etichetta.

La variabile record_batches rappresenta una PCollection di pyarrow.RecordBatch es. Il tensor_adapter_config è dato da csv_tfxio , che è dedotto da SCHEMA (e in definitiva, in questo esempio, dalle specifiche di analisi TF).

La fase finale consiste nello scrivere i dati trasformati su disco e ha una forma simile alla lettura dei dati grezzi. Lo schema utilizzato per eseguire questa operazione fa parte dell'output di AnalyzeAndTransformDataset che deduce uno schema per i dati di output. Il codice da scrivere su disco è mostrato di seguito. Lo schema fa parte dei metadati ma utilizza i due in modo intercambiabile nell'API tf.Transform (ovvero passa i metadati a ExampleProtoCoder ). Tieni presente che questo scrive in un formato diverso. Invece di textio.WriteToText , usa il supporto integrato di Beam per il formato TFRecord e usa un codificatore per codificare i dati come protos di Example . Si tratta di un formato migliore da utilizzare per la formazione, come mostrato nella sezione successiva. transformed_eval_data_base fornisce il nome file di base per i singoli frammenti scritti.

transformed_data | "WriteTrainData" >> tfrecordio.WriteToTFRecord(
    transformed_eval_data_base,
    coder=tft.coders.ExampleProtoCoder(transformed_metadata))

Oltre ai dati di addestramento, anche transform_fn viene scritto con i metadati:

_ = (
    transform_fn
    | 'WriteTransformFn' >> tft_beam.WriteTransformFn(working_dir))
transformed_metadata | 'WriteMetadata' >> tft_beam.WriteMetadata(
    transformed_metadata_file, pipeline=p)

Esegui l'intera pipeline di Beam con p.run().wait_until_finish() . Fino a questo punto, la pipeline Beam rappresenta un calcolo differito e distribuito. Fornisce istruzioni per ciò che verrà fatto, ma le istruzioni non sono state eseguite. Questa chiamata finale esegue la pipeline specificata.

Scarica il dataset del censimento

Scarica il set di dati del censimento utilizzando i seguenti comandi della shell:

  wget https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data
  wget https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.test

Quando si esegue lo script census_example.py , passare la directory contenente questi dati come primo argomento. Lo script crea una sottodirectory temporanea per aggiungere i dati preelaborati.

Integrazione con TensorFlow Training

La sezione finale di census_example.py mostra come i dati preelaborati vengono utilizzati per addestrare un modello. Consulta la documentazione degli stimatori per i dettagli. Il primo passo è costruire un Estimator che richiede una descrizione delle colonne preelaborate. Ogni colonna numerica è descritta come real_valued_column che è un wrapper attorno a un vettore denso con una dimensione fissa ( 1 in questo esempio). Ogni colonna categoriale viene mappata da stringa a numeri interi e quindi viene passata in indicator_column . tft.TFTransformOutput viene utilizzato per trovare il percorso del file del vocabolario per ogni caratteristica categoriale.

real_valued_columns = [feature_column.real_valued_column(key)
                       for key in NUMERIC_FEATURE_KEYS]

one_hot_columns = [
    tf.feature_column.indicator_column(
        tf.feature_column.categorical_column_with_vocabulary_file(
            key=key,
            vocabulary_file=tf_transform_output.vocabulary_file_by_name(
                vocab_filename=key)))
    for key in CATEGORICAL_FEATURE_KEYS]

estimator = tf.estimator.LinearClassifier(real_valued_columns + one_hot_columns)

Il passaggio successivo consiste nel creare un builder per generare la funzione di input per l'addestramento e la valutazione. È diverso dall'addestramento utilizzato da tf.Learn poiché non è richiesta una specifica di funzionalità per analizzare i dati trasformati. Utilizzare invece i metadati per i dati trasformati per generare una specifica di funzionalità.

def _make_training_input_fn(tf_transform_output, transformed_examples,
                            batch_size):
  ...
  def input_fn():
    """Input function for training and eval."""
    dataset = tf.data.experimental.make_batched_features_dataset(
        ..., tf_transform_output.transformed_feature_spec(), ...)

    transformed_features = tf.compat.v1.data.make_one_shot_iterator(
        dataset).get_next()
    ...

  return input_fn

Il codice rimanente è lo stesso dell'utilizzo della classe Estimator . L'esempio contiene anche il codice per esportare il modello nel formato SavedModel . Il modello esportato può essere utilizzato da Tensorflow Serving o Cloud ML Engine .