def test_ifelse(self): config1 = aesara.config.profile config2 = aesara.config.profile_memory try: aesara.config.profile = True aesara.config.profile_memory = True a, b = tt.scalars("a", "b") x, y = tt.scalars("x", "y") z = ifelse(tt.lt(a, b), x * 2, y * 2) p = aesara.ProfileStats(False, gpu_checks=False) if aesara.config.mode in ["DebugMode", "DEBUG_MODE", "FAST_COMPILE"]: m = "FAST_RUN" else: m = None f_ifelse = aesara.function( [a, b, x, y], z, profile=p, name="test_ifelse", mode=m ) val1 = 0.0 val2 = 1.0 big_mat1 = 10 big_mat2 = 11 f_ifelse(val1, val2, big_mat1, big_mat2) finally: aesara.config.profile = config1 aesara.config.profile_memory = config2
def test_shared_state0(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function( [ x, In(a, value=1.0, name="a"), In(s, value=0.0, update=s + a * x, mutable=True), ], s + a * x, ) g = function( [ x, In(a, value=1.0, name="a"), In(s, value=f.container[s], update=s - a * x, mutable=True), ], s + a * x, ) f(1, 2) assert f[s] == 2 assert g[s] == 2 g(1, 2) assert f[s] == 0 assert g[s] == 0
def test_shared_state2(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function( [ x, In(a, value=1.0, name="a"), In(s, value=0.0, update=s + a * x, mutable=False), ], s + a * x, ) g = function( [x, In(a, value=1.0, name="a"), In(s, value=f.container[s])], s + a * x ) f(1, 2) assert f[s] == 2 assert g[s] == 2 f(1, 2) assert f[s] == 4 assert g[s] == 4 g(1, 2) # has no effect on state assert f[s] == 4 assert g[s] == 4
def test_stan_grad_partial(self): # This test combines the following STAN tests: # https://github.com/stan-dev/math/blob/master/test/unit/math/prim/fun/inc_beta_dda_test.cpp # https://github.com/stan-dev/math/blob/master/test/unit/math/prim/fun/inc_beta_ddb_test.cpp # https://github.com/stan-dev/math/blob/master/test/unit/math/prim/fun/inc_beta_ddz_test.cpp a, b, z = aet.scalars("a", "b", "z") betainc_out = aet.betainc(a, b, z) betainc_grad = aet.grad(betainc_out, [a, b, z]) f_grad = function([a, b, z], betainc_grad) decimal_precision = 7 if config.floatX == "float64" else 3 for test_a, test_b, test_z, expected_dda, expected_ddb, expected_ddz in ( (1.5, 1.25, 0.001, -0.00028665637, 4.41357328e-05, 0.063300692), (1.5, 1.25, 0.5, -0.26038693947, 0.29301795, 1.1905416), (1.5, 1.25, 0.6, -0.23806757, 0.32279575, 1.23341068), (1.5, 1.25, 0.999, -0.00022264493, 0.0018969609, 0.35587692), (15000, 1.25, 0.001, 0, 0, 0), (15000, 1.25, 0.5, 0, 0, 0), (15000, 1.25, 0.6, 0, 0, 0), (15000, 1.25, 0.999, -6.59543226e-10, 2.00849793e-06, 0.009898182), (1.5, 12500, 0.001, -3.93756641e-05, 1.47821755e-09, 0.1848717), (1.5, 12500, 0.5, 0, 0, 0), (1.5, 12500, 0.6, 0, 0, 0), (1.5, 12500, 0.999, 0, 0, 0), (15000, 12500, 0.001, 0, 0, 0), (15000, 12500, 0.5, -8.72102443e-53, 9.55282792e-53, 5.01131256e-48), (15000, 12500, 0.6, -4.085621e-14, -5.5067062e-14, 1.15135267e-71), (15000, 12500, 0.999, 0, 0, 0), ): np.testing.assert_almost_equal( f_grad(test_a, test_b, test_z), [expected_dda, expected_ddb, expected_ddz], decimal=decimal_precision, )
def __init__(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") v = tt.vector("v") self.s = s self.x = x self.v = v self.e = a * x + s self.f1 = function( [ x, In(a, value=1.0, name="a"), In(s, value=0.0, update=s + a * x, mutable=True), ], s + a * x, ) self.f2 = function( [ x, In(a, value=1.0, name="a"), In(s, value=self.f1.container[s], update=s + a * x, mutable=True), ], s + a * x, )
def test_copy(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function( [ x, In(a, value=1.0, name="a"), In(s, value=0.0, update=s + a * x, mutable=True), ], s + a * x, ) g = copy.copy(f) # if they both return, assume that they return equivalent things. assert g.container[x].storage is not f.container[x].storage assert g.container[a].storage is not f.container[a].storage assert g.container[s].storage is not f.container[s].storage assert g.value[a] is f.value[a] # should not have been copied assert ( g.value[s] is not f.value[s] ) # should have been copied because it is mutable. assert not (g.value[s] != f.value[s]).any() # its contents should be identical assert f(2, 1) == g( 2 ) # they should be in sync, default value should be copied. assert f(2, 1) == g( 2 ) # they should be in sync, default value should be copied. f(1, 2) # put them out of sync assert f(1, 2) != g(1, 2) # they should not be equal anymore.
def __init__(self): x, y, z = tt.scalars("xyz") e = tt.nnet.sigmoid((x + y + z) ** 2) op = aesara.OpFromGraph([x, y, z], [e]) e2 = op(x, y, z) self.inputs = [x, y, z] self.outputs = [e2]
def test_betainc_derivative_nan(): a, b, x = at.scalars("a", "b", "x") res = betainc_der(a, b, x, True) test_func = function([a, b, x], res, mode=Mode("py")) assert not np.isnan(test_func(1, 1, 1)) assert np.isnan(test_func(1, 1, -1)) assert np.isnan(test_func(1, 1, 2)) assert np.isnan(test_func(1, -1, 1)) assert np.isnan(test_func(1, 1, -1))
def __init__(self): x, y, z = tt.scalars("xyz") e = x * y op = aesara.OpFromGraph([x, y], [e]) e2 = op(x, y) + z op2 = aesara.OpFromGraph([x, y, z], [e2]) e3 = op2(x, y, z) + z self.inputs = [x, y, z] self.outputs = [e3]
def test_deepcopy(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function( [ x, In(a, value=1.0, name="a"), In(s, value=0.0, update=s + a * x, mutable=True), ], s + a * x, ) try: g = copy.deepcopy(f) except NotImplementedError as e: if e[0].startswith("DebugMode is not picklable"): return else: raise # if they both return, assume that they return equivalent things. # print [(k,id(k)) for k in f.finder.keys()] # print [(k,id(k)) for k in g.finder.keys()] assert g.container[0].storage is not f.container[0].storage assert g.container[1].storage is not f.container[1].storage assert g.container[2].storage is not f.container[2].storage assert x not in g.container assert x not in g.value assert len(f.defaults) == len(g.defaults) assert f._check_for_aliased_inputs is g._check_for_aliased_inputs assert f.name == g.name assert f.maker.fgraph.name == g.maker.fgraph.name # print 'f.defaults = %s' % (f.defaults, ) # print 'g.defaults = %s' % (g.defaults, ) for ((f_req, f_feed, f_val), (g_req, g_feed, g_val)) in zip( f.defaults, g.defaults ): assert f_req == g_req and f_feed == g_feed and f_val == g_val assert g.value[1] is not f.value[1] # should not have been copied assert ( g.value[2] is not f.value[2] ) # should have been copied because it is mutable. assert not (g.value[2] != f.value[2]).any() # its contents should be identical assert f(2, 1) == g( 2 ) # they should be in sync, default value should be copied. assert f(2, 1) == g( 2 ) # they should be in sync, default value should be copied. f(1, 2) # put them out of sync assert f(1, 2) != g(1, 2) # they should not be equal anymore. g(1, 2) # put them back in sync assert f(3) == g(3) # They should be in sync again.
def test_callback_with_ifelse(self): a, b, c = tensor.scalars("abc") f = function( [a, b, c], ifelse(a, 2 * b, 2 * c), mode=Mode(optimizer=None, linker=vm.VM_Linker(callback=self.callback)), ) f(1, 2, 3) assert self.n_callbacks["IfElse"] == 2
def test_naming_rule1(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function([a, s], a / s) assert f(1, 2) == 0.5 assert f(2, 1) == 2.0 assert f(2, s=1) == 2.0 checkfor( self, lambda: f(q=2, s=1), TypeError ) # got unexpected keyword argument 'q' checkfor( self, lambda: f(a=2, s=1), TypeError ) # got unexpected keyword argument 'a'
def test_callback(self): a, b, c = tensor.scalars("abc") f = function( [a, b, c], (a + b) + c, mode=Mode(optimizer=None, linker=vm.VM_Linker(callback=self.callback)), ) f(1, 2, 3) assert sum(self.n_callbacks.values()) == len(f.maker.fgraph.toposort()) f(1, 2, 3) assert sum( self.n_callbacks.values()) == len(f.maker.fgraph.toposort()) * 2
def test_beta_inc_stan_grad_combined(self): # This test replicates the following STAN test: # https://github.com/stan-dev/math/blob/master/test/unit/math/prim/fun/grad_reg_inc_beta_test.cpp a, b, z = at.scalars("a", "b", "z") betainc_out = at.betainc(a, b, z) betainc_grad = at.grad(betainc_out, [a, b]) f_grad = function([a, b, z], betainc_grad) for test_a, test_b, test_z, expected_dda, expected_ddb in ( (1.0, 1.0, 1.0, 0, np.nan), (1.0, 1.0, 0.4, -0.36651629, 0.30649537), ): np.testing.assert_allclose(f_grad(test_a, test_b, test_z), [expected_dda, expected_ddb])
def test_naming_rule2(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") # x's name is ignored because it is followed by anonymous parameter a. # Ignore unused input x, as it hides the other error f = function([x, a, s], a / s, on_unused_input="ignore") assert f(9, 1, 2) == 0.5 assert f(9, 2, 1) == 2.0 assert f(9, 2, s=1) == 2.0 checkfor( self, lambda: f(x=9, a=2, s=1), TypeError ) # got unexpected keyword argument 'x' checkfor( self, lambda: f(5.0, x=9), TypeError ) # got unexpected keyword argument 'x'
def test_pickle(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function( [ x, In(a, value=1.0, name="a"), In(s, value=0.0, update=s + a * x, mutable=True), ], s + a * x, ) try: # Note that here we also test protocol 0 on purpose, since it # should work (even though one should not use it). g = pickle.loads(pickle.dumps(f, protocol=0)) g = pickle.loads(pickle.dumps(f, protocol=-1)) except NotImplementedError as e: if e[0].startswith("DebugMode is not picklable"): return else: raise # if they both return, assume that they return equivalent things. # print [(k,id(k)) for k in f.finder.keys()] # print [(k,id(k)) for k in g.finder.keys()] assert g.container[0].storage is not f.container[0].storage assert g.container[1].storage is not f.container[1].storage assert g.container[2].storage is not f.container[2].storage assert x not in g.container assert x not in g.value assert g.value[1] is not f.value[1] # should not have been copied assert ( g.value[2] is not f.value[2] ) # should have been copied because it is mutable. assert not (g.value[2] != f.value[2]).any() # its contents should be identical assert f(2, 1) == g( 2 ) # they should be in sync, default value should be copied. assert f(2, 1) == g( 2 ) # they should be in sync, default value should be copied. f(1, 2) # put them out of sync assert f(1, 2) != g(1, 2) # they should not be equal anymore.
def test_c_thunks(): a = tensor.scalars("a") b, c = tensor.vectors("bc") cases = [False] if aesara.config.cxx: cases.append(True) for c_thunks in cases: f = function( [a, b, c], ifelse(a, a * b, b * c), mode=Mode(optimizer=None, linker=vm.VM_Linker(c_thunks=c_thunks, use_cloop=False)), ) f(1, [2], [3, 2]) with pytest.raises(ValueError): f(0, [2], [3, 4]) assert any([hasattr(t, "cthunk") for t in f.fn.thunks]) == c_thunks
def test_naming_rule0(self): x, s = tt.scalars("xs") f = function([x, s], x / s) assert f(1, 2) == 0.5 assert f(2, 1) == 2.0 assert f(s=2, x=1) == 0.5 assert f(x=2, s=1) == 2.0 assert f(2, s=1) == 2.0 checkfor( self, lambda: f(2, x=2.0), TypeError ) # got multiple values for keyword argument 'x' checkfor( self, lambda: f(x=1), TypeError ) # takes exactly 2 non-keyword arguments (1 given) checkfor( self, lambda: f(s=1), TypeError ) # takes exactly 2 non-keyword arguments (0 given)
def test_weird_names(self): a, x, s = tt.scalars("xxx") checkfor(self, lambda: function([In(a, name=[])], []), TypeError) def t(): f = function( [ In(a, name={"adsf", ()}, value=1.0), In(x, name=(), value=2.0), In(s, name=tt.scalar(), value=3.0), ], a + x + s, ) return f checkfor(self, t, TypeError)
def test_gammainc_ddk_tabulated_values(): # This test replicates part of the old STAN test: # https://github.com/stan-dev/math/blob/21333bb70b669a1bd54d444ecbe1258078d33153/test/unit/math/prim/scal/fun/grad_reg_lower_inc_gamma_test.cpp k, x = at.scalars("k", "x") gammainc_out = at.gammainc(k, x) gammaincc_ddk = at.grad(gammainc_out, k) f_grad = function([k, x], gammaincc_ddk) for test_k, test_x, expected_ddk in ( (0.0001, 0, 0), # Limit condition (0.0001, 0.0001, -8.62594024578651), (0.0001, 6.2501, -0.0002705821702813008), (0.0001, 12.5001, -2.775406821933887e-7), (0.0001, 18.7501, -3.653379783274905e-10), (0.0001, 25.0001, -5.352425240798134e-13), (0.0001, 29.7501, -3.912723010174313e-15), (4.7501, 0.0001, 0), (4.7501, 6.2501, -0.1330287013623819), (4.7501, 12.5001, -0.004712176128251421), (4.7501, 18.7501, -0.00004898939126595217), (4.7501, 25.0001, -3.098781566343336e-7), (4.7501, 29.7501, -5.478399030091586e-9), (9.5001, 0.0001, -5.869126325643798e-15), (9.5001, 6.2501, -0.07717967485372858), (9.5001, 12.5001, -0.07661095137424883), (9.5001, 18.7501, -0.005594043337407605), (9.5001, 25.0001, -0.0001410123206233104), (9.5001, 29.7501, -5.75023943432906e-6), (14.2501, 0.0001, -7.24495484418588e-15), (14.2501, 6.2501, -0.003689474744087815), (14.2501, 12.5001, -0.1008796179460247), (14.2501, 18.7501, -0.05124664255610913), (14.2501, 25.0001, -0.005115177188580634), (14.2501, 29.7501, -0.0004793406401524598), (19.0001, 0.0001, -8.26027539153394e-15), (19.0001, 6.2501, -0.00003509660448733015), (19.0001, 12.5001, -0.02624562607393565), (19.0001, 18.7501, -0.0923829735092193), (19.0001, 25.0001, -0.03641281853907181), (19.0001, 29.7501, -0.007828749832965796), ): np.testing.assert_allclose(f_grad(test_k, test_x), expected_ddk, rtol=1e-5, atol=1e-14)
def test_shared_state_not_implicit(self): # This test is taken from the documentation in # doc/topics/function.txt. If it does not pass anymore and yet the # behavior is still intended the doc and the test should both be # updated accordingly. x, s = tt.scalars("xs") inc = function([x, In(s, update=(s + x), value=10.0)], []) dec = function( [x, In(s, update=(s - x), value=inc.container[s], implicit=False)], [] ) assert dec[s] is inc[s] inc[s] = 2 assert dec[s] == 2 dec(1) assert inc[s] == 1 dec(1, 0) assert inc[s] == -1 assert dec[s] == -1
def test_naming_rule4(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function([x, In(a, value=1.0, name="a"), s], a / s + x) assert f(9, 2, 4) == 9.5 # can specify all args in order assert f(9, 2, s=4) == 9.5 # can give s as kwarg assert f(9, s=4) == 9.25 # can give s as kwarg, get default a assert f(9, a=2, s=4) == 9.5 # can give s as kwarg, a as kwarg assert f(x=9, a=2, s=4) == 9.5 # can give all kwargs assert f(x=9, s=4) == 9.25 # can give all kwargs checkfor( self, lambda: f(), TypeError ) # takes exactly 3 non-keyword arguments (0 given) checkfor( self, lambda: f(5.0, x=9), TypeError ) # got multiple values for keyword argument 'x'
def test_naming_rule3(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") # x's name is not ignored (as in test_naming_rule2) because a has a default value. f = function([x, In(a, value=1.0), s], a / s + x) assert f(9, 2, 4) == 9.5 # can specify all args in order assert f(9, 2, s=4) == 9.5 # can give s as kwarg assert f(9, s=4) == 9.25 # can give s as kwarg, get default a assert f(x=9, s=4) == 9.25 # can give s as kwarg, omit a, x as kw checkfor( self, lambda: f(x=9, a=2, s=4), TypeError ) # got unexpected keyword argument 'a' checkfor( self, lambda: f(), TypeError ) # takes exactly 3 non-keyword arguments (0 given) checkfor( self, lambda: f(x=9), TypeError ) # takes exactly 3 non-keyword arguments (1 given)
def test_boik_robison_cox(self): # This test compares against the tabulated values in: # Boik, R. J., & Robison-Cox, J. F. (1998). Derivatives of the incomplete beta function. # Journal of Statistical Software, 3(1), 1-20. a, b, z = at.scalars("a", "b", "z") betainc_out = at.betainc(a, b, z) betainc_grad = at.grad(betainc_out, [a, b]) f_grad = function([a, b, z], betainc_grad) for test_a, test_b, test_z, expected_dda, expected_ddb in ( (1.5, 11.0, 0.001, -4.5720356e-03, 1.1845673e-04), (1.5, 11.0, 0.5, -2.5501997e-03, 9.0824388e-04), (1000.0, 1000.0, 0.5, -8.9224793e-03, 8.9224793e-03), (1000.0, 1000.0, 0.55, -3.6713108e-07, 4.0584118e-07), ): np.testing.assert_almost_equal( f_grad(test_a, test_b, test_z), [expected_dda, expected_ddb], )
def test_deepcopy_shared_container(self): # Ensure that shared containers remain shared after a deep copy. a, x = tt.scalars("ax") h = function([In(a, value=0.0)], a) f = function([x, In(a, value=h.container[a], implicit=True)], x + a) try: memo = {} ac = copy.deepcopy(a) memo.update({id(a): ac}) hc = copy.deepcopy(h, memo=memo) memo.update({id(h): hc}) fc = copy.deepcopy(f, memo=memo) except NotImplementedError as e: if e[0].startswith("DebugMode is not picklable"): return else: raise h[a] = 1 hc[ac] = 2 assert f[a] == 1 assert fc[ac] == 2
def test_state_access(self): a = tt.scalar() # the a is for 'anonymous' (un-named). x, s = tt.scalars("xs") f = function( [x, In(a, value=1.0, name="a"), In(s, value=0.0, update=s + a * x)], s + a * x, ) assert f[a] == 1.0 assert f[s] == 0.0 assert f(3.0) == 3.0 assert f(3.0, a=2.0) == 9.0 # 3.0 + 2*3.0 assert ( f[a] == 1.0 ) # state hasn't changed permanently, we just overrode it last line assert f[s] == 9.0 f[a] = 5.0 assert f[a] == 5.0 assert f(3.0) == 24.0 # 9 + 3*5 assert f[s] == 24.0
import time import numpy as np import aesara from aesara import tensor as tt from aesara.ifelse import ifelse a, b = tt.scalars("a", "b") x, y = tt.matrices("x", "y") z_switch = tt.switch(tt.lt(a, b), tt.mean(x), tt.mean(y)) z_lazy = ifelse(tt.lt(a, b), tt.mean(x), tt.mean(y)) f_switch = aesara.function([a, b, x, y], z_switch) f_lazyifelse = aesara.function([a, b, x, y], z_lazy) val1 = 0.0 val2 = 1.0 big_mat1 = np.ones((10000, 1000)) big_mat2 = np.ones((10000, 1000)) n_times = 10 tic = time.clock() for i in range(n_times): f_switch(val1, val2, big_mat1, big_mat2) print("time spent evaluating both values %f sec" % (time.clock() - tic)) tic = time.clock()
def test_betainc(): a, b, x = at.scalars("a", "b", "x") res = betainc(a, b, x) test_func = function([a, b, x], res, mode=Mode("py")) assert np.isclose(test_func(15, 10, 0.7), sp.betainc(15, 10, 0.7))
def fn(): x, s = tt.scalars("xs") function([s], Out(x))
def setup_method(self): self.x, self.y = tensor.scalars("x", "y") self.z = self.x + self.y self.w = 2 * self.z