Skip to content

Instantly share code, notes, and snippets.

@blepfo
Last active October 2, 2018 17:21
Show Gist options
  • Save blepfo/93551754c6c3f25abb56c627eb8294cc to your computer and use it in GitHub Desktop.
Save blepfo/93551754c6c3f25abb56c627eb8294cc to your computer and use it in GitHub Desktop.
TensorFlow Notes

TensorFlow Notes

By Adam Anderson

adam.b.anderson.96@gmail.com

Aggregated links to tutorials with some summaries. Like all of my Gist notes, this document is mostly so I can keep track of useful resources.

Table of Contents

Table of Contents generated with DocToc

Basics

Basic Definitions

Tenorflow is a programming system in which you represent computations as graphs. This lets us represent computation without performing it until we decide to. Nodes in the graphs are called ops (operations). An op operates on tensors.

TensorFlow programs use a tensor data structure to represent all data. A tensor is just an n-dimensional array with static type and dynamic dimensions.

A tensor is described by three properties: Rank, Shape, and Type.

Rank - The number of dimensions in the tensor (how many subscript indices we need to access an element). A standard array is a rank 2 tensor, whose elements are accessed t[i, j]. A list is a rank 1 tensor. For a rank 3 tensor, elements are accessed t[i, j, k].

Shape - A list of numbers describing the shape of the tensor along each dimension. For example, the rank 2 tensor [[1, 2, 3], [4, 5, 6]] has shape [2, 3]. In general, the shape of a tensor is [D0, D1, ... Dn-1].

Type - Data type contained by the tensor. For example, tf.float32, tf.int8, andtf.bool.

In a TensorFlow program, we create a graph that does operations on tensors and then launch the graph in a session. The graph does not compute anything or hold values; it just defines operations. A session allocates resources and holds values for variables.

A session is launched using session = tf.Session(). Because a session must be closed with session.close(), it is common to use a with statement. You can run an operation in the graph by calling session.run(op_name). This will fetch the output of the operation op_name. If you pass in a list of operation names, calling session.run() will fetch multiple values.

References

Variables and Placeholders

A variable maintains state in the graph across all calls to run(). The Variable() constructor requires an initial value, which can be a Tensor of any size and shape. When a session is launched, we need to initialize all variables with an initializer op. This is usually done using tf.global_variables_initializer(), which adds an op to the graph to initialize all variables. Don't forget to run this Op after launching the graph in a session.

import tensorflow as tf

x = tf.constant(35, name='x')
y = tf.Variable(x + 5, name='y')

model = tf.global_variables_initializer()

with tf.Session() as session:
    session.run(model)
    print(session.run(y))

A placeholder allows you to build computation graphs without needing specific data. We create a placeholder during construction and feed in data when we launch the session. This is done by adding a feed_dict={...} parameter to session.run().

import tensorflow as tf

x = tf.placeholder("float", 3)
y = x * 2

with tf.Session() as session:
    result = session.run(y, feed_dict={x: [1, 2, 3]})
    print(result)

References

Basic Machine Learning Example

Let's start with a simple univariate linear model. We want to model house price as a function of the square footage in the form y = Wx + b. Since x is an input, it makes sense to make it a placeholder. W and b are the model parameters that will be learned and reused, so we want to make them variables. During the learning process, we will want to minimize the distance between the predicted output, y, and the actual output, which we will call y_.

# Input to model
x = tf.placeholder(tf.float32)
# Actual house prices
y_ = tf.placeholder(tf.float32)
# Model Parameters
W = tf.Variable(tf.zeros([1, 1]))
b = tf.Variable(tf.zeros([1]))
# Model output
y = tf.matmul(x, W) + b

We can then define the operations to compute tha output and to compute the cost function. Note that tf.matmul() only works on matrices, AKA rank 2 tensors. Because of this we give W the shape [1, 1]. This still makes it a single number, but it is technically a rank 2 matrix that we can use with matmul.

If we ran the graph and fetched the value of y after the matmul op, we would have a rank 2 tensor with shape [1, 1]. We want to reduce this to a scalar, so we use tf.reduce_sum(). Since we do not specify the axis on which reduce_sum should reduce the dimension, all dimensions are reduced, making cost a rank 0 tensor (a scalar).

# Model Parameters
W = tf.Variable(tf.zeros([1, 1]))
b = tf.Variable(tf.zeros([1]))
# Model output
y = tf.matmul(x, W) + b
# Cost function
cost = tf.reduce_sum(tf.pow((y_ - y), 2))

Next, we can use gradient descent to minimize cost. We can do this using the tf.train.GradientDescentOptimizer class, a subclass of tf.train.Optimizer. The tf.train.Optimizer.minimize() function combines calls to the compute_gradients() and apply_gradients() methods.

# Gradient descent
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_step = optimizer.minimize(cost)

References

TensorFlow Hello World: MNIST

Now that we understand tensors, sessions, variables, placeholders, and basic TensorFlow syntax, we can make a simple neural network to classfy MNIST digits For a thorough introduction to neural networks through MNIST, see Neural Networks and Deep Learning. Otherwise, just follow along with the TensorFlow: MNIST for ML Beginners

import tensorflow as tf
# Import MNIST data
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# Input images
x = tf.placeholder(tf.float32, [None, 784])
# Model parameters
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
# Model output
y = tf.nn.softmax(tf.matmul(x, W) + b)
# Actual output
y_ = tf.placeholder(tf.float32, [None, 10])
# Cost function
cost = tf.reduce_mean(tf.reduce_sum(tf.pow(y_ - y, 2), axis=1))
training_step = tf.train.GradientDescentOptimizer(0.5).minimize(cost)
# Validate model
accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)), tf.float32))
# Initialize variables
init = tf.global_variables_initializer()
# Launch session
with tf.Session() as sess:
    sess.run(init)
    # Train model
    for i in range(2000):
        batch = mnist.train.next_batch(100)
        sess.run(training_step, feed_dict={x: batch[0], y_: batch[1]})
    print("Accuracy: %f" % sess.run(
            accuracy, feed_dict={x: mnist.test.images, y_:mnist.test.labels}))

References

Intermediate Topics

Reusing Variables

Sharing Variables

TensorBoard

tf.summary.scalar('name', variable)
...
merged = tf.summary.merge_all()

with tf.Session as sess:
	for i = 1 to num_epochs:
		writer = tf.summary.FileWriter('/logdir', sess.graph)
		summary = sess.run(merged)
		writer.add_summary(summary, i)
	saver = tf.train.Saver()
	saver.save(sess, './model')
...
with tf.Session as sess:
	saver.restore(sess, './model')
...
...
tensorboard --logdir=logdir

TensorBoard: Visualizing Learning TensorBoard: Embedding Visualization

Graph Collections

TensorFlow programs are build around a tf.Graph object, which contains a set of tf.Operation objects and tf.Tensor objects. The operations represent computation while Tensors represent data. TensorFlow functions add operations and tensors to the default graph. To control this, we can call graphObj.as_default() which returns a context manager to make graphObj the default.

A graph instance supports many collections. Graph collections keep track of data about a graph. We can access the graph collections by calling tf.get_collection(key, scope). The keys for graph collections can be found in tf.GraphKeys, including tf.GraphKeys.TRAINABLE_VARIABLES, tf.GraphKeys.SUMMARIES, etc.

When we make a call to tf.get_collection(), we pass in one of the keys to tell Tensorflow what keys to get from the current default graph. The scope parameter is used to filter results in the collection using regular expressions. This means scope should be as specific as possible.

For example, if we want all of the trainable variables in the Net/N/Layer_1 variable scope, we could use tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, "Net/N"). Note that we can NOT just use "N" as the scope parameter, because "Net/_" matches the regular expression "N".

Note that tf.Graph is not thread safe, and we should construct graphs in a single thread.

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment