Компонент конвейера Transform TFX

Компонент конвейера Transform TFX выполняет разработку функций для tf.Examples, созданных компонентом ExampleGen , с использованием схемы данных, созданной компонентом SchemaGen , и создает как SavedModel, так и статистику по данным до и после преобразования. При выполнении SavedModel примет tf.Examples, выданный из компонента ExampleGen, и выдаст преобразованные данные объекта.

  • Потребляет: tf.Examples из компонента ExampleGen и схему данных из компонента SchemaGen.
  • Выдает: SavedModel в компонент Trainer, статистику до и после преобразования.

Настройка компонента преобразования

После того, как ваш preprocessing_fn написан, его необходимо определить в модуле Python, который затем предоставляется компоненту Transform в качестве входных данных. Этот модуль будет загружен с помощью преобразования, и функция с именем preprocessing_fn будет найдена и использована преобразованием для построения конвейера предварительной обработки.

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

Кроме того, вы можете захотеть предоставить опции для расчета статистики до или после преобразования на основе TFDV . Для этого определите stats_options_updater_fn в том же модуле.

Преобразование и преобразование TensorFlow

Transform широко использует TensorFlow Transform для разработки функций в вашем наборе данных. TensorFlow Transform — отличный инструмент для преобразования данных объектов перед тем, как они попадут в вашу модель, а также в рамках процесса обучения. Общие преобразования функций включают в себя:

  • Встраивание : преобразование разреженных функций (например, целочисленных идентификаторов, созданных словарем) в плотные функции путем нахождения осмысленного отображения из пространства высокой размерности в пространство низкой размерности. См. раздел «Внедрения» в ускоренном курсе по машинному обучению для ознакомления с вложениями.
  • Генерация словаря : преобразование строк или других нечисловых функций в целые числа путем создания словаря, который сопоставляет каждое уникальное значение с идентификационным номером.
  • Нормализация значений : преобразование числовых признаков таким образом, чтобы все они попадали в один и тот же диапазон.
  • Бакетизация : преобразование функций с непрерывными значениями в категориальные функции путем присвоения значений дискретным сегментам.
  • Обогащение текстовых функций : создание функций из необработанных данных, таких как токены, n-граммы, сущности, настроения и т. д., для обогащения набора функций.

TensorFlow Transform обеспечивает поддержку этих и многих других видов преобразований:

  • Автоматически создавайте словарь из ваших последних данных.

  • Выполняйте произвольные преобразования данных перед их отправкой в ​​модель. Преобразование TensorFlow встраивает преобразования в граф TensorFlow для вашей модели, поэтому во время обучения и вывода выполняются одни и те же преобразования. Вы можете определить преобразования, которые относятся к глобальным свойствам данных, таким как максимальное значение признака во всех экземплярах обучения.

Вы можете преобразовать свои данные, как вам нравится, перед запуском TFX. Но если вы сделаете это в TensorFlow Transform, преобразования станут частью графа TensorFlow. Такой подход помогает избежать перекоса обучения/обслуживания.

Преобразования внутри вашего кода моделирования используют FeatureColumns. Используя FeatureColumns, вы можете определить сегментацию, целочисленность, использующую предопределенные словари, или любые другие преобразования, которые можно определить, не глядя на данные.

В отличие от этого, TensorFlow Transform предназначен для преобразований, которые требуют полного прохождения данных для вычисления значений, которые заранее не известны. Например, для генерации словаря требуется полный проход по данным.

Помимо вычисления значений с помощью Apache Beam, TensorFlow Transform позволяет пользователям встраивать эти значения в граф TensorFlow, который затем можно загрузить в обучающий граф. Например, при нормализации функций функция tft.scale_to_z_score будет вычислять среднее значение и стандартное отклонение функции, а также представление на графике TensorFlow функции, которая вычитает среднее значение и делит на стандартное отклонение. Создавая график TensorFlow, а не только статистику, TensorFlow Transform упрощает процесс создания конвейера предварительной обработки.

Поскольку предварительная обработка представлена ​​в виде графа, она может выполняться на сервере и гарантированно не противоречить между обучением и обслуживанием. Эта согласованность устраняет один источник перекоса обучения/обслуживания.

TensorFlow Transform позволяет пользователям указывать конвейер предварительной обработки с помощью кода TensorFlow. Это означает, что конвейер строится так же, как граф TensorFlow. Если бы в этом графе использовались только операции TensorFlow, конвейер был бы чистой картой, которая принимает пакеты ввода и возвращает пакеты вывода. Такой конвейер будет эквивалентен размещению этого графика внутри вашего input_fn при использовании API tf.Estimator . Чтобы указать полнопроходные операции, такие как вычисление квантилей, TensorFlow Transform предоставляет специальные функции, называемые analyzers , которые выглядят как операции TensorFlow, но на самом деле определяют отложенные вычисления, которые будут выполняться Apache Beam, а выходные данные вставляются в граф как постоянный. В то время как обычная операция TensorFlow будет принимать один пакет в качестве входных данных, выполнять некоторые вычисления только для этого пакета и выдавать пакет, analyzer выполнит глобальное сокращение (реализованное в Apache Beam) для всех пакетов и вернет результат.

Комбинируя обычные операции TensorFlow и анализаторы TensorFlow Transform, пользователи могут создавать сложные конвейеры для предварительной обработки своих данных. Например, функция tft.scale_to_z_score принимает входной тензор и возвращает этот тензор, нормализованный так, чтобы иметь среднее значение 0 и дисперсию 1 . Он делает это, var анализаторы mean и переменной под капотом, которые будут эффективно генерировать константы в графе, равные среднему значению и дисперсии входного тензора. Затем он будет использовать операции TensorFlow для вычитания среднего значения и деления на стандартное отклонение.

Преобразование TensorFlow preprocessing_fn

Компонент TFX Transform упрощает использование Transform, обрабатывая вызовы API, связанные с чтением и записью данных, а также записывая выходные данные SavedModel на диск. Как пользователь TFX, вам нужно определить только одну функцию, называемую preprocessing_fn . В preprocessing_fn вы определяете серию функций, которые манипулируют входным словарем тензоров для создания выходного словаря тензоров. Вы можете найти вспомогательные функции, такие как scale_to_0_1 и calculate_and_apply_vocabulary, в API преобразования TensorFlow или использовать обычные функции TensorFlow, как показано ниже.

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

Понимание входных данных для preprocessing_fn

preprocessing_fn описывает ряд операций с тензорами (то есть Tensor s или SparseTensor s), поэтому для правильного написания preprocessing_fn необходимо понимать, как ваши данные представлены в виде тензоров. Входные данные для preprocessing_fn определяются схемой. Schema содержит список Feature , и Transform преобразует их в «спецификацию функции» (иногда называемую «спецификацией синтаксического анализа»), которая представляет собой словарь, ключи которого являются именами функций, а значениями являются одно из FixedLenFeature или VarLenFeature (или другое). параметры, не используемые TensorFlow Transform).

Правила вывода спецификации функции из Schema таковы:

  • Каждая feature с установленной shape приведет к tf.FixedLenFeature с формой и default_value=None . presence.min_fraction должно быть равно 1 , в противном случае возникнет ошибка, поскольку при отсутствии значения по умолчанию tf.FixedLenFeature требует, чтобы эта функция всегда присутствовала.
  • Каждая feature с не заданной shape приведет к VarLenFeature .
  • Результатом каждого sparse_feature будет tf.SparseFeature , size и is_sorted которого определяются fixed_shape и is_sorted сообщения SparseFeature .
  • У функций, используемых в качестве index_feature или value_feature для sparse_feature , не будет собственной записи, сгенерированной в спецификации функции.
  • Соответствие между полем type feature (или функцией значений sparse_feature ) и dtype спецификации функции представлено в следующей таблице:
type dtype
schema_pb2.INT tf.int64
schema_pb2.FLOAT tf.float32
schema_pb2.BYTES tf.string

Использование TensorFlow Transform для обработки строковых меток

Обычно нужно использовать TensorFlow Transform как для создания словаря, так и для применения этого словаря для преобразования строк в целые числа. При следовании этому рабочему процессу input_fn , созданный в модели, будет выводить целочисленную строку. Однако метки являются исключением, потому что для того, чтобы модель могла отображать выходные (целочисленные) метки обратно в строки, модели требуется input_fn для вывода строковой метки вместе со списком возможных значений метки. Например, если метки — cat и dog , то выводом input_fn должны быть эти необработанные строки, а ключи ["cat", "dog"] должны быть переданы в оценщик в качестве параметра (подробности см. ниже).

Чтобы обрабатывать сопоставление строковых меток с целыми числами, вы должны использовать преобразование TensorFlow для создания словаря. Мы демонстрируем это в фрагменте кода ниже:

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)

  ...

Приведенная выше функция предварительной обработки берет необработанную входную функцию (которая также будет возвращена как часть вывода функции предварительной обработки) и вызывает tft.vocabulary . В результате создается словарный запас для education , к которому можно получить доступ в модели.

В примере также показано, как преобразовать метку, а затем сгенерировать словарь для преобразованной метки. В частности, он берет необработанное education метки и преобразует все метки, кроме первых 5 (по частоте), в UNKNOWN , не преобразовывая метку в целое число.

В коде модели классификатору должен быть передан словарь, сгенерированный tft.vocabulary , в качестве аргумента label_vocabulary . Это делается путем предварительного чтения этого словаря в виде списка со вспомогательной функцией. Это показано во фрагменте ниже. Обратите внимание, что в примере кода используется преобразованная метка, описанная выше, но здесь мы показываем код для использования необработанной метки.

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

Настройка статистики до и после преобразования

Как упоминалось выше, компонент Transform вызывает TFDV для вычисления статистики как до, так и после преобразования. TFDV принимает в качестве входных данных необязательный объект StatsOptions . Пользователи могут настроить этот объект, чтобы включить определенные дополнительные статистические данные (например, статистику NLP) или установить пороговые значения, которые проверяются (например, минимальная / максимальная частота токена). Для этого определите stats_options_updater_fn в файле модуля.

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

Статистика после преобразования часто выигрывает от знания словаря, используемого для предварительной обработки функции. Сопоставление имени словаря с путем предоставляется StatsOptions (и, следовательно, TFDV) для каждого словаря, сгенерированного TFT. Кроме того, сопоставления для словарей, созданных извне, можно добавить либо (i) напрямую изменив словарь vocab_paths в StatsOptions, либо (ii) используя tft.annotate_asset .