aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Alexandre Passos <apassos@google.com>2017-06-26 14:35:34 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2017-06-26 14:39:13 -0700
commit983dcc63afb601f64b517cf62b8384d83f6ca090 (patch)
tree57b628b1c73e09780aa7c73c596141c9b353067f
parent6f685da23e208f9e9e0091442a8ddc741657d904 (diff)
First draft of Tensors segment of the programmer's guide.
PiperOrigin-RevId: 160196550
-rw-r--r--tensorflow/docs_src/programmers_guide/tensors.md330
1 files changed, 330 insertions, 0 deletions
diff --git a/tensorflow/docs_src/programmers_guide/tensors.md b/tensorflow/docs_src/programmers_guide/tensors.md
new file mode 100644
index 0000000000..2675953db8
--- /dev/null
+++ b/tensorflow/docs_src/programmers_guide/tensors.md
@@ -0,0 +1,330 @@
+# Tensors
+
+TensorFlow, as the name indicates, is a framework to define and run computations
+involving tensors. A **tensor** is a generalization of vectors and matrices to
+potentially higher dimensions. Internally, TensorFlow represents tensors as
+n-dimensional arrays of base datatypes.
+
+When writing a TensorFlow program, the main object you manipulate and pass
+around is the `tf.Tensor`. A `tf.Tensor` object represents a partially defined
+computation that will eventually produce a value. TensorFlow programs work by
+first building a graph of `tf.Tensor` objects, detailing how each tensor is
+computed based on the other available tensors and then by running parts of this
+graph to achieve the desired results.
+
+A `tf.Tensor` has the following properties:
+
+ * a data type (`float32`, `int32`, or `string`, for example)
+ * a shape
+
+
+Each element in the Tensor has the same data type, and the data type is always
+known. The shape (that is, the number of dimensions it has and the size of each
+dimension) might be only partially known. Most operations produce tensors of
+fully-known shapes if the shapes of their inputs are also fully known, but in
+some cases it's only possible to find the shape of a tensor at graph execution
+time.
+
+Some types of tensors are special, and these will be covered in other
+units of the Programmer's guide. The main ones are:
+
+ * `tf.Variable`
+ * `tf.Constant`
+ * `tf.Placeholder`
+ * `tf.SparseTensor`
+
+With the exception of `tf.Variable`, the value of a tensor is immutable, which
+means that in the context of a single execution tensors only have a single
+value. However, evaluating the same tensor twice can return different values;
+for example that tensor can be the result of reading data from disk, or
+generating a random number.
+
+## Rank
+
+The **rank** of a `tf.Tensor` object is its number of dimensions. Synonyms for
+rank include **order** or **degree** or **n-dimension**.
+Note that rank in TensorFlow is not the same as matrix rank in mathematics.
+As the following table shows, each rank in TensorFlow corresponds to a
+different mathematical entity:
+
+Rank | Math entity
+--- | ---
+0 | Scalar (magnitude only)
+1 | Vector (magnitude and direction)
+2 | Matrix (table of numbers)
+3 | 3-Tensor (cube of numbers)
+n | n-Tensor (you get the idea)
+
+
+### Rank 0
+
+The following snippet demonstrates creating a few rank 0 variables:
+
+```python
+mammal = tf.Variable("Elephant", tf.string)
+ignition = tf.Variable(451, tf.int16)
+floating = tf.Variable(3.14159265359, tf.float64)
+its_complicated = tf.Variable((12.3, -4.85), tf.complex64)
+```
+
+Note: A string is treated as a single item in TensorFlow, not as a sequence of
+characters. It is possible to have scalar strings, vectors of strings, etc.
+
+### Rank 1
+
+To create a rank 1 `tf.Tensor` object, you can pass a list of items as the
+initial value. For example:
+
+```python
+mystr = tf.Variable(["Hello"], tf.string)
+cool_numbers = tf.Variable([3.14159, 2.71828], tf.float32)
+first_primes = tf.Variable([2, 3, 5, 7, 11], tf.int32)
+its_very_complicated = tf.Variable([(12.3, -4.85), (7.5, -6.23)], tf.complex64)
+```
+
+
+### Higher ranks
+
+A rank 2 `tf.Tensor` object consists of at least one row and at least
+one column:
+
+```python
+mymat = tf.Variable([[7],[11]], tf.int16)
+myxor = tf.Variable([[False, True],[True, False]], tf.bool)
+linear_squares = tf.Variable([[4], [9], [16], [25]], tf.int32)
+squarish_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32)
+rank_of_squares = tf.rank(squarish_squares)
+mymatC = tf.Variable([[7],[11]], tf.int32)
+```
+
+Higher-rank Tensors, similarly, consist of an n-dimensional array. For example,
+during image processing, many tensors of rank 4 are used, with dimensions
+corresponding to example-in-batch, image width, image height, and color channel.
+
+``` python
+my_image = tf.zeros([10, 299, 299, 3]) # batch x height x width x color
+```
+
+### Getting a `tf.Tensor` object's rank
+
+To determine the rank of a `tf.Tensor` object, call the `tf.rank` method.
+For example, the following method programmatically determines the rank
+of the `tf.Tensor` defined in the previous section:
+
+```python
+r = tf.rank(my3d)
+# After the graph runs, r will hold the value 3.
+```
+
+### Referring to `tf.Tensor` slices
+
+Since a `tf.Tensor` is an n-dimensional array of cells, to access a single cell
+in a `tf.Tensor` you need to specify n indices.
+
+For a rank 0 tensor (a scalar), no indices are necessary, since it is already a
+single number.
+
+For a rank 1 tensor (a vector), passing a single index allows you to access a
+number:
+
+```python
+my_scalar = my_vector[2]
+```
+
+Note that the index passed inside the `[]` can itself be a scalar `tf.Tensor`, if
+you want to dynamically choose an element from the vector.
+
+For tensors of rank 2 or higher, the situation is more interesting. For a
+`tf.Tensor` of rank 2, passing two numbers returns a scalar, as expected:
+
+
+```python
+my_scalar = my_matrix[1, 2]
+```
+
+
+Passing a single number, however, returns a subvector of a matrix, as follows:
+
+
+```python
+my_row_vetor = my_matrix[2]
+my_column_vector = my_matrix[:, 3]
+```
+
+The `:` notation is python slicing syntax for "leave this dimension alone". This
+is useful in higher-rank Tensors, as it allows you to access its subvectors,
+submatrices, and even other subtensors.
+
+
+## Shape
+
+The **shape** of a tensor is the number of elements in each dimension.
+TensorFlow automatically infers shapes during graph construction. These inferred
+shapes might have known or unknown rank. If the rank is known, the sizes of each
+dimension might be known or unknown.
+
+The TensorFlow documentation uses three notational conventions to describe
+tensor dimensionality: rank, shape, and dimension number. The following table
+shows how these relate to one another:
+
+Rank | Shape | Dimension number | Example
+--- | --- | --- | ---
+0 | [] | 0-D | A 0-D tensor. A scalar.
+1 | [D0] | 1-D | A 1-D tensor with shape [5].
+2 | [D0, D1] | 2-D | A 2-D tensor with shape [3, 4].
+3 | [D0, D1, D2] | 3-D | A 3-D tensor with shape [1, 4, 3].
+n | [D0, D1, ... Dn-1] | n-D | A tensor with shape [D0, D1, ... Dn-1].
+
+Shapes can be represented via Python lists / tuples of ints, or with the
+@{tf.TensorShape}.
+
+### Getting a `tf.Tensor` object's shape
+
+There are two ways of accessing the shape of a `tf.Tensor`. While building the
+graph, it is often useful to ask what is already known about a tensor's
+shape. This can be done by reading the `shape` property of a `tf.Tensor` object.
+This method returns a `TensorShape` object, which is a convenient way of
+representing partially-specified shapes (since, when building the graph, not all
+shapes will be fully known).
+
+It is also possible to get a `tf.Tensor` that will represent the fully-defined
+shape of another `tf.Tensor` at runtime. This is done by calling the `tf.shape`
+operation. This way, you can build a graph that manipulates the shapes of
+tensors by building other tensors that depend on the dynamic shape of the input
+`tf.Tensor`.
+
+For example, here is how to make a vector of zeros with the same size as the
+number of columns in a given matrix:
+
+``` python
+zeros = tf.zeros(tf.shape(my_matrix)[1])
+```
+
+### Changing the shape of a `tf.Tensor`
+
+The **number of elements** of a tensor is the product of the sizes of all its
+shapes. The number of elements of a scalar is always `1`. Since there are often
+many different shapes that have the same number of elements, it's often
+convenient to be able to change the shape of a `tf.Tensor`, keeping its elements
+fixed. This can be done with `tf.reshape`.
+
+The following examples demonstrate how to reshape tensors:
+
+```python
+rank_three_tensor = tf.ones([3, 4, 5])
+matrix = tf.reshape(rank_three_tensor, [6, 10]) # Reshape existing content into
+ # a 6x10 matrix
+matrixB = tf.reshape(matrix, [3, -1]) # Reshape existing content into a 3x20
+ # matrix. -1 tells reshape to calculate
+ # the size of this dimension.
+matrixAlt = tf.reshape(matrixB, [4, 3, -1]) # Reshape existing content into a
+ #4x3x5 tensor
+
+# Note that the number of elements of the reshaped Tensors has to match the
+# original number of elements. Therefore, the following example generates an
+# error because no possible value for the last dimension will match the number
+# of elements.
+yet_another = tf.reshape(matrixAlt, [13, 2, -1]) # ERROR!
+```
+
+## Data types
+
+In addition to dimensionality, Tensors have a data type. Refer to the
+`tf.DataType` page in the programmer's guide for a full list of the data types.
+
+It is not possible to have a `tf.Tensor` with more than one data type. It is
+possible, however, to serialize arbitrary data structures as `string`s and store
+those in `tf.Tensor`s.
+
+It is possible to cast `tf.Tensor`s from one datatype to another using
+`tf.cast`:
+
+``` python
+# Cast a constant integer tensor into floating point.
+float_tensor = tf.cast(tf.constant([1, 2, 3]), dtype=tf.float32)
+```
+
+To inspect a `tf.Tensor`'s data type use the `Tensor.dtype` property.
+
+When creating a `tf.Tensor` from a python object you may optionally specify the
+datatype. If you don't, TensorFlow chooses a datatype that can represent your
+data. TensorFlow converts Python integers to `tf.int32` and python floating
+point numbers to `tf.float32`. Otherwise TensorFlow uses the same rules numpy
+uses when converting to arrays.
+
+## Evaluating Tensors
+
+Once the computation graph has been built, you can run the computation that
+produces a particular `tf.Tensor` and fetch the value assigned to it. This is
+often useful for debugging as well as being required for much of TensorFlow to
+work.
+
+The simplest way to evaluate a Tensor is using the `Tensor.eval` method. For
+example:
+
+```python
+constant = tf.constant([1, 2, 3])
+tensor = constant * constant
+print tensor.eval()
+```
+
+The `eval` method only works when a default `tf.Session` is active (see
+@{$graphs$Graphs and Sessions} for more information).
+
+`Tensor.eval` returns a numpy array with the same contents as the tensor.
+
+Sometimes it is not possible to evaluate a `tf.Tensor` with no context because
+its value might depend on dynamic information that is not available. For
+example, tensors that depend on `Placeholder`s can't be evaluated without
+providing a value for the `Placeholder`.
+
+``` python
+p = tf.placeholder(tf.float32)
+t = p + 1.0
+t.eval() # This will fail, since the placeholder did not get a value.
+t.eval(feed_dict={p:2.0}) # This will succeed because we're feeding a value
+ # to the placeholder.
+```
+
+Note that it is possible to feed any `tf.Tensor`, not just placeholders.
+
+Other model constructs might make evaluating a `tf.Tensor`
+complicated. TensorFlow can't directly evaluate `tf.Tensor`s defined inside
+functions or inside control flow constructs. If a `tf.Tensor` depends on a value
+from a queue, evaluating the `tf.Tensor` will only work once something has been
+enqueued; otherwise, evaluating it will hang. When working with queues, remember
+to call `tf.train.start_queue_runners` before evaluating any `tf.Tensor`s.
+
+## Printing Tensors
+
+For debugging purposes you might want to print the value of a `tf.Tensor`. While
+ @{$debug$tfdbg} provides advanced debugging support, TensorFlow also has an
+ operation to directly print the value of a `tf.Tensor`.
+
+Note that you rarely want to use the following pattern when printing a
+`tf.Tensor`:
+
+``` python
+t = <<some tensorflow operation>>
+print t # This will print the symbolic tensor when the graph is being built.
+ # This tensor does not have a value in this context.
+```
+
+This code prints the `tf.Tensor` object (which represents deferred computation)
+and not its value. Instead, TensorFlow provides the `tf.Print` operation, which
+returns its first tensor argument unchanged while printing the set of
+`tf.Tensor`s it is passed as the second argument.
+
+To correctly use `tf.Print` its return value must be used. See the example below
+
+``` python
+t = <<some tensorflow operation>>
+tf.Print(t, [t]) # This does nothing
+t = tf.Print(t, [t]) # Here we are using the value returned by tf.Print
+result = t + 1 # Now when result is evaluated the value of `t` will be printed.
+```
+
+When you evaluate `result` you will evaluate everything `result` depends
+upon. Since `result` depends upon `t`, and evaluating `t` has the side effect of
+printing its input (the old value of `t`), `t` gets printed.
+