Il componente pipeline Transform TFX

Il componente della pipeline Transform TFX esegue la progettazione delle funzionalità su tf.Examples emessi da un componente EsempioGen , utilizzando uno schema di dati creato da un componente SchemaGen ed emette sia un SavedModel che statistiche sui dati pre-trasformazione e post-trasformazione. Una volta eseguito, SavedModel accetterà tf.Examples emessi da un componente EsempioGen ed emetterà i dati delle funzionalità trasformate.

  • Consuma: tf.Examples da un componente EsempioGen e uno schema di dati da un componente SchemaGen.
  • Emette: un modello salvato in un componente Trainer, statistiche pre-trasformazione e post-trasformazione.

Configurazione di un componente di trasformazione

Una volta scritto preprocessing_fn , è necessario definirlo 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 preelaborazione.

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 delle statistiche pre-trasformazione o post-trasformazione basate su TFDV . Per fare ciò, definisci stats_options_updater_fn all'interno dello stesso modulo.

Trasformazione e trasformazione TensorFlow

Transform fa ampio uso di TensorFlow Transform per eseguire la progettazione delle funzionalità sul set di dati. TensorFlow Transform è un ottimo strumento per trasformare i dati delle feature prima che vengano inseriti nel modello e come parte del processo di training. 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 dimensionalità allo spazio a bassa dimensionalità. Consulta l' unità Embeddings nel corso accelerato di machine learning per un'introduzione agli incorporamenti.
  • Generazione del vocabolario : conversione di stringhe o altre caratteristiche non numeriche in numeri interi creando un vocabolario che associa ciascun valore univoco a un numero ID.
  • Normalizzazione dei valori : trasformazione delle caratteristiche numeriche in modo che rientrino tutte in un intervallo simile.
  • Bucketization : conversione di funzionalità a valore continuo in funzionalità categoriali assegnando valori a bucket discreti.
  • Arricchimento delle funzionalità del 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 durante il training e l'inferenza. Puoi definire trasformazioni che fanno riferimento alle proprietà globali dei dati, come il valore massimo di una funzionalità in tutte le istanze di training.

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 distorsioni tra allenamento e servizio.

Le trasformazioni all'interno del codice di modellazione utilizzano FeatureColumns. Utilizzando FeatureColumns, puoi definire bucketization, integralizzazioni 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 training. Ad esempio, quando si normalizzano le caratteristiche, la funzione tft.scale_to_z_score calcolerà la media e la deviazione standard di una caratteristica, nonché 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 preelaborazione.

Poiché la preelaborazione è espressa come grafico, può avvenire sul server ed è garantita la coerenza tra addestramento e servizio. Questa coerenza elimina una fonte di disallineamento tra allenamento e servizio.

TensorFlow Transform consente agli utenti di specificare la pipeline di preelaborazione utilizzando il codice TensorFlow. Ciò significa che una pipeline è costruita allo stesso modo di un grafico TensorFlow. Se in questo grafico venissero utilizzate solo le operazioni TensorFlow, la pipeline sarebbe una mappa pura che accetta batch di input e restituisce batch di output. Una pipeline di questo tipo equivarrebbe a posizionare questo grafico all'interno di input_fn quando si utilizza l'API tf.Estimator . Per specificare operazioni a passaggio completo 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 le normali operazioni TensorFlow e gli analizzatori TensorFlow Transform, 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 dietro le quinte gli analizzatori mean e var , che genereranno effettivamente costanti nel grafico uguali alla media e alla varianza del tensore di input. Utilizzerà quindi le operazioni TensorFlow per sottrarre la media e dividerla per la deviazione standard.

La trasformazione TensorFlow preprocessing_fn

Il componente TFX Transform semplifica l'utilizzo di Transform gestendo le chiamate API relative alla lettura e alla 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 definisci una serie di funzioni che manipolano il dettato di input dei tensori per produrre il dettato di tensori in output. Puoi trovare funzioni di supporto come scale_to_0_1 e compute_and_apply_vocabulary nell'API TensorFlow Transform 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:
    # If sparse make it dense, setting nan's to 0 or '', and apply zscore.
    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

Comprendere gli input per preprocessing_fn

preprocessing_fn descrive una serie di operazioni sui tensori (ovvero Tensor s, SparseTensor s o RaggedTensor s). Per definire correttamente preprocessing_fn è necessario capire come i dati vengono rappresentati come tensori. L'input per preprocessing_fn è determinato dallo schema. Un prototipo Schema viene infine convertito in una "specifica di funzionalità" (a volte chiamata "specifica di analisi") utilizzata per l'analisi dei dati, vedere ulteriori dettagli sulla logica di conversione qui .

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 intera. Tuttavia le etichette rappresentano un'eccezione, perché affinché il modello sia in grado di mappare le etichette di output (intere) in stringhe, il modello necessita che input_fn restituisca 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 delle stringhe su numeri interi, dovresti utilizzare TensorFlow Transform per generare un vocabolario. Lo dimostriamo nello snippet di codice seguente:

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 preelaborazione di cui sopra prende la funzionalità di input grezzo (che verrà restituita anche come parte dell'output della funzione di preelaborazione) e richiama tft.vocabulary su di essa. Ciò si traduce nella generazione di un vocabolario per education a 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 grezza sull'etichetta 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 qui sotto. Tieni presente che il codice di esempio utilizza l'etichetta trasformata discussa sopra, ma qui mostriamo il codice per l'utilizzo dell'etichetta grezza.

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 pre-trasformazione e post-trasformazione

Come accennato in precedenza, il componente Trasformazione richiama TFDV per calcolare le statistiche sia pre-trasformazione che post-trasformazione. TFDV accetta come input un oggetto StatsOptions opzionale. Gli utenti potrebbero voler configurare questo oggetto per abilitare alcune statistiche aggiuntive (ad esempio le statistiche NLP) o per impostare soglie convalidate (ad esempio la frequenza minima/massima del token). Per fare ciò, definire 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 la preelaborazione di una funzionalità. Il nome del vocabolario per la mappatura del percorso viene fornito a StatsOptions (e quindi a TFDV) per ogni vocabolario generato da TFT. Inoltre, le mappature per i vocabolari creati esternamente possono essere aggiunte (i) modificando direttamente il dizionario vocab_paths all'interno di StatsOptions o (ii) utilizzando tft.annotate_asset .