Try not to peek at the solutions when you go through the exercises. ;-)

First let's make sure this notebook works well in both Python 2 and Python 3:


In [ ]:
from __future__ import absolute_import, division, print_function, unicode_literals

In [ ]:
import tensorflow as tf
tf.__version__

From notebook 2 on variables:


In [ ]:
>>> graph = tf.Graph()
>>> with graph.as_default():
...     x = tf.Variable(100)
...     c = tf.constant(5)
...     increment_op = tf.assign(x, x + c)
...

Collections


In [ ]:
>>> graph.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)

In [ ]:
tf.GraphKeys.GLOBAL_VARIABLES

In [ ]:
>>> graph.add_to_collection("my_collection", c)
>>> graph.get_collection("my_collection")

In [ ]:
>>> graph = tf.Graph()
>>> with graph.as_default():
...     a = tf.constant(3)
...     b = tf.constant(5)
...     s = a + b
...
>>> graph.get_operations()

In [ ]:
>>> graph.get_operation_by_name("add") is s.op

In [ ]:
>>> graph.get_tensor_by_name("add:0") is s

In [ ]:
>>> list(s.op.inputs)

In [ ]:
>>> list(s.op.outputs)

Naming Operations


In [ ]:
>>> graph = tf.Graph()
>>> with graph.as_default():
...     a = tf.constant(3, name='a')
...     b = tf.constant(5, name='b')
...     s = tf.add(a, b, name='s')
...

In [ ]:
>>> graph.get_operations()

Exercise 3

3.1) Create a graph with four variables named "x1", "x2", "x3" and "x4", with initial values 1.0, 2.0, 3.0 and 4.0 respectively, then write some code that prints the name of every operation in the graph.


In [ ]:


In [ ]:


In [ ]:

3.2) Notice that for each Variable, TensorFlow actually created 4 operations:

  • the variable itself,
  • its initial value,
  • an assignment operation to assign the initial value to the variable,
  • and a read operation that you can safely ignore for now (for details, check out mrry's great answer to this question).

Get the collection of global variables in the graph, and for each one of them use get_operation_by_name() to find its corresponding /Assign operation (just append "/Assign" to the variable's name).

Hint: each object in the collection of global variables is actually a Tensor, not an Operation (it represents the variable's output, i.e., its value), so its name ends with ":0". You can get the Operation through the Tensor's op attribute: its name will not end with ":0"


In [ ]:


In [ ]:


In [ ]:

3.3) Add a tf.group() to your graph, containing all the assignment operations you got in question 3.2. Congratulations! You have just reimplemented tf.global_variables_initializer().

Start a Session(), run your group operation, then evaluate each variable and print out the result.


In [ ]:


In [ ]:


In [ ]:

3.4) For each assignment operation you fetched earlier, get its second input and store it in a list. Next, start a session and evaluate that list (using sess.run()). Print out the result: you should see [1.0, 2.0, 3.0, 4.0]. Can you guess why?


In [ ]:


In [ ]:


In [ ]:

Try not to peek at the solution below before you have done the exercise! :)

Exercise 3 - Solution

3.1)


In [ ]:
graph = tf.Graph()
with graph.as_default():
    x1 = tf.Variable(1.0, name="x1")
    x2 = tf.Variable(2.0, name="x2")
    x3 = tf.Variable(3.0, name="x3")
    x4 = tf.Variable(4.0, name="x4")

3.2)


In [ ]:
gvars = graph.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)
init_assign_ops = [graph.get_operation_by_name(gvar.op.name + "/Assign")
                   for gvar in gvars]

In [ ]:
init_assign_ops

3.3)


In [ ]:
with graph.as_default():
    init = tf.group(*init_assign_ops)

In [ ]:
with tf.Session(graph=graph):
    init.run()
    print(x1.eval())
    print(x2.eval())
    print(x3.eval())
    print(x4.eval())

3.4)


In [ ]:
init_val_ops = [init_assign_op.inputs[1]
                for init_assign_op in init_assign_ops]

In [ ]:
with tf.Session(graph=graph) as sess:
    print(sess.run(init_val_ops))

Explanation: in the case of assignment operations, the first input is a reference to the variable, and the second is the assignment value. The assignment operations we have here are used to initialize the variables, so their assignment values correspond to the initial values: 1.0 for x1, 2.0 for x2, 3.0 for x3 and 4.0 for x4.