Following the announcement in Tensorflow Dev Summit 2018 in Eager Execution part: https://www.youtube.com/watch?v=T8AW0fKP0Hs&vl=en

It suggests that we should use tf.contrib.summary . Here is the link to the documentation https://www.tensorflow.org/api_docs/python/tf/contrib/summary

To me, it is not a very good documentation and hard to follow. I have here some example codes to guide you to the new summary API.

I will try to cover both modes, eager and graph. I shall stick with the graph mode and then add some notes for the eager mode.

Overall code template will be put at the end of this article.

### Creating the summary writer

This is the same with both graph mode and eager mode.

Since the new summary API is very context based, I think it is a good practice to separate graph for each summary writer.

Initializing the summary:

import tensorflow as tf
save_path = 'logs'
graph = tf.Graph()
with graph.as_default():
global_step = tf.train.create_global_step()
writer = tf.contrib.summary.create_file_writer(save_path)
with writer.as_default():
tf.contrib.summary.always_record_summaries()


Now, we have graph and writer .

Note: I usually also create a global_step with the creation of graph. Which is very convenient because the summary writer will automatically utilize it. You don’t really need to keep the global_step though, you can always get it from tf.train.get_global_step() given that you properly set the default graph.

### Preparing the dataset and creating the model

This is not the main topic of this article though, but for the sake of expressiveness I found it useful for explanation.

First we prepare the dataset, I will demonstrate with tf.data.Dataset here.

with graph.as_default():
# dataset
data = ... some tf.data.Dataset ...
data_itr = data.make_initializable_iterator()
x, y = data_itr.get_next() # x is feature, y is label


Note that in eager mode you don’t need the make_initializable_iterator()because the dataset is itself iterable. That means in eager you don’t need get_next() as well.

#### At the time we define model, we add something to summary

The following code is in graph mode:

with graph.as_default():
with writer.as_default():
# let's say we have "net" as our model
prediction_op = net(x)
loss_op = tf.losses.sparse_softmax_cross_entropy(y, prediction_op)
loss_op,
global_step=tf.train.get_global_step())

with tf.contrib.summary.record_summaries_every_n_global_steps(1):
tf.contrib.summary.scalar('loss', loss_op)

summary_op = tf.contrib.summary.all_summary_ops()


You see that we use tf.contrib.summary.record_summaries_every_n_global_steps (https://www.tensorflow.org/api_docs/python/tf/contrib/summary/record_summaries_every_n_global_steps) to log anything inside the context manager every “n” steps.

In eager you might consider creating a function for running in each iteration like so:

def train(net, optimizer, x, y):
prediction = net(x)
loss = tf.losses.sparse_softmax_cross_entropy(y, prediction)

global_step=tf.train.get_global_step()
)

# here is how you log every step (n=1)
with tf.contrib.summary.record_summaries_every_n_global_steps(1):
tf.contrib.summary.scalar('loss', loss)

return loss


### At the time of running

Here is the code for graph mode:

with graph.as_default():
with writer.as_default():
with tf.Session() as sess:
# initialize the summary
tf.contrib.summary.initialize(
graph=tf.get_default_graph()
)
# init vars
sess.run(tf.global_variables_initializer())
# init iterator
sess.run(data_itr.initializer)
# run
while True:
try:
_, _, loss = sess.run([
summary_op, opt_op, loss_op
])
...
except tf.errors.OutOfRangeError:
break


Two things to keep in mind:

• tf.contrib.summary.initialize(graph=...) — You can supply “None” to the graph (leave it blank), it won’t save the graph to the Tensorboard. However, this option won’t have any effect in the eager mode anyway (since it doesn’t really construct a graph)
• You need to run tf.contrib.summary.all_summary_ops() which will actually write the summary. However, you don’t need this for eager mode since it’s executed in real time anyway

#### To summarize

• Create a summary writer under a graph, and use that graph throughout
• Define what you want to include in the summary and how frequent
• Initialize the summary (you might supply the graph here if you want to get the “Graph” page in Tensorboard, won’t work in eager)
• In graph mode, also run tf.contrib.summary.all_summary_ops() to actually write the summary

#### An example of graph mode

import tensorflow as tf
import numpy as np

save_path = 'summary_path'
graph = tf.Graph()
with graph.as_default():
global_step = tf.train.create_global_step()
writer = tf.contrib.summary.create_file_writer(save_path)
with writer.as_default():
tf.contrib.summary.always_record_summaries()

# simulate dataset
fake_dataset = np.random.randn(1000, 100).astype(np.float32)
fake_label = np.random.randint(low=0, high=9, size=1000)
# preparing a fake dataset
with graph.as_default():
x = tf.data.Dataset.from_tensor_slices(fake_dataset)
y = tf.data.Dataset.from_tensor_slices(fake_label)
data = tf.data.Dataset.zip((x, y))
data = data.shuffle(10000)
data = data.batch(32)
data_itr = data.make_initializable_iterator()
x, y = data_itr.get_next()

# define the computing graph
with graph.as_default():
with writer.as_default():
# construct a simple classifier
net = tf.keras.Sequential([
tf.keras.layers.Dense(300, activation=tf.nn.relu),
tf.keras.layers.Dense(10)
])

prediction_op = net(x)
loss_op = tf.losses.sparse_softmax_cross_entropy(y, prediction_op)
loss_op,
global_step=tf.train.get_global_step())

# here is how you log every step (n=1)
with tf.contrib.summary.record_summaries_every_n_global_steps(1):
tf.contrib.summary.scalar('loss', loss_op)

summary_op = tf.contrib.summary.all_summary_ops()

# compute the graph
with graph.as_default():
with writer.as_default():
with tf.Session() as sess:
# initialize the summary writer
tf.contrib.summary.initialize(
graph=tf.get_default_graph()
)
# init vars
sess.run(tf.global_variables_initializer())
# init iterator
sess.run(data_itr.initializer)
# run until the dataset is exhausted
while True:
try:
_, _, loss = sess.run([
summary_op, opt_op, loss_op
])
except tf.errors.OutOfRangeError:
break


#### An example of eager mode

import tensorflow as tf
import numpy as np

tf.enable_eager_execution()

save_path = 'logs/test10'
graph = tf.Graph()
with graph.as_default():
global_step = tf.train.create_global_step()
writer = tf.contrib.summary.create_file_writer(save_path)
with writer.as_default():
tf.contrib.summary.always_record_summaries()

# simulate dataset
fake_dataset = np.random.randn(1000, 100).astype(np.float32)
fake_label = np.random.randint(low=0, high=9, size=1000)
# preparing a fake dataset
with graph.as_default():
x = tf.data.Dataset.from_tensor_slices(fake_dataset)
y = tf.data.Dataset.from_tensor_slices(fake_label)
data = tf.data.Dataset.zip((x, y))
data = data.shuffle(10000)
data = data.batch(32)

# define the model
with graph.as_default():
with writer.as_default():
# construct a simple classifier
net = tf.keras.Sequential([
tf.keras.layers.Dense(300, activation=tf.nn.relu),
tf.keras.layers.Dense(10)
])

def train(net, optimizer, x, y):
prediction = net(x)
loss = tf.losses.sparse_softmax_cross_entropy(y, prediction)

global_step=tf.train.get_global_step()
)

# here is how you log every step (n=1)
with tf.contrib.summary.record_summaries_every_n_global_steps(1):
tf.contrib.summary.scalar('loss', loss)

return loss

# start the training process
with graph.as_default():
with writer.as_default():
# initialize the summary writer
tf.contrib.summary.initialize()
# run until the dataset is exhausted
for x, y in data:
loss = train(net, optimizer, x, y)
print(float(loss))