Video Tutorial


How to use decorators#

Learn about the different ways to use tracing and transpilation functions.

⚠️ If you are running this notebook in Colab, you will have to install Ivy and some dependencies manually. You can do so by running the cell below ⬇️

If you want to run the notebook locally but don’t have Ivy installed just yet, you can check out the Get Started section of the docs.

[ ]:
!pip install ivy
[1]:
import ivy
import numpy as np
import tensorflow as tf
import torch

ivy.set_backend("tensorflow")

Trace#

In the example below, the ivy.trace_graph function is called as a decorator.

[ ]:
@ivy.trace_graph
def normalize(x):
    mean = ivy.mean(x)
    std = ivy.std(x, correction=1)
    return ivy.divide(ivy.subtract(x, mean), std)
[ ]:
x = tf.random.uniform((10,))
normalize(x) # tracing happens here
<tf.Tensor: shape=(10,), dtype=float64, numpy=
array([-0.34431235,  0.51129461, -0.06686894, -0.36452447, -0.98795534,
        0.15493582, -0.91630631,  1.41939619,  1.78909753, -1.19475674])>

Likewise, the function can still be called either eagerly or lazily when calling as a decorator. The example above is lazy, whereas the example below is eager:

[ ]:
@ivy.trace_graph(args=(x,))
def normalize(x):
    mean = ivy.mean(x)
    std = ivy.std(x, correction=1)
    return ivy.divide(ivy.subtract(x, mean), std)
[ ]:
normalize(x) # already traced
<tf.Tensor: shape=(10,), dtype=float64, numpy=
array([-0.34431235,  0.51129461, -0.06686894, -0.36452447, -0.98795534,
        0.15493582, -0.91630631,  1.41939619,  1.78909753, -1.19475674])>

Graph Transpile#

In the example below, the ivy.graph_transpile function is called as a decorator.

[ ]:
@ivy.graph_transpile(source="torch", to="tensorflow")
def normalize(x):
    mean = torch.mean(x)
    std = torch.std(x)
    return torch.div(torch.sub(x, mean), std)
[ ]:
normalize(x) # transpilation happens here
<tf.Tensor: shape=(10,), dtype=float64, numpy=
array([-0.34431235,  0.51129461, -0.06686894, -0.36452447, -0.98795534,
        0.15493582, -0.91630631,  1.41939619,  1.78909753, -1.19475674])>

The function can still be called either eagerly or lazily when calling as a decorator. The example above is lazy, whereas the example below is eager:

[ ]:
@ivy.graph_transpile(source="torch", to="tensorflow", args=(x,))
def normalize(x):
    mean = torch.mean(x)
    std = torch.std(x)
    return torch.div(torch.sub(x, mean), std)
[ ]:
normalize(x) # already transpiled
<tf.Tensor: shape=(10,), dtype=float64, numpy=
array([-0.34431235,  0.51129461, -0.06686894, -0.36452447, -0.98795534,
        0.15493582, -0.91630631,  1.41939619,  1.78909753, -1.19475674])>

Transpile 🚧#

In the future, ivy.transpile will be able to be used as a decorator like so:

[ ]:
@ivy.transpile(source="torch", target="tensorflow")
def normalize(x):
    mean = torch.mean(x)
    std = torch.std(x)
    return torch.div(torch.sub(x, mean), std)

# use normalize as a tensorflow function
normalize(tf.random.uniform((10,)))