Dołącz do społeczności SIG TFX-Addons i pomóż ulepszyć TFX! Dołącz do dodatków SIG TFX

Składnik Transform TFX Pipeline

Składnik Transform TFX pipeline wykonuje inżynierię funkcji na tf.Examples emitowane ze składnika ExampleGen przy użyciu schematu danych utworzonego przez składnik SchemaGen i emituje zarówno SavedModel, jak i statystyki dotyczące danych przed i po transformacji. Po wykonaniu SavedModel zaakceptuje tf.Examples wyemitowane ze składnika ExampleGen i wyemituje przekształcone dane funkcji.

  • Używa: tf.Examples ze składnika ExampleGen i schematu danych ze składnika SchemaGen.
  • Emituje: SavedModel do składnika Trainer, statystyki przed transformacją i po transformacji.

Konfigurowanie komponentu transformacji

Po zapisaniu preprocessing_fn należy go zdefiniować w module języka Python, który jest następnie przekazywany do komponentu Transform jako dane wejściowe. Ten moduł zostanie załadowany przez transformację, a funkcja o nazwie preprocessing_fn zostanie znaleziona i użyta przez Transform do skonstruowania potoku przetwarzania wstępnego.

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

Dodatkowo, możesz chcieć udostępnić opcje do obliczeń statystyk przed transformacją lub po transformacji opartych na TFDV . Aby to zrobić, zdefiniuj stats_options_updater_fn w tym samym module.

Transform i TensorFlow Transform

Transform w szerokim zakresie wykorzystuje TensorFlow Transform do wykonywania inżynierii funkcji w zestawie danych. TensorFlow Transform to doskonałe narzędzie do przekształcania danych cech, zanim trafią one do modelu i jako część procesu uczenia. Typowe przekształcenia funkcji obejmują:

  • Osadzanie : przekształcanie rzadkich cech (takich jak całkowite identyfikatory generowane przez słownik) w zagęszczone cechy poprzez znalezienie sensownego odwzorowania z przestrzeni wielowymiarowej na przestrzeń niskowymiarową. Zapoznaj się z jednostką osadzania w kursie awarii uczenia maszynowego, aby zapoznać się z wprowadzeniem do osadzania.
  • Generowanie słownictwa : konwertowanie ciągów znaków lub innych cech nienumerycznych na liczby całkowite poprzez tworzenie słownictwa, które odwzorowuje każdą unikalną wartość na numer identyfikacyjny.
  • Normalizowanie wartości : przekształcanie cech numerycznych tak, aby mieściły się w podobnym zakresie.
  • Bucketyzacja : przekształcanie elementów o wartościach ciągłych w cechy jakościowe poprzez przypisywanie wartości do dyskretnych segmentów.
  • Wzbogacanie funkcji tekstowych : tworzenie funkcji z surowych danych, takich jak tokeny, n-gramy, jednostki, sentyment itp. W celu wzbogacenia zestawu funkcji.

TensorFlow Transform zapewnia obsługę tych i wielu innych rodzajów przekształceń:

  • Automatycznie generuj słownictwo na podstawie najnowszych danych.

  • Wykonuj dowolne transformacje danych przed wysłaniem ich do modelu. TensorFlow Transform buduje transformacje na wykresie TensorFlow dla twojego modelu, więc te same transformacje są wykonywane w czasie uczenia i wnioskowania. Można zdefiniować transformacje, które odwołują się do globalnych właściwości danych, takich jak maksymalna wartość funkcji we wszystkich wystąpieniach szkoleniowych.

Możesz przekształcić swoje dane w dowolny sposób przed uruchomieniem TFX. Ale jeśli zrobisz to w ramach transformacji TensorFlow, transformacje staną się częścią wykresu TensorFlow. Takie podejście pomaga uniknąć przekrzywienia treningu / serwowania.

Transformacje w kodzie modelowania używają FeatureColumns. Korzystając z FeatureColumns, można zdefiniować podziały, integeryzacje korzystające ze wstępnie zdefiniowanych słowników lub dowolne inne przekształcenia, które można zdefiniować bez patrzenia na dane.

Natomiast transformacja TensorFlow jest przeznaczona do transformacji, które wymagają pełnego przejścia danych w celu obliczenia wartości, które nie są z góry znane. Na przykład generowanie słownictwa wymaga pełnego przejścia danych.

Oprócz obliczania wartości za pomocą Apache Beam, TensorFlow Transform umożliwia użytkownikom osadzanie tych wartości w wykresie TensorFlow, który można następnie załadować do wykresu szkoleniowego. Na przykład podczas normalizowania cech funkcja tft.scale_to_z_score obliczy średnią i odchylenie standardowe cechy, a także reprezentację na wykresie TensorFlow funkcji, która odejmuje średnią i dzieli przez odchylenie standardowe. Emitując wykres TensorFlow, a nie tylko statystyki, TensorFlow Transform upraszcza proces tworzenia potoku wstępnego przetwarzania.

Ponieważ przetwarzanie wstępne jest wyrażone w postaci wykresu, może się zdarzyć na serwerze i gwarantuje spójność między uczeniem a serwowaniem. Ta spójność eliminuje jedno źródło przekrzywienia treningu / serwowania.

TensorFlow Transform umożliwia użytkownikom określenie potoku przetwarzania wstępnego przy użyciu kodu TensorFlow. Oznacza to, że potok jest zbudowany w taki sam sposób, jak wykres TensorFlow. Gdyby na tym wykresie użyto tylko operacji TensorFlow, potok byłby czystą mapą, która akceptuje partie danych wejściowych i zwraca partie danych wyjściowych. Taki potok byłby równoważny z umieszczeniem tego wykresu wewnątrz twojego input_fn podczas korzystania z API tf.Estimator . Aby określić operacje pełnego przebiegu, takie jak obliczanie kwantyli, TensorFlow Transform udostępnia specjalne funkcje zwane analyzers które wyglądają jak operacje TensorFlow, ale w rzeczywistości określają odroczone obliczenia, które zostaną wykonane przez Apache Beam, a dane wyjściowe wstawione do wykresu jako stały. Podczas gdy zwykła operacja TensorFlow pobierze pojedynczą partię jako dane wejściowe, wykona pewne obliczenia na tej partii i wyemituje partię, analyzer wykona globalną redukcję (zaimplementowaną w Apache Beam) na wszystkie partie i zwróci wynik.

Łącząc zwykłe operacje TensorFlow i analizatory TensorFlow Transform, użytkownicy mogą tworzyć złożone potoki w celu wstępnego przetwarzania danych. Na przykład funkcja tft.scale_to_z_score przyjmuje tensor wejściowy i zwraca ten tensor znormalizowany do średniej 0 i wariancji 1 . Robi to, wywołując pod maską analizatory mean i var , które skutecznie wygenerują stałe na wykresie równe średniej i wariancji tensora wejściowego. Następnie użyje operacji TensorFlow do odjęcia średniej i podzielenia przez odchylenie standardowe.

TensorFlow Transform preprocessing_fn

Składnik TFX Transform upraszcza korzystanie z Transform, obsługując wywołania API związane z odczytywaniem i zapisywaniem danych oraz zapisywanie danych wyjściowych SavedModel na dysk. Jako użytkownik TFX musisz zdefiniować tylko jedną funkcję zwaną preprocessing_fn . W preprocessing_fn definiujesz serię funkcji, które manipulują dyktą wejściową tensorów w celu utworzenia dyktu wyjściowego tensorów. Możesz znaleźć funkcje pomocnicze, takie jak scale_to_0_1 i compute_and_apply_vocabulary, TensorFlow Transform API lub użyć zwykłych funkcji TensorFlow, jak pokazano poniżej.

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

Zrozumienie danych wejściowych do preprocessing_fn

preprocessing_fn opisuje serię operacji na tensorach (to znaczy Tensor s lub SparseTensor s), więc aby poprawnie napisać preprocessing_fn , konieczne jest zrozumienie, w jaki sposób dane są reprezentowane jako tensory. Dane wejściowe do preprocessing_fn są określane przez schemat. Schema proto zawiera listę Feature s, i Transform konwertuje je do „funkcji SPEC” (czasami nazywane jest „parsowania Spec”), który jest DICT którego klucze są nazwami funkcji i których wartości są jednym z FixedLenFeature lub VarLenFeature (lub innego opcje nieużywane przez TensorFlow Transform).

Reguły wnioskowania o specyfikacji funkcji ze Schema to

  • Każda feature z ustawionym shape da w wyniku tf.FixedLenFeature z kształtem i wartością default_value=None . presence.min_fraction musi wynosić 1 przeciwnym razie wystąpi błąd, ponieważ gdy nie ma wartości domyślnej, tf.FixedLenFeature wymaga, aby funkcja była zawsze obecna.
  • Każda feature której shape nie został ustawiony, spowoduje powstanie VarLenFeature .
  • Każdy sparse_feature spowoduje tf.SparseFeature którego size i is_sorted są określane przez fixed_shape i is_sorted pól z SparseFeature wiadomości.
  • Funkcje używane jako index_feature lub value_feature w sparse_feature nie będą miały własnego wpisu wygenerowanego w specyfikacji funkcji.
  • Zależność pomiędzy type dziedzinie feature (lub funkcją wartościami sparse_feature proto) i dtype spec funkcji podano w poniższej tabeli:
type dtype
schema_pb2.INT tf.int64
schema_pb2.FLOAT tf.float32
schema_pb2.BYTES tf.string

Używanie funkcji TensorFlow Transform do obsługi etykiet łańcuchowych

Zwykle chce się użyć transformacji TensorFlow zarówno do wygenerowania słownictwa, jak i zastosowania tego słownictwa do konwersji łańcuchów na liczby całkowite. Podczas wykonywania tego przepływu pracy input_fn skonstruowany w modelu wyprowadzi łańcuch z integeracją. Jednak etykiety są wyjątkiem, ponieważ aby model mógł odwzorować etykiety wyjściowe (całkowite) z powrotem na ciągi, model potrzebuje parametru input_fn aby wyprowadzić etykietę ciągu, wraz z listą możliwych wartości etykiety. Np. Jeśli etykiety to cat i dog to wyjście input_fn powinno być tymi nieprzetworzonymi łańcuchami, a klucze ["cat", "dog"] muszą być przekazane do estymatora jako parametr (zobacz szczegóły poniżej).

Aby obsłużyć mapowanie etykiet łańcuchowych na liczby całkowite, do wygenerowania słownika należy użyć transformacji TensorFlow. Pokazujemy to w poniższym fragmencie kodu:

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)

  ...

Powyższa funkcja przetwarzania wstępnego pobiera surową cechę wejściową (która również zostanie zwrócona jako część wyjścia funkcji przetwarzania wstępnego) i wywołuje na niej tft.vocabulary . Powoduje to generowanie słownictwa education którego można uzyskać dostęp w modelu.

Przykład pokazuje również, jak przekształcić etykietę, a następnie wygenerować słownik dla przekształconej etykiety. W szczególności pobiera surową education etykiet i konwertuje wszystkie oprócz 5 najlepszych etykiet (według częstotliwości) na UNKNOWN , bez konwertowania etykiety na liczbę całkowitą.

W kodzie modelu klasyfikator musi otrzymać słownictwo wygenerowane przez tft.vocabulary jako argument label_vocabulary . Odbywa się to poprzez przeczytanie najpierw tego słownika jako listy z funkcją pomocniczą. Jest to pokazane w poniższym fragmencie. Zwróć uwagę, że przykładowy kod używa przekształconej etykiety omówionej powyżej, ale tutaj pokazujemy kod używający etykiety surowej.

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,
      ...)

Konfigurowanie statystyk przed i po transformacji

Jak wspomniano powyżej, składnik Transform wywołuje TFDV w celu obliczenia statystyk przed i po transformacji. TFDV przyjmuje jako dane wejściowe opcjonalny obiekt StatsOptions . Użytkownicy mogą chcieć skonfigurować ten obiekt, aby włączyć pewne dodatkowe statystyki (np. Statystyki NLP) lub ustawić progi, które są sprawdzane (np. Minimalna / maksymalna częstotliwość tokenów). Aby to zrobić, zdefiniuj stats_options_updater_fn w pliku modułu.

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

Statystyki po transformacji często korzystają ze znajomości słownictwa używanego do wstępnego przetwarzania cechy. Nazwa słownika do mapowania ścieżki jest dostarczana do StatsOptions (i stąd TFDV) dla każdego słownika generowanego przez TFT. Dodatkowo, do odwzorowania na zewnątrz utworzonych słowników można dodać (i) bezpośrednią modyfikację vocab_paths słownika ciągu StatsOptions lub (ii), stosując tft.annotate_asset .