Создание пользовательских оценок в TensorFlow

машинное обучение искусственный интеллект TensorFlow
Создание пользовательских оценок в TensorFlow
БытьАвтор: команда TensorFlow

Добро пожаловать в третью часть серии блогов, посвященных наборам данных и оценкам TensorFlow.часть 1Выделение предварительно сделанных оценщиков,часть 2Обсуждаются столбцы функций. в сегодняшних В части 3 вы узнаете, как создать пользовательскую оценку. Особо следует отметить, что мы продемонстрируем, как создать имитацию при решении задачи с радужной оболочкой.DNNClassifierПользовательский оценщик поведения.

Если вам не терпится, сравните полную программу ниже:
  • здесь— это исходный код для предсказания радужной оболочки глаза, реализованный предварительно созданным оценщиком DNNClassifier.
  • здесь— это исходный код для прогнозирования радужной оболочки, реализованный с помощью пользовательского оценщика.

Сборные против пользовательских


Как показано на рисунке 1, предварительно сделанная оценкаtf.estimator.Estimatorподкласс базового класса, а пользовательская оценкаtf.estimator.Estimator:создание экземпляра

Рисунок 1. Как готовые, так и пользовательские оценщики являются оценщиками.


Готовые оценщикиЭто полностью готовый продукт. Но иногда вам нужно больше контролировать поведение оценщика. Появились пользовательские оценщики.

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

модельная функция (model_fn) для реализации вашей модели. Единственная разница между использованием готового оценщика и пользовательского оценщика заключается в следующем:
  • При использовании готовых оценок кто-то уже написал для вас функцию модели.
  • Принимая во внимание, что с пользовательским оценщиком вы должны написать функцию модели самостоятельно.

Ваша модельная функция может реализовывать различные алгоритмы, определять различные скрытые слои и метрики. Как и входные функции, все функции модели должны принимать набор стандартных входных параметров и возвращать набор стандартных выходных значений. Входные параметры могут использовать API набора данных, а функции модели могут использовать API слоев и API метрик.

Внедрение радужной оболочки глаза в качестве готового оценщика: краткое напоминание


Прежде чем продемонстрировать, как реализовать радужную оболочку в качестве пользовательской оценки, вспомните, что мычасть 1так реализуется Iris в виде готового оценщика. В части 1 мы просто создали полностью подключенныйглубинанейронная сеть, объединивГотовые оценщикиСоздайте экземпляр следующим образом:
# Instantiate a deep neural network classifier.
classifier = tf.estimator.DNNClassifier(
   feature_columns=feature_columns, # The input features to our model.
   hidden_units=[10, 10], # Two layers, each with 10 neurons.
   n_classes=3, # The number of output classes (three Iris species).
   model_dir=PATH) # Pathname of directory where checkpoints, etc. are stored.

Приведенный выше код создает глубокую нейронную сеть со следующими характеристиками:
  • Список характеристических столбцов. (Определение столбца признаков не показано во фрагменте кода выше.) Для радужной оболочки столбец признаков представляет собой числовое представление четырех входных признаков.
  • Два полносвязных слоя по 10 нейронов в каждом.полносвязный слой(также известен какплотный слой) подключен к каждому нейрону в последующем слое.
  • Выходной слой состоит из трехэлементного списка. Все элементы в этом списке являются значениями с плавающей запятой, значения должны в сумме давать 1,0 (это распределение вероятностей).
  • Каталог, который будет использоваться для хранения обученной модели и отдельных контрольных точек (PATH).

На рис. 2 показаны входной, скрытый и выходной слои модели Iris. Для ясности мы рисуем только 4 узла в каждом скрытом слое.

Рисунок 2. Наша реализация Iris содержит четыре функции, два скрытых слоя и выходной логит-слой.


Давайте посмотрим, как решить ту же проблему с радужной оболочкой, используя пользовательскую оценку.

входная функция


Одним из самых больших преимуществ платформы оценки является то, что вы можете экспериментировать с различными алгоритмами, не меняя конвейер данных. Поэтому будем повторно использоватьчасть 1Большое количество входных функций в:
def my_input_fn(file_path, repeat_count=1, shuffle_count=1):
   def decode_csv(line):
       parsed_line = tf.decode_csv(line, [[0.], [0.], [0.], [0.], [0]])
       label = parsed_line[-1]  # Last element is the label
       del parsed_line[-1]  # Delete last element
       features = parsed_line  # Everything but last elements are the features
       d = dict(zip(feature_names, features)), label
       return d

   dataset = (tf.data.TextLineDataset(file_path)  # Read text file
       .skip(1)  # Skip header row
       .map(decode_csv, num_parallel_calls=4)  # Decode each line
       .cache() # Warning: Caches entire dataset, can cause out of memory
       .shuffle(shuffle_count)  # Randomize elems (1 == no operation)
       .repeat(repeat_count)    # Repeats dataset this # times
       .batch(32)
       .prefetch(1)  # Make sure you always have 1 batch ready to serve
   )
   iterator = dataset.make_one_shot_iterator()
   batch_features, batch_labels = iterator.get_next()
   return batch_features, batch_labels

Обратите внимание, что функция ввода возвращает следующие два значения:
  • batch_features, это словарь. Ключи этого словаря — это имена функций, а значения — значения функции.
  • batch_labels, представляет собой список значений меток для пакетной обработки.

Полную информацию о функциях ввода см.часть 1.

Создать столбцы функций


Как в этой сериичасть 2Чтобы уточнить, вы должны определить столбцы функций модели, чтобы указать представление каждой функции. Столбцы функций определяются одинаково, независимо от того, используете ли вы готовую или пользовательскую оценку. Например, следующий код создает столбцы функций, представляющие четыре функции (все числовые) в наборе данных радужной оболочки:
feature_columns = [
   tf.feature_column.numeric_column(feature_names[0]),
   tf.feature_column.numeric_column(feature_names[1]),
   tf.feature_column.numeric_column(feature_names[2]),
   tf.feature_column.numeric_column(feature_names[3])
]

Напишите функции модели


Теперь мы готовы написать для пользовательского оценщикаmodel_fn. Сначала объявление функции:
def my_model_fn(
   features, # This is batch_features from input_fn
   labels,   # This is batch_labels from input_fn
   mode):    # Instance of tf.estimator.ModeKeys, see below

Первые два аргумента — это функции и метки, возвращаемые входной функцией, то естьfeaturesиlabelsэто дескриптор данных, который будет использоваться моделью.modeПараметр указывает, запрашивает ли вызывающий объект обучение, прогнозирование или оценку.

Для реализации типовой функции модели необходимо сделать следующее:
  • Определите слои модели.
  • Определяет поведение модели в трех разных режимах.

Определение слоев модели


Если ваш пользовательский оценщик генерирует глубокую нейронную сеть, вы должны определить следующие три слоя:
  • входной слой
  • один или несколько скрытых слоев
  • выходной слой

Используйте API слоев (tf.layers), чтобы определить скрытый и выходной слои.

Если пользовательский оценщик создает линейную модель, ему нужно создать только один слой, который мы рассмотрим в следующем разделе.

Определите входной слой


перечислитьtf.feature_column.input_layer, который определяет входной слой для глубокой нейронной сети. Например:
# Create the layer of input
input_layer = tf.feature_column.input_layer(features, feature_columns)

Приведенная выше строка кода создаст входной слой и прочитает его через функцию ввода.features, и передать ранее определенноеfeature_columnsфильтровать их. Чтобы узнать больше о различных способах представления данных с помощью столбцов функций, см.часть 2.

Чтобы создать входной слой для линейной модели, вызовитеtf.feature_column.linear_model, вместоtf.feature_column.input_layer. Поскольку в линейной модели нет скрытых слоев, изtf.feature_column.linear_modelВозвращенное значение будет использоваться как входной слой и выходной слой. То есть значение, возвращаемое этой функциейдапредсказывать.

построить скрытый слой


Если вы хотите создать глубокую нейронную сеть, вы должны определить один или несколько скрытых слоев. Layers API имеет богатые функции для определения всех типов скрытых слоев, включая сверточные слои, объединяющие слои и выпадающие слои. Для радужной оболочки мы просто вызываем дваждыtf.layers.Denseдля создания двух плотных скрытых слоев по 10 нейронов в каждом. «Плотный» означает, что каждый нейрон в первом скрытом слое связан с каждым нейроном во втором скрытом слое. Вот соответствующий код:
# Definition of hidden layer: h1
# (Dense returns a Callable so we can provide input_layer as argument to it)
h1 = tf.layers.Dense(10, activation=tf.nn.relu)(input_layer)

# Definition of hidden layer: h2
# (Dense returns a Callable so we can provide h1 as argument to it)
h2 = tf.layers.Dense(10, activation=tf.nn.relu)(h1)

tf.layers.Denseизinputsидентификатор параметрафронтЭтаж. родыh1Предыдущий слой является входным слоем.

Рисунок 3. Входной слой переходит в скрытый слой 1.

h2Передний слой этоh1. Таким образом, объединение этих слоев выглядит так, как показано на изображении ниже:

Рисунок 4. Скрытый слой 1 переходит в скрытый слой 2.

tf.layers.DenseПервый параметр определяет количество его выходных нейронов - здесь 10.

activationПараметры определяют функцию активации - вот онаRelu.

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

выходной слой


мы звоним сноваtf.layers.Denseчтобы определить выходной слой:
# Output 'logits' layer is three numbers = probability distribution
# (Dense returns a Callable so we can provide h2 as argument to it)
logits = tf.layers.Dense(3)(h2)

Обратите внимание, что выходной слой начинается сh2получить его ввод. Таким образом, все слои теперь связаны, как показано ниже:

Рисунок 5. Скрытый слой 2 подается в выходной слой.

При определении выходного слояunitsПараметр указывает количество возможных выходных значений. Следовательно, будетunitsУстановить как3Задний,tf.layers.DenseФункция создает трехэлементный вектор логитов. Каждая ячейка логитс-вектора содержит вероятность того, что радужка является горной, разноцветной или виргинской.

Поскольку выходной слой является последним слоем, поэтомуtf.layers.Denseвызов игнорирует необязательныйactivationпараметр.

Внедрение обучения, оценки и прогнозирования


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

когда кто-то звонит оценщикуtrain,evaluateилиpredictфункция, вызывается модельная функция. Напомним, что характеристики модельной функции выглядят так:
def my_model_fn(
   features, # This is batch_features from input_fn
   labels,   # This is batch_labels from input_fn
   mode):    # Instance of tf.estimator.ModeKeys, see below

Обратите внимание на третий параметрmode. Как показано в таблице ниже, когда кто-то звонитtrain,evaluateилиpredict, система оценки вызовет функцию модели, котораяmode parameterНастройки следующие:

Таблица 2. Значения для режима.

Вызывающий вызывает пользовательскую функцию оценки... Платформа оценки вызывает функцию модели, котораяmodeПараметры настроены...
train() ModeKeys.TRAIN
evaluate() ModeKeys.EVAL
predict() ModeKeys.PREDICT

Например, предположим, что вы создаете экземпляр пользовательского оценщика для созданияclassifierОбъект. Затем сделайте следующий вызов (пока не беспокойтесь об этом)my_input_fnпараметры):
classifier.train(
  input_fn=lambda: my_input_fn(FILE_TRAIN, repeat_count=500, shuffle_count=256))

Затем оценочная структура вызываетmodelфункционировать и будетmodeУстановить какModeKeys.TRAIN.

Функция модели должна предоставлять код для обработки всех трехmodeценность. Для каждого значения режима ваш код должен возвращатьtf.estimator.EstimatorSpec, который содержит информацию, необходимую вызывающему абоненту. Разберем каждый режим.

PREDICT


использоватьmode == ModeKeys.PREDICTперечислитьmodel_fn, функция модели должна возвращатьtf.estimator.EstimatorSpec:
  • режим, то естьtf.estimator.ModeKeys.PREDICT
  • предсказывать

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

В нашем примере код для генерации прогнозов выглядит так:
# class_ids will be the model prediction for the class (Iris flower type)
# The output node with the highest value is our prediction
predictions = { 'class_ids': tf.argmax(input=logits, axis=1) }

# Return our prediction
if mode == tf.estimator.ModeKeys.PREDICT:
   return tf.estimator.EstimatorSpec(mode, predictions=predictions)



Блоки кода на удивление просты — строки кода подобны ведру на конце длинной трубы, ожидая, пока не попадут предсказания. В конце концов, оценщик уже сделал всю тяжелую работу по прогнозированию:
  1. Функция ввода предоставляет функции модели данные (собственные значения) для вывода.
  2. Функция модели превращает эти значения признаков в столбцы признаков.
  3. Функция модели запускает эти столбцы функций через ранее обученную модель.

Выходной слойlogitsВектор, содержащий каждое из трех значений для вида ириса в качестве входного цветка.tf.argmaxфункция выберетlogitsвекторное значениемаксимумвиды ириса.

Обратите внимание, что наибольшее значение присвоеноclass_idsключ словаря. мы проходимtf.estimator.EstimatorSpecПараметр предсказания возврата этого словаря. Затем вызывающий абонент может проверить возвращенную оценку.predictСловарь функций для получения прогнозов.

EVAL


использоватьmode == ModeKeys.EVALперечислитьmodel_fn, функция модели должна оценивать модель, возвращая потери и даже одну или несколько метрик.

мы можем позвонитьtf.losses.sparse_softmax_cross_entropyдля расчета убытка. Вот полный код:
# To calculate the loss, we need to convert our labels
# Our input labels have shape: [batch_size, 1]
labels = tf.squeeze(labels, 1)          # Convert to shape [batch_size]
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

Теперь обратим внимание на индикаторы. Хотя возвращать метрики необязательно, большинство пользовательских оценщиков возвращают хотя бы одну метрику. TensorFlow предоставляет API метрик (tf.metrics) для расчета различных типов метрик. Для краткости мы возвращаем только точность.tf.metrics.accuracyСравните прогнозы с «истинными метками» (то есть метками, предоставленными входной функцией).tf.metrics.accuracyФункция требует, чтобы метки и прогнозы имели одинаковую форму (что мы и сделали ранее). звоните нижеtf.metrics.accuracy:
# Calculate the accuracy between the true labels, and our predictions
accuracy = tf.metrics.accuracy(labels, predictions['class_ids'])

использоватьmode == ModeKeys.EVALКогда модель вызывается, функция модели возвращаетtf.estimator.EstimatorSpec:
  • mode,Сейчасtf.estimator.ModeKeys.EVAL
  • потеря модели
  • Одна или несколько метрик, обычно содержащихся в словаре.

Поэтому мы создадим индекс, содержащий уникальные метрики (my_accuracy) Словарь. Если бы мы рассчитывали другие метрики, их следовало бы добавить в тот же словарь в качестве дополнительных пар ключ-значение. Тогда мыtf.estimator.EstimatorSpecизeval_metric_opsСловарь передается в параметре. Вот блок кода:
# Return our loss (which is used to evaluate our model)
# Set the TensorBoard scalar my_accurace to the accuracy
# Obs: This function only sets value during mode == ModeKeys.EVAL
# To set values during training, see tf.summary.scalar
if mode == tf.estimator.ModeKeys.EVAL:
   return tf.estimator.EstimatorSpec(
       mode,
       loss=loss,
       eval_metric_ops={'my_accuracy': accuracy})

TRAIN


использоватьmode == ModeKeys.TRAINперечислитьmodel_fn, функция модели должна обучать модель.

Сначала мы должны создать экземпляр объекта оптимизатора. Мы выбрали Adagrad из следующего блока кода (tf.train.AdagradOptimizer), только потому, что мы подражалиDNNClassifierТакже используйте Адаград.tf.trainПакет предоставляет множество других оптимизаторов — экспериментируйте.

Затем мы обучаем модель, устанавливая цель оптимизатора, чтобы минимизировать егоloss. Чтобы установить эту цель, мы вызовемminimizeфункция.

В приведенном ниже коде необязательныйglobal_stepПараметры указывают TensorFlow Переменная, используемая для подсчета количества обработанных пакетов. будетglobal_stepУстановить какtf.train.get_global_stepработает отлично. Кроме того, мы позвонимtf.summary.scalar, во время обучения Отчет TensorBoardmy_accuracy. Для получения дополнительных инструкций см. раздел TensorBoard ниже.
optimizer = tf.train.AdagradOptimizer(0.05)
train_op = optimizer.minimize(
   loss,
   global_step=tf.train.get_global_step())

# Set the TensorBoard scalar my_accuracy to the accuracy
tf.summary.scalar('my_accuracy', accuracy[1])

использоватьmode == ModeKeys.TRAINПри вызове модели функция модели должна возвращатьtf.estimator.EstimatorSpec:
  • режим, то естьtf.estimator.ModeKeys.TRAIN
  • потеря
  • результат тренировочной операции

Вот код:
# Return training operations: loss and train_op
return tf.estimator.EstimatorSpec(
   mode,
   loss=loss,
   train_op=train_op)

Функция модели теперь завершена!

пользовательский оценщик


После того, как вы создадите новый пользовательский оценок, вы захотите его использовать. во-первых

пройти черезEstimatorБазовый класс создает экземпляр пользовательской оценки следующим образом:
classifier = tf.estimator.Estimator(
   model_fn=my_model_fn,
   model_dir=PATH)  # Path to where checkpoints etc are stored

Далее следует остальная часть кода для обучения, оценки и прогнозирования с использованием нашего оценщика.часть 1Представляем сборныеDNNClassifierТакой же. Например, следующая строка кода запустит обучение модели:
classifier.train(
  input_fn=lambda: my_input_fn(FILE_TRAIN, repeat_count=500, shuffle_count=256))

TensorBoard


рисунокчасть 1Точно так же мы можем просматривать результаты обучения в TensorBoard. Чтобы просмотреть этот отчет, запустите TensorBoard из командной строки следующим образом:
# Replace PATH with the actual path passed as model_dir
tensorboard --logdir=PATH 

Затем перейдите по следующему URL-адресу:
localhost:6006 

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

Рисунок 6. TensorBoard отображает три графика.

Вкратце, эти три графика могут сказать вам следующее:
  • global_step/sec: показатель производительности, показывающий, сколько пакетов (ось Y, градиентные обновления) мы обрабатываем в секунду в конкретном пакете (ось X). Для просмотра этого отчета необходимо предоставитьglobal_step(например, использованиеtf.train.get_global_step()то же время). также требует обучения, которое выполняется достаточно долго, поэтому мы просим оценщика обучить его, когда мы вызываем его обучающую функцию. 500 циклов:
    • loss: Заявленная потеря. Фактическое значение потерь (ось Y) не имеет особого смысла. Форма диаграммы имеет большое значение.
  • my_accuracy: Точность зафиксирована при вызове следующей функции:
  • eval_metric_ops={'my_accuracy': accuracy}),существуетEVALпериод (вернемся к нашемуEstimatorSpecВремя)
  • tf.summary.scalar('my_accuracy', accuracy[1]),существуетTRAINпериод

Уведомлениеmy_accuracyиlossНа графике следующая информация:
  • Оранжевая линия указываетTRAIN.
  • синие точки представляютEVAL.

существуетTRAINВ то же время оранжевые значения постоянно записываются по мере обработки пакета, поэтому диаграмма охватывает диапазон оси X. Напротив,EVALПри обработке всех шагов оценки генерируется только одно значение.

Следуя подсказкам на рис. 7, вы можете просматривать и при необходимости отключать/включать отчеты об обучении и оценке слева. (На рис. 7 показано, что мы сохранили отчет для обоих.)

Рисунок 7. Включение или отключение отчетов.

Чтобы увидеть оранжевую диаграмму, необходимо указать глобальный шаг. комбинироватьglobal_steps/secотчет, становится лучшей практикой регистрировать глобальные шаги в любое время, просто добавляяtf.train.get_global_step()передается как параметр вoptimizer.minimizeПросто позвони.

Суммировать


Хотя готовые оценщики могут быть эффективным способом быстрого создания новых моделей, вам часто требуется большая гибкость пользовательских оценщиков. К счастью, готовые и пользовательские оценщики следуют одной и той же модели программирования. Единственное практическое отличие состоит в том, что вам нужно написать функцию модели для вашего пользовательского оценщика, все остальное то же самое!

Дополнительные сведения см. в ресурсах ниже:
  • Полная версия этого сообщения в блогеисходный код.
  • Официальная реализация TensorFlow MNIST, используя пользовательскую оценку. Эта модель также является примером, в котором мы используем необработанные пиксели в качестве числовых значений вместо столбцов функций (иinput_layer).
  • TensorFlow Официальная библиотека моделей, который может содержать дополнительные вводные примеры и использовать пользовательские оценки.
  • на саммите разработчиков TensorFlowTensorboard видео, представляет TensorBoard в увлекательной и познавательной форме.

Всем удачного кодирования TensorFlow, до встречи в следующий раз!