Introductory demo of autodiff module with the gradpy package¶
Welcome to the introductory demo for automatic differentiation with
gradpy! After you have successfully installed the gradpy package
(please refer to the
Installation
page for reference), you can follow along the commands below to get
started.
Single-variable function¶
From the main module autodiff, we will begin by importing the
elementary Var object, used to define independent variables in an
equation or model of interest. We create a Var variable \(x\)
initialized with the value 1 and use it to create a simple user-defined
function, \(f = 3x^2+5\).
In [1]:
from gradpy.autodiff import Var
x = Var(1)
f = 3*x**2 + 5
We can obtain the value and derivative of \(f\) with respect to
\(x\), evaluated at \(x=1\), by accessing the value
attribute, and calling the der method with the appropriate Var
object as its argument:
In [2]:
fval = f.value
fder = f.der(x)
print("f(x) =",fval)
print("f'(x) =",fder)
f(x) = 8
f'(x) = 6
If we do not know the value of \(x\) ahead of time, or would like to
change it later without redefining \(f\), we can do so using the
set_value method:
In [3]:
x.set_value(3)
print("f(x) =",f.value)
print("f'(x) =",f.der(x))
f(x) = 32
f'(x) = 18
Var is itself a differentiable object; thus we can also do:
In [4]:
print("x =",x.value)
print("x' =",x.der(x))
x = 3
x' = 1
Multi-variable function¶
Multi-variable functions can be defined by instantiating multiple
Var instances as independent variables.
In [5]:
a = Var()
b = Var()
c = a**2 - 2*a*b + b**2
a.set_value(2)
b.set_value(2)
print(c.value, c.der(a), c.der(b))
a.set_value(3)
b.set_value(4)
print(c.value, c.der(a), c.der(b))
0 0 0
1 -2 2
Derivatives with respect to several independent variables, comprising
the gradient of a function, can be obtained simultaneously by supplying
a list of Var objects to the grad method. The return type is a
numpy array.
In [6]:
print(c.value, c.grad([a,b]), type(c.grad([a,b])))
1 [-2 2] <class 'numpy.ndarray'>
Vector-valued function¶
Vector-valued functions can be initialized with the Array class. The
value attribute and der method of Array objects also return
numpy arrays.
In [7]:
from gradpy.autodiff import Array
t = Var(4)
vec = Array([0.5*t**2,
5*t])
print(vec.value, vec.der(t))
[ 8. 20.] [4. 5.]
Vector-valued functions can also be multi-variable:
In [8]:
import numpy as np
x = Var(3)
y = Var(2)
z = Var(1)
v = Array([-y - z,
x + 0.1*y,
0.1 + z*(x - 14)])
print(v.grad([x,y,z]))
# is equivalent to ...
print(np.array([v[0].grad([x,y,z]),
v[1].grad([x,y,z]),
v[2].grad([x,y,z])]))
# is equivalent to ...
print(np.array([[v[0].der(x), v[0].der(y), v[0].der(z)],
[v[1].der(x), v[1].der(y), v[1].der(z)],
[v[2].der(x), v[2].der(y), v[2].der(z)]]))
[[ 0. -1. -1. ]
[ 1. 0.1 0. ]
[ 1. 0. -11. ]]
[[ 0. -1. -1. ]
[ 1. 0.1 0. ]
[ 1. 0. -11. ]]
[[ 0. -1. -1. ]
[ 1. 0.1 0. ]
[ 1. 0. -11. ]]