Does anyone get frustrated by Python print()
function when you want to print out some tensor value during the TensorFlow graph construction? Often we want to inspect the itermidiate value for debugging purpose, but Python print()
merely prints out the side information about this tensor, such as its name, shape information (so long as it can be accurately infered from the constructed graph), which is not the right information we want to get.
Neither the TensorFlow nor the print()
is to be blamed. The reason for this awkardness is simple: TensorFlow splits graph construction and computation apart, Python print()
merely gives a node within a graph with its basic information, such as its shape (if available), name and data type information. Let’s dive deeper with one simple example: $ e = c \times (a + b) $. The basic script should look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
The print( c )
outputs information looks like:
1
|
|
It works as the way as we expected: no tensor value is outputed! Fortunately, TensorFlow already takes care of this issue: tf.Print(). First, let’s take a look at its constructor:
1 2 3 4 5 6 7 8 |
|
In concise, it receives the input_
tensor, outputs the data
information with the prefixed message
information. Before directly entering into the final correct snippet, I would like to highlight two rules TensorFlow always obeys:
tf.Print()
is capable of printing out all the tensors it has access to. Here “all the tensors” means the tensors the data flows through until the currenttf.Print()
operator. That is, in this example, tensora
and tensorb
can be accessed bytf.Print()
.- To calculate the defined loss value, TensorFlow would choose the most directly related operators to run by a session. That is, any “dangling” or “irrelevant” operator would not be executed.
Beneath these two rules, two things gradually become clear: First, tf.Print()
can print out all tensors the data flow has covered while tf.Print()
operator has been reached. Second, instead of randomly putting tf.Print()
as a “dangling” or “irrelevant” operator, we have to add the tf.Print()
to the place of the graph where the data has to flow through.
With aforementioned discussion, here I provide the correct code snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
The final outout of this snippet is:
1 2 |
|
The following picture illustrates the graph without and with “dangling” tf.Print()
operator.
Believe it or not, if the graph is constructed with the tf.Print()
operator being “dangled”, tf.Print()
won’t print out anything! Thus, we should be careful when utilizing tf.Print()
for either debugging or visualization purpose.