TensorFlow Tutorial : A Beginner’s Guide to TensorFlow (Part -2)

Original article can be found here (source): Artificial Intelligence on Medium

TensorFlow Tutorial : A Beginner’s Guide to TensorFlow (Part -2)

How does TensorFlow work?

• TensorFlow defines computations as Graphs, and these are made with operations (also know as “ops”). So, when we work with TensorFlow, it is the same as defining a series of operations in a Graph.
• To execute these operations as computations, we must launch the Graph into a Session. The session translates and passes the operations represented into the graphs to the device you want to execute them on, be it a GPU or CPU.
• For example, the image below represents a graph in TensorFlow. W, x and b are tensors over the edges of this graph. MatMul is an operation over the tensors W and x, after that Add is called and add the result of the previous operator with b. The resultant tensors of each operation cross the next one until the end where it’s possible to get the wanted result.

Importing TensorFlow

To use TensorFlow, we need to import the library. We imported it and optionally gave it the name “tf”, so the modules can be accessed by tf.module-name:

`import tensorflow as tf`

Building a Graph

As we discussed before, TensorFlow works as a graph computational model. Let’s create our first graph which we named as graph1.

`graph1 = tf.Graph()`

Now we call the TensorFlow functions that construct new tf.Operation and tf.Tensor objects and add them to the graph1. As mentioned, each tf.Operation is a node and each tf.Tensor is an edge in the graph.

Lets add 2 constants to our graph. For example, calling tf.constant([2], name = ‘constant_a’) adds a single tf.Operation to the default graph. This operation produces the value 2, and returns a tf.Tensor that represents the value of the constant.
Notice: tf.constant([2], name=”constant_a”) creates a new tf.Operation named “constant_a” and returns a tf.Tensor named “constant_a:0”.

`with graph1.as_default(): a = tf.constant([2], name = 'constant_a') b = tf.constant([3], name = 'constant_b')`

Look at the tensor a

`a`

As you can see, it just show the name, shape and type of the tensor in the graph. We will see it’s value when we run it in a TensorFlow session.

`# Printing the value of asess = tf.Session(graph = graph1)result = sess.run(a)print(result)sess.close()`

Now, let’s make an operation over these tensors. The function tf.add() adds two tensors (you could also use `c = a + b`).

`with graph1.as_default(): c = tf.add(a, b) #c = a + b is also a way to define the sum of the terms`

Then TensorFlow needs to initialize a session to run our code. Sessions are, in a way, a context for creating a graph inside TensorFlow. Let’s define our session:

`sess = tf.Session(graph = graph1)`

Let’s run the session to get the result from the previous defined ‘c’ operation:

`result = sess.run(c)print(result)`

Close the session to release resources:

`sess.close()`

To avoid having to close sessions every time, we can define them in a with block, so after running the with block the session will close automatically:

`with tf.Session(graph = graph1) as sess: result = sess.run(c) print(result)`

Even this silly example of adding 2 constants to reach a simple result defines the basis of TensorFlow. Define your operations (In this case our constants and tf.add), and start a session to build a graph.

Defining multidimensional arrays using TensorFlow

Now we will try to define such arrays using TensorFlow:

`graph2 = tf.Graph()with graph2.as_default(): Scalar = tf.constant(2) Vector = tf.constant([5,6,2]) Matrix = tf.constant([[1,2,3],[2,3,4],[3,4,5]]) Tensor = tf.constant( [ [[1,2,3],[2,3,4],[3,4,5]] , [[4,5,6],[5,6,7],[6,7,8]] , [[7,8,9],[8,9,10],[9,10,11]] ] )with tf.Session(graph = graph2) as sess: result = sess.run(Scalar) print ("Scalar (1 entry):\n %s \n" % result) result = sess.run(Vector) print ("Vector (3 entries) :\n %s \n" % result) result = sess.run(Matrix) print ("Matrix (3x3 entries):\n %s \n" % result) result = sess.run(Tensor) print ("Tensor (3x3x3 entries) :\n %s \n" % result)`

tf.shape returns the shape of our data structure.

`Scalar.shapeMatrix.shapeTensor.shape`

Now play with using some previous functions to see how they will behave, according to their structure types:

`graph3 = tf.Graph()with graph3.as_default(): Matrix_one = tf.constant([[1,2,3],[2,3,4],[3,4,5]]) Matrix_two = tf.constant([[2,2,2],[2,2,2],[2,2,2]])add_1_operation = tf.add(Matrix_one, Matrix_two) add_2_operation = Matrix_one + Matrix_twowith tf.Session(graph =graph3) as sess: result = sess.run(add_1_operation) print ("Defined using tensorflow function :") print(result) result = sess.run(add_2_operation) print ("Defined using normal expressions :") print(result)`

With the regular symbol definition and also the TensorFlow function we were able to get an element-wise multiplication, also known as Hadamard product. But what if we want the regular matrix product? We then need to use another TensorFlow function called tf.matmul():

`graph4 = tf.Graph()with graph4.as_default(): Matrix_one = tf.constant([[2,3],[3,4]]) Matrix_two = tf.constant([[2,3],[3,4]])mul_operation = tf.matmul(Matrix_one, Matrix_two)with tf.Session(graph = graph4) as sess: result = sess.run(mul_operation) print ("Defined using tensorflow function :") print(result)`

We could also define this multiplication ourselves, but there is a function that already does that, so no need to reinvent the wheel!

Variables

Now that we are more familiar with the structure of data, we will take a look at how TensorFlow handles variables. First of all, having tensors, why do we need variables?
TensorFlow variables are used to share and persistent some stats that are manipulated by our program. That is, when you define a variable, TensorFlow adds a tf.Operation to your graph. Then, this operation will store a writable tensor value that persists between tf.Session.run calls. So, you can update the value of a variable through each run, while you cannot update tensor (e.g a tensor created by tf.constant()) through multiple runs in a session.

How to define a variable?
To define variables we use the command tf.Variable(). To be able to use variables in a computation graph it is necessary to initialize them before running the graph in a session. This is done by running tf.global_variables_initializer().

To update the value of a variable, we simply run an assign operation that assigns a value to the variable:

`v = tf.Variable(0)`

Let’s first create a simple counter, a variable that increases one unit at a time:

To do this we use the tf.assign(reference_variable, value_to_update) command. tf.assign takes in two arguments, the reference_variable to update, and assign it to the value_to_update it by.

`update = tf.assign(v, v+1)`

Variables must be initialized by running an initialization operation after having launched the graph. We first have to add the initialization operation to the graph:

`init_op = tf.global_variables_initializer()`

We then start a session to run the graph, first initialize the variables, then print the initial value of the state variable, and then run the operation of updating the state variable and printing the result after each update:

`with tf.Session() as session: session.run(init_op) print(session.run(v)) for _ in range(3): session.run(update) print(session.run(v))`

Placeholders

Now we know how to manipulate variables inside TensorFlow graph, but what about feeding data outside of a TensorFlow graph?

If you want to feed data to a TensorFlow graph from outside a graph, you will need to use placeholders.

So what are these placeholders and what do they do?

Placeholders can be seen as “holes” in your model, “holes” which you will pass the data to, you can create them using
tf.placeholder(datatype), where datatype specifies the type of data (integers, floating points, strings, booleans) along with its precision (8, 16, 32, 64) bits.

The definition of each data type with the respective python syntax is defined as: