Back to Tensorflow

AutoGraph reference

tensorflow/python/autograph/g3doc/reference/intro.md

2.21.03.7 KB
Original Source

AutoGraph reference

Index

Introduction

Terminology

Typically, AutoGraph operates by converting a function into a new function with new semantics.

def f(...):
  ...

converted_f = tf.autograph.to_graph(f)

In TensorFlow 2, AutoGraph is used to convert functions before they are being traced, when using the tf.function API. For example, the following code:

def f(...):
  ...

graph_f = tf.function(f)

is roughly equivalent to:

converted_f = tf.autograph.to_graph(f)
graph_f = tf.function(autograph=False)(converted_f)

For the remainder of this document:

  • converted functions are functions converted by AutoGraph
  • graph functions are functions compiled with tf.function

Graph functions are usually also converted, unless specified otherwise.

Safe behavior

The semantics described below can be summarized as:

  1. code should either produce the same results as running it in Eager mode, or fail with error.
  2. TF 1.* graph code should produce the same graph as running it directly in graph mode.

Python semantics

In general, AutoGraph does not change the semantics of error-free Python. In special circumstances, AutoGraph may also preserve the semantics of code that raises error as well. Semantics are preserved in the sense of the as-if rule.

More specifically, code that would not be legal TensorFlow Graph code may become legal when converted.

For example, consider the following function and the corresponding converted function:

def f(x):
  if x > 0:
    return x
  return -x

converted_f = tf.autograph.to_graph(f)

If f executes without error, then the converted_f has identical results:

>>> f(3)                               # Runs without error
3
>>> converted_f(3)                     # Identical result
3

TensorFlow Eager semantics

If a function is called with Tensor arguments in Eager execution mode, it has certain semantics that are different from the Graph execution semantics.

For example, the function below produces different results when executed in Eager and Graph modes:

def f(x):
  if x > 0:
    return x
  return -x

# Use tf.function to run code as a TensorFlow Graph.
unconverted_graph_f = tf.function(f, autograph=False)
graph_f = tf.function(f, autograph=True)
>>> f(tf.constant(3))                      # Valid in Eager
<tf.Tensor ... numpy=3>

>>> unconverted_graph_f(tf.constant(3))    # Error - not legal Graph code
TypeError: Using a `tf.Tensor` ...

AutoGraph transfers the Eager semantics to the graph function:

>>> graph_f(tf.constant(3))                # Valid in AutoGraph
<tf.Tensor ... numpy=3>

Subset of Eager

AutoGraph currently supports only a subset of Eager. For example, list operation semantics are not supported:

def f(n):
  l = []
  for i in tf.range(n):
    l.append(i)
  return l

converted_f = tf.autograph.to_graph(f)
>>> f(3)                               # Valid in Eager
[1, 2, 3]
>>> converted_f(3)                     # Not valid in AutoGraph (by default)
<<error>>

Experimental features

AutoGraph supports additional semantics which are not yet stable. This includes for example support for list semantics applied to TensorArray:

def f(n):
  l = tf.TensorArray(dtype=tf.int32, size=0, dynamic_size=True)
  for i in tf.range(n):
    l.append(i)
  return l

converted_f = tf.autograph.to_graph(f)
experimental_converted_f = tf.autograph.to_graph(
    f, experimental_optional_features=tf.autograph.experimental.Feature.LISTS)
>>> converted_f(3)                     # Not valid in AutoGraph (by default)
<<error>>
>>> experimental_converted_f(3)        # Valid
<<TensorArray object>>