def test_basics(self): random = RandomStream(seed=utt.fetch_seed()) with pytest.raises(TypeError): random.uniform(0, 1, size=(2, 2), rng=np.random.RandomState(23)) with pytest.raises(AttributeError): random.blah with pytest.raises(AttributeError): np_random = RandomStream(namespace=np) np_random.ndarray fn = function([], random.uniform(0, 1, size=(2, 2)), updates=random.updates()) fn_val0 = fn() fn_val1 = fn() rng_seed = np.random.RandomState(utt.fetch_seed()).randint(2**30) rng = np.random.RandomState(int(rng_seed)) # int() is for 32bit numpy_val0 = rng.uniform(0, 1, size=(2, 2)) numpy_val1 = rng.uniform(0, 1, size=(2, 2)) assert np.allclose(fn_val0, numpy_val0) assert np.allclose(fn_val1, numpy_val1)
def test_basics(self, rng_ctor): random = RandomStream(seed=utt.fetch_seed(), rng_ctor=rng_ctor) with pytest.raises(ValueError): random.uniform(0, 1, size=(2, 2), rng=np.random.default_rng(23)) with pytest.raises(AttributeError): random.blah assert hasattr(random, "standard_normal") with pytest.raises(AttributeError): np_random = RandomStream(namespace=np, rng_ctor=rng_ctor) np_random.ndarray fn = function([], random.uniform(0, 1, size=(2, 2)), updates=random.updates()) fn_val0 = fn() fn_val1 = fn() rng_seed = np.random.SeedSequence(utt.fetch_seed()) (rng_seed, ) = rng_seed.spawn(1) rng = random.rng_ctor(rng_seed) numpy_val0 = rng.uniform(0, 1, size=(2, 2)) numpy_val1 = rng.uniform(0, 1, size=(2, 2)) assert np.allclose(fn_val0, numpy_val0) assert np.allclose(fn_val1, numpy_val1)
def test_multiple_rng_aliasing(self, rng_ctor): # Test that when we have multiple random number generators, we do not alias # the state_updates member. `state_updates` can be useful when attempting to # copy the (random) state between two similar aesara graphs. The test is # meant to detect a previous bug where state_updates was initialized as a # class-attribute, instead of the __init__ function. rng1 = RandomStream(1234, rng_ctor=rng_ctor) rng2 = RandomStream(2392, rng_ctor=rng_ctor) assert rng1.state_updates is not rng2.state_updates assert rng1.gen_seedgen is not rng2.gen_seedgen
def test_default_updates(self, rng_ctor): # Basic case: default_updates random_a = RandomStream(utt.fetch_seed(), rng_ctor=rng_ctor) out_a = random_a.uniform(0, 1, size=(2, 2)) fn_a = function([], out_a) fn_a_val0 = fn_a() fn_a_val1 = fn_a() assert not np.all(fn_a_val0 == fn_a_val1) nearly_zeros = function([], out_a + out_a - 2 * out_a) assert np.all(abs(nearly_zeros()) < 1e-5) # Explicit updates #1 random_b = RandomStream(utt.fetch_seed(), rng_ctor=rng_ctor) out_b = random_b.uniform(0, 1, size=(2, 2)) fn_b = function([], out_b, updates=random_b.updates()) fn_b_val0 = fn_b() fn_b_val1 = fn_b() assert np.all(fn_b_val0 == fn_a_val0) assert np.all(fn_b_val1 == fn_a_val1) # Explicit updates #2 random_c = RandomStream(utt.fetch_seed(), rng_ctor=rng_ctor) out_c = random_c.uniform(0, 1, size=(2, 2)) fn_c = function([], out_c, updates=random_c.state_updates) fn_c_val0 = fn_c() fn_c_val1 = fn_c() assert np.all(fn_c_val0 == fn_a_val0) assert np.all(fn_c_val1 == fn_a_val1) # No updates at all random_d = RandomStream(utt.fetch_seed(), rng_ctor=rng_ctor) out_d = random_d.uniform(0, 1, size=(2, 2)) fn_d = function([], out_d, no_default_updates=True) fn_d_val0 = fn_d() fn_d_val1 = fn_d() assert np.all(fn_d_val0 == fn_a_val0) assert np.all(fn_d_val1 == fn_d_val0) # No updates for out random_e = RandomStream(utt.fetch_seed(), rng_ctor=rng_ctor) out_e = random_e.uniform(0, 1, size=(2, 2)) fn_e = function([], out_e, no_default_updates=[random_e.state_updates[0][0]]) fn_e_val0 = fn_e() fn_e_val1 = fn_e() assert np.all(fn_e_val0 == fn_a_val0) assert np.all(fn_e_val1 == fn_e_val0)
def test_RandomStream(): srng = RandomStream(seed=123) out = srng.normal() - srng.normal() fn = function([], out, mode=jax_mode) jax_res_1 = fn() jax_res_2 = fn() assert np.array_equal(jax_res_1, jax_res_2)
def test_tutorial(self): srng = RandomStream(seed=234) rv_u = srng.uniform(0, 1, size=(2, 2)) rv_n = srng.normal(0, 1, size=(2, 2)) f = function([], rv_u) # Disabling `default_updates` means that we have to pass # `srng.state_updates` to `function` manually, if we want the shared # state to change g = function([], rv_n, no_default_updates=True) nearly_zeros = function([], rv_u + rv_u - 2 * rv_u) assert np.all(f() != f()) assert np.all(g() == g()) assert np.all(abs(nearly_zeros()) < 1e-5)
def test_uniform(self): # Test that RandomStream.uniform generates the same results as numpy # Check over two calls to see if the random state is correctly updated. random = RandomStream(utt.fetch_seed()) fn = function([], random.uniform(-1, 1, size=(2, 2))) fn_val0 = fn() fn_val1 = fn() rng_seed = np.random.RandomState(utt.fetch_seed()).randint(2**30) rng = np.random.RandomState(int(rng_seed)) # int() is for 32bit numpy_val0 = rng.uniform(-1, 1, size=(2, 2)) numpy_val1 = rng.uniform(-1, 1, size=(2, 2)) assert np.allclose(fn_val0, numpy_val0) assert np.allclose(fn_val1, numpy_val1)
def test_uniform(self, rng_ctor): # Test that RandomStream.uniform generates the same results as numpy # Check over two calls to see if the random state is correctly updated. random = RandomStream(utt.fetch_seed(), rng_ctor=rng_ctor) fn = function([], random.uniform(-1, 1, size=(2, 2))) fn_val0 = fn() fn_val1 = fn() rng_seed = np.random.SeedSequence(utt.fetch_seed()) (rng_seed, ) = rng_seed.spawn(1) rng = random.rng_ctor(rng_seed) numpy_val0 = rng.uniform(-1, 1, size=(2, 2)) numpy_val1 = rng.uniform(-1, 1, size=(2, 2)) assert np.allclose(fn_val0, numpy_val0) assert np.allclose(fn_val1, numpy_val1)
def test_seed(self): init_seed = 234 random = RandomStream(init_seed) ref_state = np.random.RandomState(init_seed).get_state() random_state = random.gen_seedgen.get_state() assert random.default_instance_seed == init_seed assert np.array_equal(random_state[1], ref_state[1]) assert random_state[0] == ref_state[0] assert random_state[2:] == ref_state[2:] new_seed = 43298 random.seed(new_seed) ref_state = np.random.RandomState(new_seed).get_state() random_state = random.gen_seedgen.get_state() assert np.array_equal(random_state[1], ref_state[1]) assert random_state[0] == ref_state[0] assert random_state[2:] == ref_state[2:] random.seed() ref_state = np.random.RandomState(init_seed).get_state() random_state = random.gen_seedgen.get_state() assert random.default_instance_seed == init_seed assert np.array_equal(random_state[1], ref_state[1]) assert random_state[0] == ref_state[0] assert random_state[2:] == ref_state[2:] # Reset the seed random.seed(new_seed) # Check state updates _ = random.normal() # Now, change the seed when there are state updates random.seed(new_seed) rng = np.random.RandomState(new_seed) update_seed = rng.randint(2**30) ref_state = np.random.RandomState(update_seed).get_state() random_state = random.state_updates[0][0].get_value( borrow=True).get_state() assert np.array_equal(random_state[1], ref_state[1]) assert random_state[0] == ref_state[0] assert random_state[2:] == ref_state[2:]
def test_seed(self, rng_ctor): init_seed = 234 random = RandomStream(init_seed, rng_ctor=rng_ctor) assert random.default_instance_seed == init_seed new_seed = 43298 random.seed(new_seed) rng_seed = np.random.SeedSequence(new_seed) assert random.gen_seedgen.entropy == rng_seed.entropy random.seed() rng_seed = np.random.SeedSequence(init_seed) assert random.gen_seedgen.entropy == rng_seed.entropy # Reset the seed random.seed(new_seed) # Check state updates _ = random.normal() # Now, change the seed when there are state updates random.seed(new_seed) update_seed = np.random.SeedSequence(new_seed) (update_seed, ) = update_seed.spawn(1) ref_rng = random.rng_ctor(update_seed) state_rng = random.state_updates[0][0].get_value(borrow=True) if hasattr(state_rng, "get_state"): ref_state = ref_rng.get_state() random_state = state_rng.get_state() assert np.array_equal(random_state[1], ref_state[1]) assert random_state[0] == ref_state[0] assert random_state[2:] == ref_state[2:] else: ref_state = ref_rng.__getstate__() random_state = state_rng.__getstate__() assert random_state["bit_generator"] == ref_state["bit_generator"] assert random_state["state"] == ref_state["state"]
def test_connection_pattern(self, cls_ofg): # Basic case x, y, z = matrices("xyz") out1 = x * y out2 = y * z op1 = cls_ofg([x, y, z], [out1, out2]) results = op1.connection_pattern(None) expect_result = [[True, False], [True, True], [False, True]] assert results == expect_result # Graph with ops that don't have a 'full' connection pattern # and with ops that have multiple outputs m, n, p, q = matrices("mnpq") o1, o2 = op1(m, n, p) out1, out2 = op1(o1, q, o2) op2 = cls_ofg([m, n, p, q], [out1, out2]) results = op2.connection_pattern(None) expect_result = [[True, False], [True, True], [False, True], [True, True]] assert results == expect_result # Inner graph where some computation doesn't rely on explicit inputs srng = RandomStream(seed=234) rv_u = srng.uniform((2, 2)) x, y = matrices("xy") out1 = x + rv_u out2 = y + 3 out3 = 3 + rv_u op3 = cls_ofg([x, y], [out1, out2, out3]) results = op3.connection_pattern(None) expect_result = [ [True, False, False], [False, True, False], [True, False, True], ] assert results == expect_result
def check_binomial(mean, size, const_size, var_input, input, steps, rtol): R = MRG_RandomStream(234) u = R.binomial(size=size, p=mean) f = function(var_input, u) f(*input) # Increase the number of steps if sizes implies only a few samples if np.prod(const_size) < 10: steps_ = steps * 100 else: steps_ = steps check_basics( f, steps_, const_size, prefix="mrg cpu", inputs=input, allow_01=True, target_avg=mean, mean_rtol=rtol, ) RR = RandomStream(234) uu = RR.binomial(1, mean, size=size) ff = function(var_input, uu) # It's not our problem if numpy generates 0 or 1 check_basics( ff, steps_, const_size, prefix="numpy", allow_01=True, inputs=input, target_avg=mean, mean_rtol=rtol, )
def __init__(self, seed=123): self.rng = RandomStream(seed, rng_ctor=rng_ctor) self.y = self.rng.uniform(0, 1, size=(1, ))
def test_normal0(): steps = 50 std = 2.0 if (config.mode in ("DEBUG_MODE", "DebugMode", "FAST_COMPILE") or config.mode == "Mode" and config.linker in ["py"]): sample_size = (25, 30) default_rtol = 0.02 else: sample_size = (999, 50) default_rtol = 0.01 sample_size_odd = (sample_size[0], sample_size[1] - 1) x = matrix() test_cases = [ (sample_size, sample_size, [], [], -5.0, default_rtol, default_rtol), ( x.shape, sample_size, [x], [np.zeros(sample_size, dtype=config.floatX)], -5.0, default_rtol, default_rtol, ), # test odd value ( x.shape, sample_size_odd, [x], [np.zeros(sample_size_odd, dtype=config.floatX)], -5.0, default_rtol, default_rtol, ), ( sample_size, sample_size, [], [], np.arange(np.prod(sample_size), dtype="float32").reshape(sample_size), 10.0 * std / np.sqrt(steps), default_rtol, ), # test empty size (scalar) ((), (), [], [], -5.0, default_rtol, 0.02), # test with few samples at the same time ((1, ), (1, ), [], [], -5.0, default_rtol, 0.02), ((3, ), (3, ), [], [], -5.0, default_rtol, 0.02), ] for size, const_size, var_input, input, avg, rtol, std_tol in test_cases: R = MRG_RandomStream(234) # Note: we specify `nstreams` to avoid a warning. n = R.normal( size=size, avg=avg, std=std, nstreams=rng_mrg.guess_n_streams(size, warn=False), ) f = function(var_input, n) f(*input) # Increase the number of steps if size implies only a few samples if np.prod(const_size) < 10: steps_ = steps * 50 else: steps_ = steps check_basics( f, steps_, const_size, target_avg=avg, target_std=std, prefix="mrg ", allow_01=True, inputs=input, mean_rtol=rtol, std_tol=std_tol, ) sys.stdout.flush() RR = RandomStream(235) nn = RR.normal(avg, std, size=size) ff = function(var_input, nn) check_basics( ff, steps_, const_size, target_avg=avg, target_std=std, prefix="numpy ", allow_01=True, inputs=input, mean_rtol=rtol, )
def test_uniform(): # TODO: test param low, high # TODO: test size=None # TODO: test ndim!=size.ndim # TODO: test bad seed # TODO: test size=Var, with shape that change from call to call if (config.mode in ("DEBUG_MODE", "DebugMode", "FAST_COMPILE") or config.mode == "Mode" and config.linker in ["py"]): sample_size = (10, 100) steps = 50 else: sample_size = (500, 50) steps = int(1e3) x = matrix() for size, const_size, var_input, input in [ (sample_size, sample_size, [], []), (x.shape, sample_size, [x], [np.zeros(sample_size, dtype=config.floatX)]), ( (x.shape[0], sample_size[1]), sample_size, [x], [np.zeros(sample_size, dtype=config.floatX)], ), # test empty size (scalar) ((), (), [], []), ]: # TEST CPU IMPLEMENTATION # The python and C implementation are tested with DebugMode x = matrix() R = MRG_RandomStream(234) # Note: we specify `nstreams` to avoid a warning. # TODO Look for all occurrences of `guess_n_streams` and `30 * 256` # for such situations: it would be better to instead filter the # warning using the warning module. u = R.uniform(size=size, nstreams=rng_mrg.guess_n_streams(size, warn=False)) f = function(var_input, u) assert any( isinstance(node.op, mrg_uniform) for node in f.maker.fgraph.toposort()) f(*input) # Increase the number of steps if sizes implies only a few samples if np.prod(const_size) < 10: steps_ = steps * 100 else: steps_ = steps check_basics(f, steps_, const_size, prefix="mrg cpu", inputs=input) RR = RandomStream(234) uu = RR.uniform(size=size) ff = function(var_input, uu) # It's not our problem if numpy generates 0 or 1 check_basics(ff, steps_, const_size, prefix="numpy", allow_01=True, inputs=input)