Как построить различные суммарные показатели на одном графике с помощью Tensorboard?

Я хотел бы иметь возможность составить график потерь обучения на партию и средней потери проверки для проверки, установленной на том же графике в Tensorboard. Я столкнулся с этой проблемой, когда мой набор проверки был слишком большим, чтобы поместиться в памяти, поэтому требовались пакетная обработка и использование tf.metrics обновить опс.

Этот вопрос может относиться к любым метрикам Tensorflow, которые вы хотите отобразить на том же графике в Tensorboard.

я смогу

  • построить эти два графика отдельно (см. здесь)
  • нанесите на карту график проверки потерь-на-проверку-проверки на том же графике, что и на тренировку-потери-на-тренировку (это было нормально, когда набор проверки мог быть одной партией, и я мог повторно использовать операционную сводку обучения train_summ ниже)

В приведенном ниже примере кода моя проблема связана с тем, что мое резюме проверки tf.summary.scalar с name=loss переименовывается в loss_1 и таким образом перемещается в отдельный граф в Tensorboard. Из того, что я могу понять, Tensorboard берет "одно и то же имя" и отображает их на одном графике, независимо от того, в какой папке они находятся. train_summ (имя = потеря) записывается только в train папка и valid_summ (имя = потеря) записывается только в valid папка - но все еще переименована в loss_1,

Пример кода:

# View graphs with (Linux): $ tensorboard --logdir=/tmp/my_tf_model

import tensorflow as tf
import numpy as np
import os
import tempfile

def train_data_gen():
    yield np.random.normal(size=[3]), np.array([0.5, 0.5, 0.5])

def valid_data_gen():
    yield np.random.normal(size=[3]), np.array([0.8, 0.8, 0.8])

batch_size = 25
n_training_batches = 4
n_valid_batches = 2
n_epochs = 5
summary_loc = os.path.join(tempfile.gettempdir(), 'my_tf_model')
print("Summaries written to" + summary_loc)

# Dummy data
train_data = tf.data.Dataset.from_generator(train_data_gen, (tf.float32, tf.float32)).repeat().batch(batch_size)
valid_data = tf.data.Dataset.from_generator(valid_data_gen, (tf.float32, tf.float32)).repeat().batch(batch_size)
handle = tf.placeholder(tf.string, shape=[])
iterator = tf.data.Iterator.from_string_handle(handle, 
train_data.output_types, train_data.output_shapes)
batch_x, batch_y = iterator.get_next()
train_iter = train_data.make_initializable_iterator()
valid_iter = valid_data.make_initializable_iterator()

# Some ops on the data
loss = tf.losses.mean_squared_error(batch_x, batch_y)
valid_loss, valid_loss_update = tf.metrics.mean(loss)

# Write to summaries
train_summ = tf.summary.scalar('loss', loss)
valid_summ = tf.summary.scalar('loss', valid_loss)  # <- will be renamed to "loss_1"

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    train_handle, valid_handle = sess.run([train_iter.string_handle(), valid_iter.string_handle()])
    sess.run([train_iter.initializer, valid_iter.initializer])

    # Summary writers
    writer_train = tf.summary.FileWriter(os.path.join(summary_loc, 'train'), sess.graph)
    writer_valid = tf.summary.FileWriter(os.path.join(summary_loc, 'valid'), sess.graph)

    global_step = 0  # implicit as no actual training
    for i in range(n_epochs):
        # "Training"
        for j in range(n_training_batches):
            global_step += 1
            summ = sess.run(train_summ, feed_dict={handle: train_handle})
            writer_train.add_summary(summary=summ, global_step=global_step)
        # "Validation"
        sess.run(tf.local_variables_initializer())
        for j in range(n_valid_batches):
             _, batch_summ = sess.run([valid_loss_update, train_summ], feed_dict={handle: valid_handle})
            # The following will plot the batch loss for the validation set on the loss plot with the training data:
            # writer_valid.add_summary(summary=batch_summ, global_step=global_step + j + 1)
        summ = sess.run(valid_summ)
        writer_valid.add_summary(summary=summ, global_step=global_step)  # <- I want this on the training loss graph

Что я пробовал

  • отдельный tf.summary.FileWriter объекты (один для обучения, один для проверки), как рекомендовано в этой проблеме и в этом вопросе (подумайте, на что я ссылаюсь в комментарии к этому вопросу)
  • Использование tf.summary.merge объединить все мои показатели обучения и валидации / тестирования в общую сводку операций; делает полезный бухгалтерский учет, но не отображает то, что я хочу, на том же графике
  • Использование tf.summary.scalarfamily атрибут (loss все еще переименовывается в loss_1)
  • (Полное решение взлома) Использование valid_loss, valid_loss_update = tf.metrics.mean(loss) на тренировочных данных, а затем запустить tf.local_variables_initializer() каждая тренировочная партия. Это дает вам ту же сводную опцию и, таким образом, помещает вещи в один и тот же график, но, конечно же, вы не должны этого делать? Это также не обобщает другие метрики.

контекст

  • Tensorflow 1.9.0
  • Тензорборд 1.9.0
  • Python 3.5.2

1 ответ

Решение

Тензорная доска custom_scalar Плагин это способ решить эту проблему.

Вот тот же пример снова с custom_scalar построить две потери (для каждой обучающей партии + усредненные по всем проверочным партиям) на одном графике:

# View graphs with (Linux): $ tensorboard --logdir=/tmp/my_tf_model

import os
import tempfile
import tensorflow as tf
import numpy as np
from tensorboard import summary as summary_lib
from tensorboard.plugins.custom_scalar import layout_pb2

def train_data_gen():
    yield np.random.normal(size=[3]), np.array([0.5, 0.5, 0.5])

def valid_data_gen():
    yield np.random.normal(size=[3]), np.array([0.8, 0.8, 0.8])

batch_size = 25
n_training_batches = 4
n_valid_batches = 2
n_epochs = 5
summary_loc = os.path.join(tempfile.gettempdir(), 'my_tf_model')
print("Summaries written to " + summary_loc)

# Dummy data
train_data = tf.data.Dataset.from_generator(
    train_data_gen, (tf.float32, tf.float32)).repeat().batch(batch_size)
valid_data = tf.data.Dataset.from_generator(
    valid_data_gen, (tf.float32, tf.float32)).repeat().batch(batch_size)
handle = tf.placeholder(tf.string, shape=[])
iterator = tf.data.Iterator.from_string_handle(handle, train_data.output_types,
                                               train_data.output_shapes)
batch_x, batch_y = iterator.get_next()
train_iter = train_data.make_initializable_iterator()
valid_iter = valid_data.make_initializable_iterator()

# Some ops on the data
loss = tf.losses.mean_squared_error(batch_x, batch_y)
valid_loss, valid_loss_update = tf.metrics.mean(loss)

with tf.name_scope('loss'):
    train_summ = summary_lib.scalar('training', loss)
    valid_summ = summary_lib.scalar('valid', valid_loss)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    train_handle, valid_handle = sess.run([train_iter.string_handle(), valid_iter.string_handle()])
    sess.run([train_iter.initializer, valid_iter.initializer])

    writer_train = tf.summary.FileWriter(os.path.join(summary_loc, 'train'), sess.graph)
    writer_valid = tf.summary.FileWriter(os.path.join(summary_loc, 'valid'), sess.graph)

    layout_summary = summary_lib.custom_scalar_pb(
        layout_pb2.Layout(category=[
            layout_pb2.Category(
                title='losses',
                chart=[
                    layout_pb2.Chart(
                        title='losses',
                        multiline=layout_pb2.MultilineChartContent(tag=[
                            'loss/training', 'loss/valid'
                        ]))
                ])
        ]))
    writer_train.add_summary(layout_summary)

    global_step = 0
    for i in range(n_epochs):
        for j in range(n_training_batches): # "Training"
            global_step += 1
            summ = sess.run(train_summ, feed_dict={handle: train_handle})
            writer_train.add_summary(summary=summ, global_step=global_step)

        sess.run(tf.local_variables_initializer())
        for j in range(n_valid_batches):  # "Validation"
            _, batch_summ = sess.run([valid_loss_update, train_summ], feed_dict={handle: valid_handle})
        summ = sess.run(valid_summ)
        writer_valid.add_summary(summary=summ, global_step=global_step)

Вот результирующий вывод в Tensorboard.

Другие вопросы по тегам