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

Il componente Transform TFX Pipeline

Il componente della pipeline Transform TFX esegue l'ingegneria delle funzionalità su tf.Examples emessi da un componente ExampleGen , utilizzando uno schema di dati creato da un componente SchemaGen , ed emette sia un SavedModel che statistiche sui dati pre-trasformazione e post-trasformazione. Quando viene eseguito, il SavedModel accetterà tf.Examples emesso da un componente ExampleGen ed emetterà i dati della caratteristica trasformata.

  • Consume: tf.Examples da un componente ExampleGen e uno schema di dati da un componente SchemaGen.
  • Emette: un SavedModel in un componente Trainer, statistiche di pre-trasformazione e post-trasformazione.

Configurazione di un componente di trasformazione

Una volta che il tuo preprocessing_fn è stato scritto, deve essere definito in un modulo python che viene quindi fornito al componente Transform come input. Questo modulo verrà caricato da Transform e la funzione denominata preprocessing_fn verrà trovata e utilizzata da Transform per costruire la pipeline di pre-elaborazione.

transform = Transform(
    examples=example_gen.outputs['examples'],
    schema=schema_gen.outputs['schema'],
    module_file=os.path.abspath(_taxi_transform_module_file))

Inoltre, potresti voler fornire opzioni per il calcolo statistico di pre-trasformazione o post-trasformazione basato su TFDV . Per fare ciò, definire una stats_options_updater_fn all'interno dello stesso modulo.

Transform e TensorFlow Transform

Transform fa un uso estensivo di TensorFlow Transform per eseguire l'ingegneria delle funzionalità sul tuo set di dati. TensorFlow Transform è un ottimo strumento per trasformare i dati delle feature prima che vadano al tuo modello e come parte del processo di addestramento. Le trasformazioni di funzionalità comuni includono:

  • Incorporamento : conversione di caratteristiche sparse (come gli ID interi prodotti da un vocabolario) in caratteristiche dense trovando una mappatura significativa dallo spazio ad alta dimensione allo spazio a bassa dimensione. Vedere l' unità Incorporamenti nel corso intensivo di apprendimento automatico per un'introduzione agli incorporamenti.
  • Generazione di vocabolario : conversione di stringhe o altre caratteristiche non numeriche in numeri interi creando un vocabolario che associa ogni valore univoco a un numero ID.
  • Valori di normalizzazione : trasformare le caratteristiche numeriche in modo che rientrino tutte in un intervallo simile.
  • Bucketization : conversione di feature a valore continuo in feature categoriali assegnando valori a bucket discreti.
  • Arricchimento delle funzionalità di testo : produzione di funzionalità da dati grezzi come token, n-grammi, entità, sentiment, ecc. Per arricchire il set di funzionalità.

TensorFlow Transform fornisce supporto per questi e molti altri tipi di trasformazioni:

  • Genera automaticamente un vocabolario dai tuoi dati più recenti.

  • Esegui trasformazioni arbitrarie sui tuoi dati prima di inviarli al tuo modello. TensorFlow Transform crea trasformazioni nel grafico TensorFlow per il tuo modello in modo che le stesse trasformazioni vengano eseguite al momento dell'addestramento e dell'inferenza. È possibile definire trasformazioni che fanno riferimento alle proprietà globali dei dati, come il valore massimo di una funzionalità in tutte le istanze di addestramento.

Puoi trasformare i tuoi dati come preferisci prima di eseguire TFX. Ma se lo fai all'interno di TensorFlow Transform, le trasformazioni diventano parte del grafico TensorFlow. Questo approccio aiuta a evitare il disallineamento dell'addestramento / servizio.

Le trasformazioni all'interno del codice di modellazione utilizzano FeatureColumns. Utilizzando FeatureColumns, puoi definire bucketizzazioni, integerizzazioni che utilizzano vocabolari predefiniti o qualsiasi altra trasformazione che può essere definita senza esaminare i dati.

Al contrario, TensorFlow Transform è progettato per trasformazioni che richiedono un passaggio completo sui dati per calcolare valori non noti in anticipo. Ad esempio, la generazione del vocabolario richiede un passaggio completo dei dati.

Oltre a calcolare i valori utilizzando Apache Beam, TensorFlow Transform consente agli utenti di incorporare questi valori in un grafico TensorFlow, che può quindi essere caricato nel grafico di addestramento. Ad esempio, quando si normalizzano le caratteristiche, la funzione tft.scale_to_z_score calcolerà la media e la deviazione standard di una caratteristica e anche una rappresentazione, in un grafico TensorFlow, della funzione che sottrae la media e divide per la deviazione standard. Emettendo un grafico TensorFlow, non solo statistiche, TensorFlow Transform semplifica il processo di creazione della pipeline di pre-elaborazione.

Poiché la preelaborazione è espressa come un grafico, può avvenire sul server ed è garantito che sia coerente tra l'addestramento e il servizio. Questa coerenza elimina una fonte di disallineamento di addestramento / servizio.

TensorFlow Transform consente agli utenti di specificare la pipeline di pre-elaborazione utilizzando il codice TensorFlow. Ciò significa che una pipeline viene costruita allo stesso modo di un grafico TensorFlow. Se in questo grafico fossero utilizzate solo operazioni TensorFlow, la pipeline sarebbe una mappa pura che accetta batch di input e restituisce batch di output. Una tale pipeline sarebbe equivalente a posizionare questo grafico all'interno di input_fn quando si utilizza l'API tf.Estimator . Per specificare operazioni full-pass come il calcolo dei quantili, TensorFlow Transform fornisce funzioni speciali chiamate analyzers che appaiono come operazioni TensorFlow, ma in realtà specificano un calcolo differito che verrà eseguito da Apache Beam e l'output inserito nel grafico come un costante. Mentre una normale operazione TensorFlow prenderà un singolo batch come input, eseguirà alcuni calcoli solo su quel batch ed emetterà un batch, un analyzer eseguirà una riduzione globale (implementata in Apache Beam) su tutti i batch e restituirà il risultato.

Combinando operazioni TensorFlow ordinarie e analizzatori di trasformazione TensorFlow, gli utenti possono creare pipeline complesse per preelaborare i propri dati. Ad esempio, la funzione tft.scale_to_z_score accetta un tensore di input e restituisce quel tensore normalizzato per avere media 0 e varianza 1 . Lo fa chiamando gli analizzatori mean e var sotto il cofano, che genereranno effettivamente costanti nel grafico uguali alla media e alla varianza del tensore di input. Quindi utilizzerà le operazioni TensorFlow per sottrarre la media e dividerla per la deviazione standard.

TensorFlow Transform preprocessing_fn

Il componente TFX Transform semplifica l'uso di Transform gestendo le chiamate API relative alla lettura e scrittura dei dati e scrivendo l'output SavedModel su disco. Come utente TFX, devi solo definire una singola funzione chiamata preprocessing_fn . In preprocessing_fn si definisce una serie di funzioni che manipolano il comando di input dei tensori per produrre il comando di output dei tensori. Puoi trovare funzioni di supporto come scale_to_0_1 e compute_and_apply_vocabulary l' API di trasformazione TensorFlow o utilizzare le normali funzioni TensorFlow come mostrato di seguito.

def preprocessing_fn(inputs):
  """tf.transform's callback function for preprocessing inputs.

  Args:
    inputs: map from feature keys to raw not-yet-transformed features.

  Returns:
    Map from string feature key to transformed feature operations.
  """
  outputs = {}
  for key in _DENSE_FLOAT_FEATURE_KEYS:
    # Preserve this feature as a dense float, setting nan's to the mean.
    outputs[_transformed_name(key)] = transform.scale_to_z_score(
        _fill_in_missing(inputs[key]))

  for key in _VOCAB_FEATURE_KEYS:
    # Build a vocabulary for this feature.
    outputs[_transformed_name(
        key)] = transform.compute_and_apply_vocabulary(
            _fill_in_missing(inputs[key]),
            top_k=_VOCAB_SIZE,
            num_oov_buckets=_OOV_SIZE)

  for key in _BUCKET_FEATURE_KEYS:
    outputs[_transformed_name(key)] = transform.bucketize(
        _fill_in_missing(inputs[key]), _FEATURE_BUCKET_COUNT)

  for key in _CATEGORICAL_FEATURE_KEYS:
    outputs[_transformed_name(key)] = _fill_in_missing(inputs[key])

  # Was this passenger a big tipper?
  taxi_fare = _fill_in_missing(inputs[_FARE_KEY])
  tips = _fill_in_missing(inputs[_LABEL_KEY])
  outputs[_transformed_name(_LABEL_KEY)] = tf.where(
      tf.is_nan(taxi_fare),
      tf.cast(tf.zeros_like(taxi_fare), tf.int64),
      # Test if the tip was > 20% of the fare.
      tf.cast(
          tf.greater(tips, tf.multiply(taxi_fare, tf.constant(0.2))), tf.int64))

  return outputs

Comprensione degli input per preprocessing_fn

Il preprocessing_fn descrive una serie di operazioni sui tensori (cioè, Tensor s o SparseTensor s) e quindi per scrivere correttamente il preprocessing_fn è necessario capire come i tuoi dati sono rappresentati come tensori. L'input per preprocessing_fn è determinato dallo schema. Un Schema contiene un elenco di Feature e Transform le converte in una "specifica di funzionalità" (a volte chiamata "specifica di analisi") che è un dict le cui chiavi sono nomi di funzionalità e i cui valori sono uno di FixedLenFeature o VarLenFeature (o altro opzioni non utilizzate da TensorFlow Transform).

Le regole per dedurre una specifica di funzionalità dallo Schema sono

  • Ogni feature con shape impostata risulterà in una tf.FixedLenFeature con forma e tf.FixedLenFeature default_value=None . presence.min_fraction deve essere 1 altrimenti si verificherà un errore, poiché quando non c'è un valore predefinito, un tf.FixedLenFeature richiede che la funzione sia sempre presente.
  • Ogni feature con shape non impostata risulterà in una VarLenFeature .
  • Ogni sparse_feature risulterà in un tf.SparseFeature cui size e is_sorted sono determinate dai campi fixed_shape e is_sorted del messaggio SparseFeature .
  • Le funzionalità utilizzate come index_feature o value_feature di una sparse_feature non avranno la propria voce generata nella specifica della funzionalità.
  • La corrispondenza tra il campo del type della feature (o la caratteristica dei valori di un sparse_feature ) e il dtype di caratteristica della specifica della caratteristica è data dalla seguente tabella:
type dtype
schema_pb2.INT tf.int64
schema_pb2.FLOAT tf.float32
schema_pb2.BYTES tf.string

Utilizzo di TensorFlow Transform per gestire le etichette delle stringhe

Di solito si desidera utilizzare TensorFlow Transform sia per generare un vocabolario sia per applicare quel vocabolario per convertire le stringhe in numeri interi. Quando si segue questo flusso di lavoro, input_fn costruito nel modello restituirà la stringa integerizzata. Tuttavia le etichette sono un'eccezione, perché affinché il modello sia in grado di mappare le etichette di output (intero) alle stringhe, il modello ha bisogno che input_fn un'etichetta di stringa, insieme a un elenco di possibili valori dell'etichetta. Ad esempio, se le etichette sono cat e dog l'output di input_fn dovrebbe essere queste stringhe grezze e le chiavi ["cat", "dog"] devono essere passate allo stimatore come parametro (vedere i dettagli di seguito).

Per gestire la mappatura delle etichette di stringa su numeri interi, è necessario utilizzare TensorFlow Transform per generare un vocabolario. Lo dimostriamo nello snippet di codice di seguito:

def _preprocessing_fn(inputs):
  """Preprocess input features into transformed features."""

  ...


  education = inputs[features.RAW_LABEL_KEY]
  _ = tft.vocabulary(education, vocab_filename=features.RAW_LABEL_KEY)

  ...

La funzione di pre-elaborazione sopra accetta la funzione di input non elaborata (che verrà anche restituita come parte dell'output della funzione di pre-elaborazione) e chiama tft.vocabulary su di essa. Ciò si traduce nella generazione di un vocabolario per l' education cui è possibile accedere nel modello.

L'esempio mostra anche come trasformare un'etichetta e quindi generare un vocabolario per l'etichetta trasformata. In particolare, prende la education sull'etichetta grezza e converte tutte le etichette tranne le prime 5 (per frequenza) in UNKNOWN , senza convertire l'etichetta in un numero intero.

Nel codice del modello, al classificatore deve essere assegnato il vocabolario generato da tft.vocabulary come argomento label_vocabulary . Questo viene fatto leggendo prima questo vocabolario come un elenco con una funzione di aiuto. Questo è mostrato nello snippet di seguito. Nota che il codice di esempio usa l'etichetta trasformata discussa sopra, ma qui mostriamo il codice per usare l'etichetta non elaborata.

def create_estimator(pipeline_inputs, hparams):

  ...

  tf_transform_output = trainer_util.TFTransformOutput(
      pipeline_inputs.transform_dir)

  # vocabulary_by_name() returns a Python list.
  label_vocabulary = tf_transform_output.vocabulary_by_name(
      features.RAW_LABEL_KEY)

  return tf.contrib.learn.DNNLinearCombinedClassifier(
      ...
      n_classes=len(label_vocab),
      label_vocabulary=label_vocab,
      ...)

Configurazione delle statistiche di pre-trasformazione e post-trasformazione

Come accennato in precedenza, il componente Transform richiama TFDV per calcolare le statistiche di pre-trasformazione e post-trasformazione. TFDV accetta come input un oggetto StatsOptions opzionale. Gli utenti potrebbero voler configurare questo oggetto per abilitare determinate statistiche aggiuntive (es. Statistiche NLP) o per impostare soglie convalidate (es. Frequenza minima / massima del token). Per fare ciò, definire una stats_options_updater_fn nel file del modulo.

def stats_options_updater_fn(stats_type, stats_options):
  ...
  if stats_type == stats_options_util.StatsType.PRE_TRANSFORM:
    # Update stats_options to modify pre-transform statistics computation.
    # Most constraints are specified in the schema which can be accessed
    # via stats_options.schema.
  if stats_type == stats_options_util.StatsType.POST_TRANSFORM
    # Update stats_options to modify post-transform statistics computation.
    # Most constraints are specified in the schema which can be accessed
    # via stats_options.schema.
  return stats_options

Le statistiche post-trasformazione spesso traggono vantaggio dalla conoscenza del vocabolario utilizzato per preelaborare una caratteristica. Il nome del vocabolario per la mappatura del percorso viene fornito a StatsOptions (e quindi TFDV) per ogni vocabolario generato da TFT. Inoltre, mappature per vocabolari esternamente create possono essere aggiunti (i) modificando direttamente i vocab_paths dizionario di entro StatsOptions o (ii) utilizzando tft.annotate_asset .