<jupyter_start><jupyter_text>Autograph: Graphs for complex codeIn this ungraded lab you'll go through some of the scenarios from the lesson `Creating graphs for complex code`.  Imports<jupyter_code>try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass

import tensorflow as tf<jupyter_output><empty_output><jupyter_text>As you saw in the lectures, Autograph generates complex graph code from seemingly simple functions.  - Here is a function that does some multiplication and additon.<jupyter_code>a = tf.Variable(1.0)
b = tf.Variable(2.0)

@tf.function
def f(x,y):
    a.assign(y * b)
    b.assign_add(x * a)
    return a + b

print(f(1.0, 2.0))

print(tf.autograph.to_code(f.python_function))<jupyter_output><empty_output><jupyter_text>Here is a function that checks if the sign of a number is positive or not.<jupyter_code>@tf.function
def sign(x):
  if x > 0:
    return 'Positive'
  else:
    return 'Negative or zero'

print("Sign = {}".format(sign(tf.constant(2))))
print("Sign = {}".format(sign(tf.constant(-2))))

print(tf.autograph.to_code(sign.python_function))<jupyter_output><empty_output><jupyter_text>Here is another function that includes a while loop.<jupyter_code>@tf.function
def f(x):
  while tf.reduce_sum(x) > 1:
    tf.print(x)
    x = tf.tanh(x)
  return x

#f(tf.random.uniform([5]))

print(tf.autograph.to_code(f.python_function))<jupyter_output><empty_output><jupyter_text>Here is a function that uses a for loop and an if statement.<jupyter_code>@tf.function
def sum_even(items):
  s = 0
  for c in items:
    if c % 2 > 0:
      continue
    s += c
  return s

print(tf.autograph.to_code(sum_even.python_function))<jupyter_output><empty_output><jupyter_text>Print statementsHere is a function (not decorated with @tf.function yet) that prints the value of the input parameter.  `f(2)` is called in a for loop 5 times, and then `f(3)` is called.<jupyter_code>def f(x):
  print("Traced with", x)

for i in range(5):
  f(2)
f(3)<jupyter_output><empty_output><jupyter_text>If you were to decorate this function with `@tf.function` and run it, notice that the print statement only appears once for `f(2)` even though it is called in a loop.<jupyter_code>@tf.function
def f(x):
  print("Traced with", x)

for i in range(5):
  f(2)
f(3)<jupyter_output><empty_output><jupyter_text>Now compare `print` to `tf.print`.- `tf.print` is graph aware and will run as expected in loops. Try running the same code where `tf.print()` is added in addition to the regular `print`.- Note how `tf.print` behaves compared to `print` in graph mode.<jupyter_code>@tf.function
def f(x):
  print("Traced with", x)
  # added tf.print
  tf.print("Executed with", x)

for i in range(5):
  f(2)
f(3)<jupyter_output><empty_output><jupyter_text>Avoid defining variables inside the functionThis function (not decorated yet) defines a tensor `v` and adds the input `x` to it.  Here, it runs fine.<jupyter_code>def f(x):
  v = tf.Variable(1.0)
  v.assign_add(x)
  return v

print(f(1))<jupyter_output><empty_output><jupyter_text>Now if you decorate the function with `@tf.function`.The cell below will throw an error because `tf.Variable` is defined within the function. The graph mode function should only contain operations.<jupyter_code>@tf.function
def f(x):
  v = tf.Variable(1.0)
  v.assign_add(x)
  return v
print(f(1))<jupyter_output><empty_output><jupyter_text>To get around the error above, simply move `v = tf.Variable(1.0)` to the top of the cell before the `@tf.function` decorator.<jupyter_code># define the variables outside of the decorated function
v = tf.Variable(1.0)

@tf.function
def f(x):
  return v.assign_add(x)

print(f(5))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11834319526627218, 'fraction_numerical': 0.011027434104357182, 'mean_word_length': 5.047154471544715, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '86799', 'license': 'Apache-2.0', 'n_tokens_mistral': 1330, 'n_tokens_neox': 1315, 'n_words': 399, 'path': 'Course 2 - Custom Training loops, Gradients and Distributed Training/Week 3 - Autograph/C2_W3_Lab_2-graphs-for-complex-code.ipynb', 'repo_name': 'https-deeplearning-ai/tensorflow-3-public', 'size': '3718'}