# AutoGraph reference [Index](index.md) ## 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](https://en.wikipedia.org/wiki/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 >>> 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 ``` ### 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) <> ``` ### 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) <> >>> experimental_converted_f(3) # Valid <> ```