title: How to plot different summary metrics on the same plot with Tensorboard?
body: <p>I would like to be able plot the <strong>training loss per batch</strong> and the <strong><em>average</em> validation loss</strong> for the validation set on the same plot in Tensorboard. I ran into this issue when my validation set was too large to fit into memory so required batching and the use of <code>tf.metrics</code> update ops. </p>
  
  <p>This question could apply to any Tensorflow metrics you wanted to appear on the same graph in Tensorboard.</p>
  
  <p>I am able to</p>
  
  <ul>
  <li>plot these two graphs separately (see <a href="https://i.stack.imgur.com/o3fLM.png" rel="nofollow noreferrer">here</a>)</li>
  <li>plot the <em>validation-loss-per-validation-batch</em> on the same graph as the <em>training-loss-per-training-batch</em> (this was OK when the validation set could be a single batch and I could reuse the training summary op <code>train_summ</code> below)</li>
  </ul>
  
  <p>In the example code below, my issue stems from the fact that my validation summary <code>tf.summary.scalar</code> with <code>name=loss</code> gets renamed to <code>loss_1</code> and thus is moved to a separate graph in Tensorboard. From what I can work out Tensorboard takes <em>"same name"</em> and plots them on the same graph, regardless of what folder they are in. This is frustrating as <code>train_summ</code> (name=loss) is only ever written to the <code>train</code> folder and <code>valid_summ</code> (name=loss) is only ever written to the <code>valid</code> folder - but is still renamed to <code>loss_1</code>.</p>
  
  <p>The example code:</p>
  
  <pre><code># 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)  # &lt;- 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)  # &lt;- I want this on the training loss graph
  </code></pre>
  
  <h2>What I have tried</h2>
  
  <ul>
  <li>Separate <code>tf.summary.FileWriter</code> objects (one for training, one for validation), as recommended by <a href="https://github.com/tensorflow/tensorflow/issues/7089" rel="nofollow noreferrer">this issue</a> and <a href="https://stackoverflow.com/questions/48951136/plot-multiple-graphs-in-one-plot-using-tensorboard?rq=1">this question</a> (think what I'm after is alluded to in the comment of that question) </li>
  <li>The use of <code>tf.summary.merge</code> to merge all my training and validation/test metrics into overall summary ops; does useful book-keeping but doesn't plot what I want on the same graph</li>
  <li>Use of the <code>tf.summary.scalar</code> <code>family</code> attribute (<code>loss</code> still gets renamed to <code>loss_1</code>)</li>
  <li><strong>(Complete hack solution)</strong> Use <code>valid_loss, valid_loss_update = tf.metrics.mean(loss)</code> on the <em>training</em> data and then run <code>tf.local_variables_initializer()</code> every training batch. This does give you the same summary op and thus puts things on the same graph but is surely not how you're <em>meant</em> to do this? It also doesn't generalise to other metrics.</li>
  </ul>
  
  <h2>Context</h2>
  
  <ul>
  <li>Tensorflow 1.9.0</li>
  <li>Tensorboard 1.9.0</li>
  <li>Python 3.5.2</li>
  </ul>