Помогают защитить Большой Барьерный Риф с TensorFlow на Kaggle Присоединяйтесь вызов

Начните с преобразования TensorFlow

Это руководство содержит основные понятия tf.Transform и как использовать их. Будет:

  • Определение предварительной обработки функции, логическое описание трубопровода , который преобразует исходные данные в данных , используемых для обучения модели машинного обучения.
  • Показать Apache Beam реализации используется для преобразования данных путем преобразования функции предварительной обработки в трубопровод Beam.
  • Показать дополнительные примеры использования.

Определите функцию предварительной обработки

Функция предварительной обработки является наиболее важным понятием tf.Transform . Функция предварительной обработки представляет собой логическое описание преобразования набора данных. Функция предварительной обработки принимает и возвращает словарь тензоров, где тензор означает Tensor или SparseTensor . Существует два типа функций, используемых для определения функции предварительной обработки:

  1. Любая функция, которая принимает и возвращает тензоры. Они добавляют к графу операции TensorFlow, которые преобразуют необработанные данные в преобразованные данные.
  2. Любой из анализаторов , предоставленных tf.Transform . Анализаторы также принимают и возвращают тензоры, но в отличие от функций TensorFlow, они не добавляют операций на графику. Вместо этого, анализаторы вызывают tf.Transform вычислить полный проход операции за пределами TensorFlow. Они используют входные значения тензора по всему набору данных для создания постоянного тензора, который возвращается в качестве выходных данных. Например, tft.min вычисляет минимум тензора над набором данных. tf.Transform обеспечивает фиксированный набор анализаторов, но это будет продлено в версиях будущих.

Пример функции предварительной обработки

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

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
  }

Здесь, x , y и s являются Tensor ы , которые представляют собой входные функции. Первый новый тензор , который создается, x_centered , построен с применением tft.mean на x и вычитая из этого x . tft.mean(x) возвращает тензор , представляющий среднее значение тензора x . x_centered тензор x со средним вычитаются.

Второй новый тензор, y_normalized , создается таким же образом , но с использованием метода удобства tft.scale_to_0_1 . Этот метод делает что - то похожее на вычислительный x_centered , а именно вычисление максимума и минимума и использование их для шкалы y .

Тензорное s_integerized показывает пример манипуляций со строками. В этом случае мы берем строку и сопоставляем ее с целым числом. При этом используется функция удобства tft.compute_and_apply_vocabulary . Эта функция использует анализатор для вычисления уникальных значений, полученных входными строками, а затем использует операции TensorFlow для преобразования входных строк в индексы в таблице уникальных значений.

Последний столбец показывает, что можно использовать операции TensorFlow для создания новых функций путем объединения тензоров.

Функция предварительной обработки определяет конвейер операций над набором данных. Для применения трубопровода, мы рассчитываем на реализацию конкретной части tf.Transform API. Реализация Apache Beam обеспечивает PTransform , который применяет функцию предварительной обработки пользователя к данным. Типичный рабочий процесс из tf.Transform пользователя будет строить Preprocessing функции, а затем включить это в больший трубопровод Beam, создавая данные для обучения.

Дозирование

Пакетная обработка — важная часть TensorFlow. Поскольку одна из целей tf.Transform является обеспечение TensorFlow график для предварительной обработки , которые могут быть включены в сервировки графа (и, в случае необходимости, учебный график), дозирующее также является важным понятием в tf.Transform .

Хотя не ясно , в приведенном выше примере, пользователь определяется предобработки функция передается тензоры , представляющие партии , а не отдельные экземпляры, как это происходит в процессе подготовки и обслуживания с TensorFlow. С другой стороны, анализаторы выполняют вычисления по всему набору данных, которые возвращают одно значение, а не пакет значений. x представляет собой Tensor с формой (batch_size,) , в то время как tft.mean(x) представляет собой Tensor с формой () . Вычитания x - tft.mean(x) трансляции , где значение tft.mean(x) вычитаются из каждого элемента партии , представленной x .

Реализация Apache Beam

В то время как функция предварительной обработки предназначена как логическое описание предварительной обработки трубопровода , реализованный на перерабатывающие рамках нескольких данных, tf.Transform обеспечивает каноническую реализацию , используемую на Apache Beam. Эта реализация демонстрирует функциональные возможности, требуемые от реализации. Для этой функции не существует формального API, поэтому каждая реализация может использовать API, идиоматический для своей конкретной платформы обработки данных.

Реализация Apache предоставляет два луча PTransform сек , используемые для обработки данных для предварительной обработки функции. Ниже показано использование для композитного 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

transformed_data содержание показан ниже и содержит преобразованных столбцов в том же формате, что и исходные данные. В частности, значения s_integerized являются [0, 1, 0] -эти значения зависят от того, как слова hello и world были нанесены на карту в целые числа, что является детерминированным. Для столбца x_centered , мы вычитали среднее так что значения столбца x , которые были [1.0, 2.0, 3.0] , стали [-1.0, 0.0, 1.0] . Точно так же остальные столбцы соответствуют ожидаемым значениям.

[{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}]

Оба raw_data и transformed_data являются наборами данных. В следующих двух разделах показано, как реализация Beam представляет наборы данных и как читать и записывать данные на диск. Другое возвращаемое значение, transform_fn , представляет собой преобразование применяется к данным, покрытые подробно ниже.

AnalyzeAndTransformDataset представляет собой композицию из двух фундаментальных преобразований , предусмотренных реализацией AnalyzeDataset и TransformDataset . Таким образом, следующие два фрагмента кода эквивалентны:

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 является чистой функцией , которая представляет собой операцию, которая применяется к каждой строке набора данных. В частности, значения анализатора уже вычислены и рассматриваются как константы. В примере, transform_fn содержит в качестве констант среднего столбцов x , минимального и максимального столбец y , и словаря , используемый для отображения строки в целые числа.

Важная особенность tf.Transform является то , что transform_fn представляет собой карту над рядами -это является чистой функция применяется к каждой строке отдельно. Все вычисления для объединения строк выполняется в AnalyzeDataset . Кроме того, transform_fn представлен в виде TensorFlow Graph , который может быть встроен в обслуживающем граф.

AnalyzeAndTransformDataset предназначен для оптимизации в этом особом случае. Это та же модель используется в scikit учиться , обеспечивая fit , transform и fit_transform методы.

Форматы данных и схема

Реализация TFT Beam поддерживает два разных формата входных данных. Формат «экземпляр ДИКТ» (как показано в примере , приведенном выше , и в simple_example.py ) представляет собой интуитивное формат и подходит для небольших наборов данных , в то время как TFXIO ( Apache Стрелка формат) обеспечивает повышенную производительность и Suitble для больших массивов данных.

Реализация Beam сообщает, в каком формате будет входная коллекция PCollection, с помощью «метаданных», сопровождающих PCollection:

(raw_data, raw_data_metadata) | tft.AnalyzeDataset(...)
  • Если raw_data_metadata является dataset_metadata.DatasetMetadata (смотри ниже, «О„экземпляр ДИКТ“формат» раздела), а затем raw_data как ожидается, будет в формате «экземпляр ДИКТ».
  • Если raw_data_metadata является tfxio.TensorAdapterConfig (смотри ниже, «Формат TFXIO» секция), то raw_data как ожидается, будет в формате TFXIO.

Формат экземпляра dict

В предыдущих примерах кода, код определения raw_data_metadata опущено. Метаданные содержат схему, определяющую расположение данных, поэтому они считываются и записываются в различные форматы. Даже формат в памяти, показанный в последнем разделе, не является самоописывающим и требует схемы для интерпретации как тензоры.

Вот определение схемы для примера данных:

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

Schema прото содержит информацию , необходимую для синтаксического анализа данных из формата на диске или в памяти, в тензоры. Это , как правило , строится с помощью вызова schema_utils.schema_from_feature_spec с отображением ДИКТ функциональными клавишами для tf.io.FixedLenFeature , tf.io.VarLenFeature и tf.io.SparseFeature значений. Обратитесь к документации по tf.parse_example для более подробной информации.

Выше мы используем tf.io.FixedLenFeature , чтобы указать , что каждая функция содержит фиксированное число значений, в данном случае одно скалярное значение. Поскольку tf.Transform плавок случаев фактические Tensor , представляющая функцию будет иметь форму (None,) , где неизвестное измерение является пакетным измерением.

Формат TFXIO

В этом формате, данные , как ожидается , будет содержаться в pyarrow.RecordBatch . Для табличных данных, наша реализация Apache Beam принимает Arrow RecordBatch эс , которые состоят из колонн следующих типов:

  • pa.list_(<primitive>) , где <primitive> является pa.int64() , pa.float32() pa.binary() или pa.large_binary() .

  • pa.large_list(<primitive>)

Входная игрушки набор данных мы использовали выше, когда представляются в виде RecordBatch , выглядит следующим образом :

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'])
]

Подобно DatasetMetadata нужности для сопровождения формата «экземпляр Словаря», появится tfxio.TensorAdapterConfig необходимо сопровождать RecordBatch эс. Он состоит из схемы Стрелки из RecordBatch х лет, и TensorRepresentations однозначно определить , как столбцы в RecordBatch эс могут быть истолкованы как TensorFlow тензоры (включая , но не ограничиваясь tf.Tensor, tf.SparseTensor).

TensorRepresentations является Dict[Text, TensorRepresentation] , которая устанавливает связь между тензором , что preprocessing_fn принимает и столбцы в RecordBatch х годов. Например:

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

Значит , что inputs['x'] в preprocessing_fn должен быть плотным tf.Tensor, значение которого происходит из столбца имени 'col1' во входном RecordBatch х лет, и его (порционный) форма должна быть [batch_size, 2] .

TensorRepresentation является Protobuf определено в TensorFlow метаданных .

Совместимость с TensorFlow

tf.Transform обеспечивает поддержку для экспорта transform_fn выше или как 1.x TF или 2.x TF SavedModel. Поведение по умолчанию до 0.30 выпуска экспортировали 1.x TF SavedModel. Начиная с 0.30 выпуска, поведение по умолчанию для экспорта 2.x TF SavedModel если 2.x TF поведения не заблокированы явно (по телефону tf.compat.v1.disable_v2_behavior() , например).

При использовании концепции 1.x TF , таких как Estimators и Sessions , вы можете сохранить прежнее поведение, передав force_tf_compat_v1=True в tft_beam.Context при использовании tf.Transform в качестве библиотеки автономной или к Transform компонент в TFX.

При экспорте transform_fn в качестве 2.x TF SavedModel, то preprocessing_fn как ожидается, будет прослеживаться с использованием tf.function . Кроме того, если работает ваш трубопровод удаленно (например , с DataflowRunner ), убедитесь , что preprocessing_fn и вся зависимость упакованы надлежащим образом, как описано здесь .

Известные проблемы с использованием tf.Transform экспортировать 2.x TF SavedModel документируются здесь .

Ввод и вывод с помощью Apache Beam

До сих пор мы видели , входные и выходные данные в списках питона (из RecordBatch эс или экземпляров словарей). Это упрощение , что зависит от способности Apache Beam для работы со списками, а также в качестве основного представления данных, в PCollection .

PCollection является представлением данных , который образует часть трубопровода Beam. Трубопровод луча формируется путем применения различных PTransform с, в том числе AnalyzeDataset и TransformDataset , и работает трубопровод. PCollection не создается в памяти основного двоичного файла, но вместо этого распределяется среди рабочих (хотя этот раздел использует режим выполнения в памяти).

Предварительно консервированный PCollection Источники ( TFXIO )

RecordBatch формат , что наша реализация принимает общий формат , что и другие библиотеки TFX принять. Поэтому TFX предлагает удобный «источники» (ака TFXIO ) , которые считывают файлы различных форматов на диск и производить RecordBatch эс , а также может дать TensorAdapterConfig , в том числе выведенных TensorRepresentations .

Те TFXIO s можно найти в пакете tfx_bsl ( tfx_bsl.public.tfxio ).

Пример: набор данных «Доход переписи»

Следующий пример требует чтения и записи данных на диске и представляющий данные в виде PCollection (не список), см: census_example.py . Ниже мы покажем, как загрузить данные и запустить этот пример. Набор данных «Перепись Доход» обеспечивается UCI Machine Learning Repository . Этот набор данных содержит как категориальные, так и числовые данные.

Данные в формате CSV, вот первые две строки:

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

Столбцы набора данных могут быть категориальными или числовыми. Этот набор данных описывает проблему классификации: прогнозирование последнего столбца, в котором человек зарабатывает больше или меньше 50 тысяч в год. Однако, с точки зрения tf.Transform , эта метка просто еще один категорический столбец.

Мы используем Предварительно консервированный TFXIO , BeamRecordCsvTFXIO переводить строки в CSV RecordBatches . TFXIO требует два важной части информации:

  • TensorFlow метаданные схема , который содержит тип и форму информации о каждом столбце CSV. TensorRepresentation ы является дополнительной частью схемы; если они не предоставлены (что имеет место в этом примере), они будут выведены из информации о типе и форме. Можно получить схему либо с помощью вспомогательной функции мы обеспечиваем перевод с спецификации TF разбором (показано в этом примере), или запустив TensorFlow Data Validation .

  • список имен столбцов в порядке их появления в CSV-файле. Обратите внимание, что эти имена должны совпадать с именами функций в схеме.

В этом примере мы разрешаем education-num функция будет отсутствовать. Это означает , что оно представлено в виде tf.io.VarLenFeature в feature_spec, и как tf.SparseTensor в preprocessing_fn . Другие признаки станут tf.Tensor с тем же именем в 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()

. Обратите внимание , что мы должны были сделать некоторые дополнительные починки окна после того , CSV строки считываются в противном случае, мы могли бы рассчитывать на CsvTFXIO обрабатывать как чтение файлов и перевод на RecordBatch эс:

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()

Предварительная обработка аналогична предыдущему примеру, за исключением того, что функция предварительной обработки генерируется программно, а не задается вручную для каждого столбца. В предварительной обработки функции ниже, NUMERICAL_COLUMNS и CATEGORICAL_COLUMNS списки, содержащие имена числовых и категориальных столбцов:

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

Одним из отличий от предыдущего примера является то, что в столбце метки вручную указывается сопоставление строки с индексом. Так '>50' отображаются на 0 и '<=50K' отображается на 1 , потому что это полезно знать , какой индекс в тренированной модели соответствует которой этикетке.

record_batches переменная представляет собой PCollection из pyarrow.RecordBatch х годов. tensor_adapter_config дается csv_tfxio , который выводится из SCHEMA (и , в конечном счете, в этом примере, от синтаксического анализа TF спецификации).

Заключительный этап заключается в записи преобразованных данных на диск и имеет форму, аналогичную чтению необработанных данных. Схема , используемая для этого является частью вывода AnalyzeAndTransformDataset , который выводит схему для вывода данных. Код для записи на диск показан ниже. Схема является частью метаданных , но использует два взаимозаменяемые в tf.Transform API (т.е. передать метаданные в ExampleProtoCoder ). Имейте в виду, что это записывает в другой формат. Вместо textio.WriteToText , использовать Beam встроенной поддержки для TFRecord формата и использовать кодер для кодирования данных в виде Example Протоса. Этот формат лучше использовать для обучения, как показано в следующем разделе. transformed_eval_data_base обеспечивает базовое имя для отдельных осколков, которые написаны.

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

В дополнение к подготовке данных, transform_fn также выписаны с метаданными:

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

Выполнить весь трубопровод Beam с p.run().wait_until_finish() . До этого момента конвейер Beam представлял собой отложенные распределенные вычисления. Он предоставляет инструкции о том, что будет сделано, но инструкции не были выполнены. Этот последний вызов выполняет указанный конвейер.

Скачать набор данных переписи

Загрузите набор данных переписи, используя следующие команды оболочки:

  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

При запуске census_example.py сценария, передайте каталог , содержащий эти данные в качестве первого аргумента. Сценарий создает временный подкаталог для добавления предварительно обработанных данных.

Интеграция с обучением TensorFlow

В заключительном разделе census_example.py показывают , как препроцессированный данных используется для обучения модели. Смотрите документацию оценщиков для деталей. Первый шаг состоит в построении Estimator , который требует описаний предварительно обработанных колонн. Каждый числовой столбец описывается как real_valued_column , который является оболочкой вокруг плотного вектора с фиксированным размером ( 1 в этом примере). Каждый категоричен столбец отображается из строки в целые , а затем получает передается в indicator_column . tft.TFTransformOutput используется , чтобы найти путь к файлу словаря для каждого категориального признака.

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)

Следующим шагом является создание построителя для создания входной функции для обучения и оценки. В отличается от обучения , используемого tf.Learn поскольку особенность спецификации не требуется для анализа преобразованных данных. Вместо этого используйте метаданные преобразованных данных для создания спецификации функции.

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

Остальной код такой же , как с помощью Estimator класса. В примере также содержит код для экспорта модели в SavedModel формате. Экспортировали модель может быть использована Tensorflow сервировка или Cloud ML Engine .