def test_grad_reverse(): def f(x): return x**2 adobj = AD(f) adobj.set_mode('reverse') assert adobj.grad(2) == [[4]]
def test_sum(): def myfunc(a): return a.sum() adobj = AD(myfunc) inp = np.array([n for n in range(5)]) truth = [[1, 1, 1, 1, 1]] assert (adobj._reverse(inp) == truth).all()
def test_constant_function(): adobj = AD(lambda x: 4) assert adobj.grad(2) == [[0]]
from funkyAD.base import AD, grad def f(x, y): return x * y ad = AD(f)._reverse(4, 5) print(ad) print(AD(f).grad(4, 5))
def test_set_incorrect_set_mode(): adobj = AD(lambda x, y: x + y) with pytest.raises(ValueError): adobj.set_mode('backprop')
def test_reverse_noinfl_in(): adobj = AD(lambda x, y: x**2 + x) grad = adobj._reverse(1, 1) truth = [[3, 0]] assert (grad == truth).all()
def test_reverse_multidim_n(): adobj = AD(lambda x, y: x**2 + 2 * y) truth = [[4, 2]] assert (adobj._reverse(2, 1) == truth).all()
def test_trace_1dim(): adobj = AD(lambda x: 3) trace = adobj._buildtrace(2) assert len(trace) == 1
def test_grad(): def f(x): return x**2 assert AD(f).grad(2) == [[4]]
def test_set_seed_nonarray(): adobj = AD(lambda x: x * x) with pytest.raises(ValueError): adobj.set_seed('what')
def test_set_seed_wrong_dim(): adobj = AD(lambda x: x + 5) adobj.set_seed([2, 1]) with pytest.raises(ValueError): adobj._forward(3)
def test_set_seed(): adobj = AD(lambda x: x + 5) adobj.set_seed(5) adobj.set_seed(0) assert adobj.seed == 0
def test_grad_reverse_multidim_n(): adobj = AD(lambda x, y: x**2 + 2 * y) adobj.set_mode('reverse') truth = [[4, 2]] assert (adobj.grad(2, 1) == truth).all()
def test_noncallable_f(): with pytest.raises(TypeError): AD(5 * 5)
def test_set_incorrect_mode(): adobj = AD(lambda x, y: x + y) adobj.mode = 'backprop' with pytest.raises(ValueError): adobj.grad(1, 2)
def test_no_args(): adobj = AD(lambda x: x) with pytest.raises(TypeError): adobj._forward()
def test_usage_example(): def f(x): return exp(x) assert AD(f).grad(0) == [[1]]
def test_check_seed(): adobj = AD(lambda x: 2 * x + x**3) adobj.n = 5 adobj.set_seed([2, 1]) with pytest.raises(ValueError): adobj._check_seed(adobj.n)
def test_trace(): adobj = AD(lambda x, y: x + y) trace = adobj._buildtrace(1, 2) assert len(trace) == 3
def test_self_n(): adobj = AD(lambda x, y: x + y) adobj._forward(1, 2) assert adobj.n == 2
def test_reverse(): def f(x): return x**2 assert AD(f)._reverse(2) == [[4]]
def test_AD_string_input(): with pytest.raises(TypeError): AD('hello').grad(1)
def test_reverse_multidim_m(): adobj = AD(lambda x, y: [x + y, x**2]) grad = adobj._reverse(1, 1) truth = [[1, 1], [2, 0]] assert (grad == truth).all()
def test_multidim_n(): adobj = AD(lambda x, y: x + y) grad = adobj.grad(1, 1) truth = [[1, 1]] assert (grad == truth).all()
def test_set_mode(): adobj = AD(lambda x, y: x + y) adobj.set_mode('reverse') assert adobj.mode == 'reverse'
def test_self_m(): adobj = AD(lambda x, y: x**2 + y + y) adobj._forward(0, 0) assert adobj.m == 1
from funkyAD.base import AD, grad def cube(x): return x ** 3 print(grad(cube)(10)) print(AD(cube)._reverse(10)) from funkyAD.functions import exp def exponential(x): return exp(x) print(grad(exponential)(1)) print(AD(exponential)._reverse(1)) import numpy as np #a = np.array([1]) #print(a.__class__([4, 5])) def add(a): s = 0 for x in a: s += x return s
import time import sys import numpy as np import matplotlib.pyplot as plt from funkyAD.base import AD sys.setrecursionlimit(100000) def my_sum(a): return a.sum() ad_object = AD(my_sum) # showcase reverse better than forward when inputs increase fwd_times = [] rev_times = [] ninputs = range(1, 10000, 100) for n in range(1, 10000, 100): inp = np.array([i for i in range(n)]) start_time = time.time() ad_object._forward(inp) runtime = time.time() - start_time fwd_times.append(runtime) start_time = time.time() ad_object._reverse(inp) runtime = time.time() - start_time rev_times.append(runtime)