See the variable guide.

Used in the notebooks

Used in the guide Used in the tutorials

A variable maintains shared, persistent state manipulated by a program.

The Variable() constructor requires an initial value for the variable, which can be a Tensor of any type and shape. This initial value defines the type and shape of the variable. After construction, the type and shape of the variable are fixed. The value can be changed using one of the assign methods.

v = tf.Variable(1.)
<tf.Variable ... shape=() dtype=float32, numpy=2.0>
<tf.Variable ... shape=() dtype=float32, numpy=2.5>

The shape argument to Variable's constructor allows you to construct a variable with a less defined shape than its initial_value:

v = tf.Variable(1., shape=tf.TensorShape(None))
<tf.Variable ... shape=<unknown> dtype=float32, numpy=array([[1.]], ...)>

Just like any Tensor, variables created with Variable() can be used as inputs to operations. Additionally, all the operators overloaded for the Tensor class are carried over to variables.

w = tf.Variable([[1.], [2.]])
x = tf.constant([[3., 4.]])
tf.matmul(w, x)
<tf.Tensor:... shape=(2, 2), ... numpy=
  array([[3., 4.],
         [6., 8.]], dtype=float32)>
tf.sigmoid(w + x)
<tf.Tensor:... shape=(2, 2), ...>

When building a machine learning model it is often convenient to distinguish between variables holding trainable model parameters and other variables such as a step variable used to count training steps. To make this easier, the variable constructor supports a trainable=<bool> parameter. tf.GradientTape watches trainable variables by default:

with tf.GradientTape(persistent=True) as tape:
  trainable = tf.Variable(1.)
  non_trainable = tf.Variable(2., trainable=False)
  x1 = trainable * 2.
  x2 = non_trainable * 3.
tape.gradient(x1, trainable)
<tf.Tensor:... shape=(), dtype=float32, numpy=2.0>
assert tape.gradient(x2, non_trainable) is None  # Unwatched

Variables are automatically tracked when assigned to attributes of types inheriting from tf.Module.

m = tf.Module()
m.v = tf.Variable([1.])
(<tf.Variable ... shape=(1,) ... numpy=array([1.], dtype=float32)>,)

This tracking then allows saving variable values to training checkpoints, or to SavedModels which include serialized TensorFlow graphs.

Variables are often captured and manipulated by tf.functions. This works the same way the un-decorated function would have:

v = tf.Variable(0.)
read_and_decrement = tf.function(lambda: v.assign_sub(0.1))
<tf.Tensor: shape=(), dtype=float32, numpy=-0.1>
<tf.Tensor: shape=(), dtype=float32, numpy=-0.2>

Variables created inside a tf.function must be owned outside the function and be created only once:

class M(tf.Module):
  def __call__(self, x):
    if not hasattr(self, "v"):  # Or set self.v to None in __init__
      self.v = tf.Variable(x)
    return self.v * x
m = M()