提交 96ea23b6 authored 作者: abergeron's avatar abergeron

Merge pull request #766 from larseeri/shape_raw_random

infer_shape for random ops
...@@ -184,7 +184,8 @@ class RandomFunction(gof.Op): ...@@ -184,7 +184,8 @@ class RandomFunction(gof.Op):
else: else:
# if shape == () then it will depend on args # if shape == () then it will depend on args
# if ndim_added != 0 and shape != () then it will depend on args # if ndim_added != 0 and shape != () then it will depend on args
sample_shp = node.outputs[1].shape #Use the default infer_shape implementation.
raise tensor.ShapeError()
return [None, [sample_shp[i] for i in xrange(node.outputs[1].ndim)]] return [None, [sample_shp[i] for i in xrange(node.outputs[1].ndim)]]
......
...@@ -5,13 +5,15 @@ import numpy as N ...@@ -5,13 +5,15 @@ import numpy as N
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
from theano.tensor.raw_random import * from theano.tensor.raw_random import *
from theano.tensor import raw_random from theano.tensor import (raw_random, ivector, dvector, iscalar, dcol,
dtensor3)
from theano.tests import unittest_tools as utt
from theano import tensor from theano import tensor
from theano import compile, config, gof from theano import compile, config, gof
class T_random_function(unittest.TestCase):
class T_random_function(utt.InferShapeTester):
def setUp(self): def setUp(self):
utt.seed_rng() utt.seed_rng()
...@@ -38,21 +40,23 @@ class T_random_function(unittest.TestCase): ...@@ -38,21 +40,23 @@ class T_random_function(unittest.TestCase):
assert numpy.all(f_0 == f_1) assert numpy.all(f_0 == f_1)
def test_inplace_norun(self): def test_inplace_norun(self):
rf = RandomFunction(numpy.random.RandomState.uniform, tensor.dvector, inplace=True) rf = RandomFunction(numpy.random.RandomState.uniform, tensor.dvector,
inplace=True)
assert rf.inplace assert rf.inplace
assert getattr(rf, 'destroy_map', {}) != {} assert getattr(rf, 'destroy_map', {}) != {}
def test_args(self): def test_args(self):
"""Test that arguments to RandomFunction are honored""" """Test that arguments to RandomFunction are honored"""
rf2 = RandomFunction(numpy.random.RandomState.uniform, tensor.dvector) rf2 = RandomFunction(numpy.random.RandomState.uniform, tensor.dvector)
rf4 = RandomFunction(numpy.random.RandomState.uniform, tensor.dvector, inplace=True) rf4 = RandomFunction(numpy.random.RandomState.uniform, tensor.dvector,
inplace=True)
rng_R = random_state_type() rng_R = random_state_type()
# use make_node to override some of the self.args # use make_node to override some of the self.args
post_r2, out2 = rf2(rng_R, (4,), -2, 2) # NOT INPLACE post_r2, out2 = rf2(rng_R, (4,), -2, 2) # NOT INPLACE
post_r4, out4 = rf4(rng_R, (4,), -4, 4) # INPLACE post_r4, out4 = rf4(rng_R, (4,), -4, 4) # INPLACE
post_r2_4, out2_4 = rf2(rng_R, (4,), -4.0, 2) # NOT INPLACE post_r2_4, out2_4 = rf2(rng_R, (4, ), -4.0, 2) # NOT INPLACE
post_r2_4_4, out2_4_4 = rf2(rng_R, (4,), -4.0, 4.0) # NOT INPLACE post_r2_4_4, out2_4_4 = rf2(rng_R, (4, ), -4.0, 4.0) # NOT INPLACE
# configure out4 to be computed inplace # configure out4 to be computed inplace
# The update expression means that the random state rng_R will # The update expression means that the random state rng_R will
...@@ -79,7 +83,7 @@ class T_random_function(unittest.TestCase): ...@@ -79,7 +83,7 @@ class T_random_function(unittest.TestCase):
#print f2_4_4b #print f2_4_4b
# setting bounds is same as multiplying by 2 # setting bounds is same as multiplying by 2
assert numpy.allclose(f2*2, f4), (f2, f4) assert numpy.allclose(f2 * 2, f4), (f2, f4)
# retrieving from non-inplace generator # retrieving from non-inplace generator
# is same as inplace one for first call # is same as inplace one for first call
...@@ -104,10 +108,11 @@ class T_random_function(unittest.TestCase): ...@@ -104,10 +108,11 @@ class T_random_function(unittest.TestCase):
update=post_r2, update=post_r2,
mutable=True)], mutable=True)],
out2, out2,
mode='FAST_RUN') #DEBUG_MODE can't pass the id-based test below mode='FAST_RUN') # DEBUG_MODE can't pass the id-based
# test below
# test that the RandomState object stays the same from function call to function call, # test that the RandomState object stays the same from function call to
# but that the values returned change from call to call. # function call, but that the values returned change from call to call.
id0 = id(f[rng_R]) id0 = id(f[rng_R])
val0 = f() val0 = f()
...@@ -118,7 +123,8 @@ class T_random_function(unittest.TestCase): ...@@ -118,7 +123,8 @@ class T_random_function(unittest.TestCase):
assert not numpy.allclose(val0, val1) assert not numpy.allclose(val0, val1)
def test_no_inplace(self): def test_no_inplace(self):
"""Test that when not running inplace, the RandomState is not updated""" """Test that when not running inplace, the RandomState is
not updated"""
rf = RandomFunction('uniform', tensor.dvector) rf = RandomFunction('uniform', tensor.dvector)
rng_R = random_state_type() rng_R = random_state_type()
...@@ -135,9 +141,9 @@ class T_random_function(unittest.TestCase): ...@@ -135,9 +141,9 @@ class T_random_function(unittest.TestCase):
f2 = compile.function( f2 = compile.function(
[compile.In(rng_R, [compile.In(rng_R,
value = rng, value=rng,
update = post_r, update=post_r,
mutable = False)], mutable=False)],
[post_r, out]) [post_r, out])
rng2, val2 = f2() rng2, val2 = f2()
# rng should be in a fresh state # rng should be in a fresh state
...@@ -163,8 +169,8 @@ class T_random_function(unittest.TestCase): ...@@ -163,8 +169,8 @@ class T_random_function(unittest.TestCase):
post_out4, out4 = uniform(rng_R, (4,)) post_out4, out4 = uniform(rng_R, (4,))
# ndim specified, consistent with shape, OK # ndim specified, consistent with shape, OK
post_out1_4, out1_4 = uniform(rng_R, (4,), ndim=1) post_out1_4, out1_4 = uniform(rng_R, (4, ), ndim=1)
post_out2_4_4, out2_4_4= uniform(rng_R, (4, 4), ndim=2) post_out2_4_4, out2_4_4 = uniform(rng_R, (4, 4), ndim=2)
# ndim specified, but not compatible with shape # ndim specified, but not compatible with shape
self.assertRaises(ValueError, uniform, rng_R, (4,), ndim=2) self.assertRaises(ValueError, uniform, rng_R, (4,), ndim=2)
...@@ -206,7 +212,7 @@ class T_random_function(unittest.TestCase): ...@@ -206,7 +212,7 @@ class T_random_function(unittest.TestCase):
broadcastable=(True, True, True, False))() broadcastable=(True, True, True, False))()
post_out2, out2 = uniform(rng_R, size=None, ndim=2, low=low, high=high) post_out2, out2 = uniform(rng_R, size=None, ndim=2, low=low, high=high)
self.assertEqual(out2.ndim, 4) self.assertEqual(out2.ndim, 4)
self.assertEqual(out2.broadcastable, (True,False,True,False)) self.assertEqual(out2.broadcastable, (True, False, True, False))
g = compile.function( g = compile.function(
[low, [low,
...@@ -217,10 +223,10 @@ class T_random_function(unittest.TestCase): ...@@ -217,10 +223,10 @@ class T_random_function(unittest.TestCase):
mutable=True)], mutable=True)],
[out2], [out2],
accept_inplace=True) accept_inplace=True)
low_v = [[[3]],[[4]],[[-5]]] low_v = [[[3]], [[4]], [[-5]]]
high_v = [[[[5, 8]]]] high_v = [[[[5, 8]]]]
o2, = g(low_v, high_v) o2, = g(low_v, high_v)
self.assertEqual(o2.shape, (1,3,1,2)) self.assertEqual(o2.shape, (1, 3, 1, 2))
def test_random_function_noshape_noargs(self): def test_random_function_noshape_noargs(self):
'''Test if random_function helper works without args or shape''' '''Test if random_function helper works without args or shape'''
...@@ -230,14 +236,16 @@ class T_random_function(unittest.TestCase): ...@@ -230,14 +236,16 @@ class T_random_function(unittest.TestCase):
self.assertRaises(TypeError, permutation, rng_R, size=None, ndim=2) self.assertRaises(TypeError, permutation, rng_R, size=None, ndim=2)
def test_random_function_ndim_added(self): def test_random_function_ndim_added(self):
"""Test that random_function helper function accepts ndim_added as keyword argument""" """Test that random_function helper function accepts ndim_added as
keyword argument"""
# If using numpy's uniform distribution, ndim_added should be 0, # If using numpy's uniform distribution, ndim_added should be 0,
# because the shape provided as argument is the output shape. # because the shape provided as argument is the output shape.
# Specifying a different ndim_added will change the Op's output ndim, # Specifying a different ndim_added will change the Op's output ndim,
# so numpy.uniform will produce a result of incorrect shape, # so numpy.uniform will produce a result of incorrect shape,
# and a ValueError should be raised. # and a ValueError should be raised.
def ndim_added_deco(ndim_added): def ndim_added_deco(ndim_added):
def randomfunction(random_state, size=(), low=0.0, high=0.0, ndim=None): def randomfunction(random_state, size=(), low=0.0, high=0.0,
ndim=None):
ndim, size, bcast = raw_random._infer_ndim_bcast(ndim, size) ndim, size, bcast = raw_random._infer_ndim_bcast(ndim, size)
if ndim_added < 0: if ndim_added < 0:
bcast = bcast[:ndim_added] bcast = bcast[:ndim_added]
...@@ -245,7 +253,8 @@ class T_random_function(unittest.TestCase): ...@@ -245,7 +253,8 @@ class T_random_function(unittest.TestCase):
bcast = bcast + ((False,) * ndim_added) bcast = bcast + ((False,) * ndim_added)
assert len(bcast) == ndim + ndim_added assert len(bcast) == ndim + ndim_added
op = RandomFunction('uniform', op = RandomFunction('uniform',
tensor.TensorType(dtype='float64', broadcastable=bcast), tensor.TensorType(dtype='float64',
broadcastable=bcast),
ndim_added=ndim_added) ndim_added=ndim_added)
return op(random_state, size, low, high) return op(random_state, size, low, high)
return randomfunction return randomfunction
...@@ -257,11 +266,11 @@ class T_random_function(unittest.TestCase): ...@@ -257,11 +266,11 @@ class T_random_function(unittest.TestCase):
rng_R = random_state_type() rng_R = random_state_type()
p_uni11, uni11 = uni_1(rng_R, size=(4,)) p_uni11, uni11 = uni_1(rng_R, size=(4,))
p_uni12, uni12 = uni_1(rng_R, size=(3,4)) p_uni12, uni12 = uni_1(rng_R, size=(3, 4))
p_uni01, uni01 = uni_0(rng_R, size=(4,)) p_uni01, uni01 = uni_0(rng_R, size=(4,))
p_uni02, uni02 = uni_0(rng_R, size=(3,4)) p_uni02, uni02 = uni_0(rng_R, size=(3, 4))
p_unim11, unim11 = uni_m1(rng_R, size=(4,)) p_unim11, unim11 = uni_m1(rng_R, size=(4,))
p_unim12, unim12 = uni_m1(rng_R, size=(3,4)) p_unim12, unim12 = uni_m1(rng_R, size=(3, 4))
self.assertEqual(uni11.ndim, 2) self.assertEqual(uni11.ndim, 2)
self.assertEqual(uni12.ndim, 3) self.assertEqual(uni12.ndim, 3)
...@@ -330,12 +339,13 @@ class T_random_function(unittest.TestCase): ...@@ -330,12 +339,13 @@ class T_random_function(unittest.TestCase):
self.assertTrue(numpy.allclose(val1, numpy_val1)) self.assertTrue(numpy.allclose(val1, numpy_val1))
def test_binomial(self): def test_binomial(self):
"""Test that raw_random.binomial generates the same results as numpy.""" """Test that raw_random.binomial generates the same results
as numpy."""
# Check over two calls to see if the random state is correctly updated. # Check over two calls to see if the random state is correctly updated.
rng_R = random_state_type() rng_R = random_state_type()
# Use non-default parameters, and larger dimensions because of # Use non-default parameters, and larger dimensions because of
# the integer nature of the result # the integer nature of the result
post_r, bin = binomial(rng_R, (7,12), 5, 0.8) post_r, bin = binomial(rng_R, (7, 12), 5, 0.8)
f = compile.function( f = compile.function(
[compile.In(rng_R, [compile.In(rng_R,
...@@ -346,8 +356,8 @@ class T_random_function(unittest.TestCase): ...@@ -346,8 +356,8 @@ class T_random_function(unittest.TestCase):
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
val0 = f() val0 = f()
val1 = f() val1 = f()
numpy_val0 = numpy_rng.binomial(5, 0.8, size=(7,12)) numpy_val0 = numpy_rng.binomial(5, 0.8, size=(7, 12))
numpy_val1 = numpy_rng.binomial(5, 0.8, size=(7,12)) numpy_val1 = numpy_rng.binomial(5, 0.8, size=(7, 12))
print val0 print val0
print numpy_val0 print numpy_val0
print val1 print val1
...@@ -360,7 +370,7 @@ class T_random_function(unittest.TestCase): ...@@ -360,7 +370,7 @@ class T_random_function(unittest.TestCase):
# Check over two calls to see if the random state is correctly updated. # Check over two calls to see if the random state is correctly updated.
rng_R = random_state_type() rng_R = random_state_type()
# Use non-default parameters # Use non-default parameters
post_r, out = normal(rng_R, (2,3), 4.0, 2.0) post_r, out = normal(rng_R, (2, 3), 4.0, 2.0)
f = compile.function( f = compile.function(
[compile.In(rng_R, [compile.In(rng_R,
...@@ -371,8 +381,8 @@ class T_random_function(unittest.TestCase): ...@@ -371,8 +381,8 @@ class T_random_function(unittest.TestCase):
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
val0 = f() val0 = f()
val1 = f() val1 = f()
numpy_val0 = numpy_rng.normal(4.0, 2.0, size=(2,3)) numpy_val0 = numpy_rng.normal(4.0, 2.0, size=(2, 3))
numpy_val1 = numpy_rng.normal(4.0, 2.0, size=(2,3)) numpy_val1 = numpy_rng.normal(4.0, 2.0, size=(2, 3))
print val0 print val0
print numpy_val0 print numpy_val0
print val1 print val1
...@@ -381,12 +391,13 @@ class T_random_function(unittest.TestCase): ...@@ -381,12 +391,13 @@ class T_random_function(unittest.TestCase):
self.assertTrue(numpy.allclose(val1, numpy_val1)) self.assertTrue(numpy.allclose(val1, numpy_val1))
def test_random_integers(self): def test_random_integers(self):
"""Test that raw_random.random_integers generates the same results as numpy.""" """Test that raw_random.random_integers generates the same
results as numpy."""
# Check over two calls to see if the random state is correctly updated. # Check over two calls to see if the random state is correctly updated.
rng_R = random_state_type() rng_R = random_state_type()
# Use non-default parameters, and larger dimensions because of # Use non-default parameters, and larger dimensions because of
# the integer nature of the result # the integer nature of the result
post_r, out = random_integers(rng_R, (11,8), -3, 16) post_r, out = random_integers(rng_R, (11, 8), -3, 16)
f = compile.function( f = compile.function(
[compile.In(rng_R, [compile.In(rng_R,
...@@ -397,8 +408,8 @@ class T_random_function(unittest.TestCase): ...@@ -397,8 +408,8 @@ class T_random_function(unittest.TestCase):
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
val0 = f() val0 = f()
val1 = f() val1 = f()
numpy_val0 = numpy_rng.random_integers(-3, 16, size=(11,8)) numpy_val0 = numpy_rng.random_integers(-3, 16, size=(11, 8))
numpy_val1 = numpy_rng.random_integers(-3, 16, size=(11,8)) numpy_val1 = numpy_rng.random_integers(-3, 16, size=(11, 8))
print val0 print val0
print numpy_val0 print numpy_val0
print val1 print val1
...@@ -407,14 +418,16 @@ class T_random_function(unittest.TestCase): ...@@ -407,14 +418,16 @@ class T_random_function(unittest.TestCase):
self.assertTrue(numpy.allclose(val1, numpy_val1)) self.assertTrue(numpy.allclose(val1, numpy_val1))
def test_permutation_helper(self): def test_permutation_helper(self):
"""Test that raw_random.permutation_helper generates the same results as numpy, """Test that raw_random.permutation_helper generates the same
results as numpy,
and that the 'ndim_added' keyword behaves correctly.""" and that the 'ndim_added' keyword behaves correctly."""
# permutation_helper needs "ndim_added=1", because its output # permutation_helper needs "ndim_added=1", because its output
# is one dimension more than its "shape" argument (and there's # is one dimension more than its "shape" argument (and there's
# no way to determine that automatically). # no way to determine that automatically).
# Check the working case, over two calls to see if the random # Check the working case, over two calls to see if the random
# state is correctly updated. # state is correctly updated.
rf = RandomFunction(permutation_helper, tensor.imatrix, 8, ndim_added=1) rf = RandomFunction(permutation_helper, tensor.imatrix, 8,
ndim_added=1)
rng_R = random_state_type() rng_R = random_state_type()
post_r, out = rf(rng_R, (7,), 8) post_r, out = rf(rng_R, (7,), 8)
...@@ -429,8 +442,10 @@ class T_random_function(unittest.TestCase): ...@@ -429,8 +442,10 @@ class T_random_function(unittest.TestCase):
val1 = f() val1 = f()
# numpy_rng.permutation outputs one vector at a time, # numpy_rng.permutation outputs one vector at a time,
# so we call it iteratively to generate all the samples. # so we call it iteratively to generate all the samples.
numpy_val0 = numpy.asarray([numpy_rng.permutation(8) for i in range(7)]) numpy_val0 = numpy.asarray([numpy_rng.permutation(8)
numpy_val1 = numpy.asarray([numpy_rng.permutation(8) for i in range(7)]) for i in range(7)])
numpy_val1 = numpy.asarray([numpy_rng.permutation(8)
for i in range(7)])
print val0 print val0
print numpy_val0 print numpy_val0
print val1 print val1
...@@ -450,7 +465,8 @@ class T_random_function(unittest.TestCase): ...@@ -450,7 +465,8 @@ class T_random_function(unittest.TestCase):
self.assertRaises(ValueError, f0) self.assertRaises(ValueError, f0)
# Here, ndim_added is 2 instead of 1. A ValueError should be raised. # Here, ndim_added is 2 instead of 1. A ValueError should be raised.
rf2 = RandomFunction(permutation_helper, tensor.imatrix, 8, ndim_added=2) rf2 = RandomFunction(permutation_helper, tensor.imatrix, 8,
ndim_added=2)
post_r2, out2 = rf2(rng_R, (7,), 8) post_r2, out2 = rf2(rng_R, (7,), 8)
f2 = compile.function( f2 = compile.function(
[compile.In(rng_R, [compile.In(rng_R,
...@@ -460,7 +476,8 @@ class T_random_function(unittest.TestCase): ...@@ -460,7 +476,8 @@ class T_random_function(unittest.TestCase):
self.assertRaises(ValueError, f2) self.assertRaises(ValueError, f2)
def test_permutation(self): def test_permutation(self):
"""Test that raw_random.permutation generates the same results as numpy.""" """Test that raw_random.permutation generates the same
results as numpy."""
rng_R = random_state_type() rng_R = random_state_type()
post_r, out = permutation(rng_R, size=(9,), n=6) post_r, out = permutation(rng_R, size=(9,), n=6)
print 'OUT NDIM', out.ndim print 'OUT NDIM', out.ndim
...@@ -476,8 +493,10 @@ class T_random_function(unittest.TestCase): ...@@ -476,8 +493,10 @@ class T_random_function(unittest.TestCase):
# so we call it iteratively to generate all the samples. # so we call it iteratively to generate all the samples.
val0 = f() val0 = f()
val1 = f() val1 = f()
numpy_val0 = numpy.asarray([numpy_rng.permutation(6) for i in range(9)]) numpy_val0 = numpy.asarray([numpy_rng.permutation(6)
numpy_val1 = numpy.asarray([numpy_rng.permutation(6) for i in range(9)]) for i in range(9)])
numpy_val1 = numpy.asarray([numpy_rng.permutation(6)
for i in range(9)])
print val0 print val0
print numpy_val0 print numpy_val0
print val1 print val1
...@@ -486,10 +505,11 @@ class T_random_function(unittest.TestCase): ...@@ -486,10 +505,11 @@ class T_random_function(unittest.TestCase):
self.assertTrue(numpy.all(val1 == numpy_val1)) self.assertTrue(numpy.all(val1 == numpy_val1))
def test_multinomial(self): def test_multinomial(self):
"""Test that raw_random.multinomial generates the same results as numpy.""" """Test that raw_random.multinomial generates the same
results as numpy."""
# Check over two calls to see if the random state is correctly updated. # Check over two calls to see if the random state is correctly updated.
rng_R = random_state_type() rng_R = random_state_type()
post_r, out = multinomial(rng_R, (7,3), 6, [0.2]*5) post_r, out = multinomial(rng_R, (7, 3), 6, [0.2] * 5)
f = compile.function( f = compile.function(
[compile.In(rng_R, [compile.In(rng_R,
...@@ -500,8 +520,8 @@ class T_random_function(unittest.TestCase): ...@@ -500,8 +520,8 @@ class T_random_function(unittest.TestCase):
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
val0, = f() val0, = f()
val1, = f() val1, = f()
numpy_val0 = numpy_rng.multinomial(6, [0.2]*5, (7,3)) numpy_val0 = numpy_rng.multinomial(6, [0.2] * 5, (7, 3))
numpy_val1 = numpy_rng.multinomial(6, [0.2]*5, (7,3)) numpy_val1 = numpy_rng.multinomial(6, [0.2] * 5, (7, 3))
print val0 print val0
print numpy_val0 print numpy_val0
print val1 print val1
...@@ -509,9 +529,8 @@ class T_random_function(unittest.TestCase): ...@@ -509,9 +529,8 @@ class T_random_function(unittest.TestCase):
self.assertTrue(numpy.all(val0 == numpy_val0)) self.assertTrue(numpy.all(val0 == numpy_val0))
self.assertTrue(numpy.all(val1 == numpy_val1)) self.assertTrue(numpy.all(val1 == numpy_val1))
self.assertTrue(val0.shape == (7,3,5)) self.assertTrue(val0.shape == (7, 3, 5))
self.assertTrue(val1.shape == (7,3,5)) self.assertTrue(val1.shape == (7, 3, 5))
def test_symbolic_shape(self): def test_symbolic_shape(self):
rng_R = random_state_type() rng_R = random_state_type()
...@@ -520,11 +539,11 @@ class T_random_function(unittest.TestCase): ...@@ -520,11 +539,11 @@ class T_random_function(unittest.TestCase):
f = compile.function([rng_R, shape], out) f = compile.function([rng_R, shape], out)
rng_state0 = numpy.random.RandomState(utt.fetch_seed()) rng_state0 = numpy.random.RandomState(utt.fetch_seed())
assert f(rng_state0, [2,3]).shape == (2,3) assert f(rng_state0, [2, 3]).shape == (2, 3)
assert f(rng_state0, [4,8]).shape == (4,8) assert f(rng_state0, [4, 8]).shape == (4, 8)
self.assertRaises(ValueError, f, rng_state0, [4]) self.assertRaises(ValueError, f, rng_state0, [4])
self.assertRaises(ValueError, f, rng_state0, [4,3,4,5]) self.assertRaises(ValueError, f, rng_state0, [4, 3, 4, 5])
def test_default_shape(self): def test_default_shape(self):
rng_R = random_state_type() rng_R = random_state_type()
...@@ -535,8 +554,10 @@ class T_random_function(unittest.TestCase): ...@@ -535,8 +554,10 @@ class T_random_function(unittest.TestCase):
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
post0, val0 = f(rng_state0) post0, val0 = f(rng_state0)
post1, val1 = f(post0) post1, val1 = f(post0)
numpy_val0 = numpy.asarray(numpy_rng.uniform(), dtype=theano.config.floatX) numpy_val0 = numpy.asarray(numpy_rng.uniform(),
numpy_val1 = numpy.asarray(numpy_rng.uniform(), dtype=theano.config.floatX) dtype=theano.config.floatX)
numpy_val1 = numpy.asarray(numpy_rng.uniform(),
dtype=theano.config.floatX)
assert numpy.all(val0 == numpy_val0) assert numpy.all(val0 == numpy_val0)
assert numpy.all(val1 == numpy_val1) assert numpy.all(val1 == numpy_val1)
...@@ -572,7 +593,8 @@ class T_random_function(unittest.TestCase): ...@@ -572,7 +593,8 @@ class T_random_function(unittest.TestCase):
high = tensor.vector() high = tensor.vector()
post_rb, outb = uniform(rng_R, low=low, high=high) post_rb, outb = uniform(rng_R, low=low, high=high)
assert outb.ndim == 1 assert outb.ndim == 1
fb = compile.function([rng_R, low, high], [post_rb, outb], accept_inplace=True) fb = compile.function([rng_R, low, high], [post_rb, outb],
accept_inplace=True)
post0b, val0b = fb(post1, [-4., -2], [-1, 0]) post0b, val0b = fb(post1, [-4., -2], [-1, 0])
post1b, val1b = fb(post0b, [-4.], [-1]) post1b, val1b = fb(post0b, [-4.], [-1])
...@@ -586,7 +608,8 @@ class T_random_function(unittest.TestCase): ...@@ -586,7 +608,8 @@ class T_random_function(unittest.TestCase):
size = tensor.lvector() size = tensor.lvector()
post_rc, outc = uniform(rng_R, low=low, high=high, size=size, ndim=1) post_rc, outc = uniform(rng_R, low=low, high=high, size=size, ndim=1)
fc = compile.function([rng_R, low, high, size], [post_rc, outc], accept_inplace=True) fc = compile.function([rng_R, low, high, size], [post_rc, outc],
accept_inplace=True)
post0c, val0c = fc(post1b, [-4., -2], [-1, 0], [2]) post0c, val0c = fc(post1b, [-4., -2], [-1, 0], [2])
post1c, val1c = fc(post0c, [-4.], [-1], [1]) post1c, val1c = fc(post0c, [-4.], [-1], [1])
numpy_val0c = as_floatX(numpy_rng.uniform(low=[-4., -2], high=[-1, 0])) numpy_val0c = as_floatX(numpy_rng.uniform(low=[-4., -2], high=[-1, 0]))
...@@ -594,8 +617,8 @@ class T_random_function(unittest.TestCase): ...@@ -594,8 +617,8 @@ class T_random_function(unittest.TestCase):
assert numpy.all(val0c == numpy_val0c) assert numpy.all(val0c == numpy_val0c)
assert numpy.all(val1c == numpy_val1c) assert numpy.all(val1c == numpy_val1c)
self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1, 0], [1]) self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1, 0], [1])
self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1, 0], [1,2]) self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1, 0], [1, 2])
self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1, 0], [2,1]) self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1, 0], [2, 1])
self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1], [1]) self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1], [1])
#TODO: do we want that? #TODO: do we want that?
#self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1], [2]) #self.assertRaises(ValueError, fc, post1c, [-4., -2], [-1], [2])
...@@ -606,7 +629,8 @@ class T_random_function(unittest.TestCase): ...@@ -606,7 +629,8 @@ class T_random_function(unittest.TestCase):
high = tensor.dcol() high = tensor.dcol()
post_r, out = uniform(rng_R, low=low, high=high) post_r, out = uniform(rng_R, low=low, high=high)
assert out.ndim == 2 assert out.ndim == 2
f = compile.function([rng_R, low, high], [post_r, out], accept_inplace=True) f = compile.function([rng_R, low, high], [post_r, out],
accept_inplace=True)
rng_state0 = numpy.random.RandomState(utt.fetch_seed()) rng_state0 = numpy.random.RandomState(utt.fetch_seed())
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
...@@ -616,7 +640,8 @@ class T_random_function(unittest.TestCase): ...@@ -616,7 +640,8 @@ class T_random_function(unittest.TestCase):
numpy_val0 = numpy_rng.uniform(low=[-5, .5, 0, 1], high=[1.]) numpy_val0 = numpy_rng.uniform(low=[-5, .5, 0, 1], high=[1.])
numpy_val1 = numpy_rng.uniform(low=[.9], high=[[1.], [1.1], [1.5]]) numpy_val1 = numpy_rng.uniform(low=[.9], high=[[1.], [1.1], [1.5]])
numpy_val2 = numpy_rng.uniform(low=[-5, .5, 0, 1], high=[[1.], [1.1], [1.5]]) numpy_val2 = numpy_rng.uniform(low=[-5, .5, 0, 1],
high=[[1.], [1.1], [1.5]])
assert numpy.all(val0 == numpy_val0), (val0, numpy_val0) assert numpy.all(val0 == numpy_val0), (val0, numpy_val0)
assert numpy.all(val1 == numpy_val1) assert numpy.all(val1 == numpy_val1)
...@@ -628,7 +653,8 @@ class T_random_function(unittest.TestCase): ...@@ -628,7 +653,8 @@ class T_random_function(unittest.TestCase):
high = tensor.vector() high = tensor.vector()
post_r, out = uniform(rng_R, low=low, high=high) post_r, out = uniform(rng_R, low=low, high=high)
assert out.ndim == 1 assert out.ndim == 1
f = compile.function([rng_R, low, high], [post_r, out], accept_inplace=True) f = compile.function([rng_R, low, high], [post_r, out],
accept_inplace=True)
def as_floatX(thing): def as_floatX(thing):
return numpy.asarray(thing, dtype=theano.config.floatX) return numpy.asarray(thing, dtype=theano.config.floatX)
...@@ -644,7 +670,8 @@ class T_random_function(unittest.TestCase): ...@@ -644,7 +670,8 @@ class T_random_function(unittest.TestCase):
# arguments of size (2,) # arguments of size (2,)
rng1, val1 = f(rng0, low_val[:-1], high_val[:-1]) rng1, val1 = f(rng0, low_val[:-1], high_val[:-1])
numpy_val1 = as_floatX(numpy_rng.uniform(low=low_val[:-1], high=high_val[:-1])) numpy_val1 = as_floatX(numpy_rng.uniform(low=low_val[:-1],
high=high_val[:-1]))
assert numpy.all(val1 == numpy_val1) assert numpy.all(val1 == numpy_val1)
# Specifying the size explicitly # Specifying the size explicitly
...@@ -652,7 +679,8 @@ class T_random_function(unittest.TestCase): ...@@ -652,7 +679,8 @@ class T_random_function(unittest.TestCase):
uniform(rng_R, low=low, high=high, size=(3,)), uniform(rng_R, low=low, high=high, size=(3,)),
accept_inplace=True) accept_inplace=True)
rng2, val2 = g(rng1, low_val, high_val) rng2, val2 = g(rng1, low_val, high_val)
numpy_val2 = as_floatX(numpy_rng.uniform(low=low_val, high=high_val, size=(3,))) numpy_val2 = as_floatX(numpy_rng.uniform(low=low_val, high=high_val,
size=(3,)))
assert numpy.all(val2 == numpy_val2) assert numpy.all(val2 == numpy_val2)
self.assertRaises(ValueError, g, rng2, low_val[:-1], high_val[:-1]) self.assertRaises(ValueError, g, rng2, low_val[:-1], high_val[:-1])
...@@ -662,7 +690,8 @@ class T_random_function(unittest.TestCase): ...@@ -662,7 +690,8 @@ class T_random_function(unittest.TestCase):
prob = tensor.vector() prob = tensor.vector()
post_r, out = binomial(rng_R, n=n, p=prob) post_r, out = binomial(rng_R, n=n, p=prob)
assert out.ndim == 1 assert out.ndim == 1
f = compile.function([rng_R, n, prob], [post_r, out], accept_inplace=True) f = compile.function([rng_R, n, prob], [post_r, out],
accept_inplace=True)
n_val = [1, 2, 3] n_val = [1, 2, 3]
prob_val = numpy.asarray([.1, .2, .3], dtype=config.floatX) prob_val = numpy.asarray([.1, .2, .3], dtype=config.floatX)
...@@ -694,7 +723,8 @@ class T_random_function(unittest.TestCase): ...@@ -694,7 +723,8 @@ class T_random_function(unittest.TestCase):
std = tensor.vector() std = tensor.vector()
post_r, out = normal(rng_R, avg=avg, std=std) post_r, out = normal(rng_R, avg=avg, std=std)
assert out.ndim == 1 assert out.ndim == 1
f = compile.function([rng_R, avg, std], [post_r, out], accept_inplace=True) f = compile.function([rng_R, avg, std], [post_r, out],
accept_inplace=True)
def as_floatX(thing): def as_floatX(thing):
return numpy.asarray(thing, dtype=theano.config.floatX) return numpy.asarray(thing, dtype=theano.config.floatX)
...@@ -712,7 +742,8 @@ class T_random_function(unittest.TestCase): ...@@ -712,7 +742,8 @@ class T_random_function(unittest.TestCase):
# arguments of size (2,) # arguments of size (2,)
rng1, val1 = f(rng0, avg_val[:-1], std_val[:-1]) rng1, val1 = f(rng0, avg_val[:-1], std_val[:-1])
numpy_val1 = numpy.asarray(numpy_rng.normal(loc=avg_val[:-1], scale=std_val[:-1]), numpy_val1 = numpy.asarray(numpy_rng.normal(loc=avg_val[:-1],
scale=std_val[:-1]),
dtype=theano.config.floatX) dtype=theano.config.floatX)
assert numpy.all(val1 == numpy_val1) assert numpy.all(val1 == numpy_val1)
...@@ -721,7 +752,8 @@ class T_random_function(unittest.TestCase): ...@@ -721,7 +752,8 @@ class T_random_function(unittest.TestCase):
normal(rng_R, avg=avg, std=std, size=(3,)), normal(rng_R, avg=avg, std=std, size=(3,)),
accept_inplace=True) accept_inplace=True)
rng2, val2 = g(rng1, avg_val, std_val) rng2, val2 = g(rng1, avg_val, std_val)
numpy_val2 = numpy.asarray(numpy_rng.normal(loc=avg_val, scale=std_val, size=(3,)), numpy_val2 = numpy.asarray(numpy_rng.normal(loc=avg_val, scale=std_val,
size=(3,)),
dtype=theano.config.floatX) dtype=theano.config.floatX)
assert numpy.all(val2 == numpy_val2) assert numpy.all(val2 == numpy_val2)
self.assertRaises(ValueError, g, rng2, avg_val[:-1], std_val[:-1]) self.assertRaises(ValueError, g, rng2, avg_val[:-1], std_val[:-1])
...@@ -732,7 +764,8 @@ class T_random_function(unittest.TestCase): ...@@ -732,7 +764,8 @@ class T_random_function(unittest.TestCase):
high = tensor.lvector() high = tensor.lvector()
post_r, out = random_integers(rng_R, low=low, high=high) post_r, out = random_integers(rng_R, low=low, high=high)
assert out.ndim == 1 assert out.ndim == 1
f = compile.function([rng_R, low, high], [post_r, out], accept_inplace=True) f = compile.function([rng_R, low, high], [post_r, out],
accept_inplace=True)
low_val = [100, 200, 300] low_val = [100, 200, 300]
high_val = [110, 220, 330] high_val = [110, 220, 330]
...@@ -770,7 +803,8 @@ class T_random_function(unittest.TestCase): ...@@ -770,7 +803,8 @@ class T_random_function(unittest.TestCase):
pvals = tensor.matrix() pvals = tensor.matrix()
post_r, out = multinomial(rng_R, n=n, pvals=pvals) post_r, out = multinomial(rng_R, n=n, pvals=pvals)
assert out.ndim == 2 assert out.ndim == 2
f = compile.function([rng_R, n, pvals], [post_r, out], accept_inplace=True) f = compile.function([rng_R, n, pvals], [post_r, out],
accept_inplace=True)
n_val = [1, 2, 3] n_val = [1, 2, 3]
pvals_val = [[.1, .9], [.2, .8], [.3, .7]] pvals_val = [[.1, .9], [.2, .8], [.3, .7]]
...@@ -800,18 +834,18 @@ class T_random_function(unittest.TestCase): ...@@ -800,18 +834,18 @@ class T_random_function(unittest.TestCase):
assert numpy.all(val2 == numpy_val2) assert numpy.all(val2 == numpy_val2)
self.assertRaises(ValueError, g, rng2, n_val[:-1], pvals_val[:-1]) self.assertRaises(ValueError, g, rng2, n_val[:-1], pvals_val[:-1])
def test_multinomial_tensor3_a(self): def test_multinomial_tensor3_a(self):
# Test the examples given in the multinomial documentation regarding # Test the examples given in the multinomial documentation regarding
# tensor3 objects # tensor3 objects
rng_R = random_state_type() rng_R = random_state_type()
n = 9 n = 9
pvals = tensor.dtensor3() pvals = tensor.dtensor3()
post_r, out = multinomial(rng_R, n=n, pvals=pvals, size=(1,-1)) post_r, out = multinomial(rng_R, n=n, pvals=pvals, size=(1, -1))
assert out.ndim == 3 assert out.ndim == 3
assert out.broadcastable==(True, False, False) assert out.broadcastable == (True, False, False)
f = compile.function([rng_R, pvals], [post_r, out], accept_inplace=True) f = compile.function([rng_R, pvals], [post_r, out],
accept_inplace=True)
rng = numpy.random.RandomState(utt.fetch_seed()) rng = numpy.random.RandomState(utt.fetch_seed())
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
...@@ -820,7 +854,7 @@ class T_random_function(unittest.TestCase): ...@@ -820,7 +854,7 @@ class T_random_function(unittest.TestCase):
assert pvals_val.shape == (1, 3, 2) assert pvals_val.shape == (1, 3, 2)
new_rng, draw = f(rng, pvals_val) new_rng, draw = f(rng, pvals_val)
assert draw.shape==(1,3,2) assert draw.shape == (1, 3, 2)
assert numpy.allclose(draw.sum(axis=2), 9) assert numpy.allclose(draw.sum(axis=2), 9)
def test_multinomial_tensor3_b(self): def test_multinomial_tensor3_b(self):
...@@ -829,11 +863,12 @@ class T_random_function(unittest.TestCase): ...@@ -829,11 +863,12 @@ class T_random_function(unittest.TestCase):
rng_R = random_state_type() rng_R = random_state_type()
n = 9 n = 9
pvals = tensor.dtensor3() pvals = tensor.dtensor3()
post_r, out = multinomial(rng_R, n=n, pvals=pvals, size=(10, 1,-1)) post_r, out = multinomial(rng_R, n=n, pvals=pvals, size=(10, 1, -1))
assert out.ndim == 4 assert out.ndim == 4
assert out.broadcastable==(False, True, False, False) assert out.broadcastable == (False, True, False, False)
f = compile.function([rng_R, pvals], [post_r, out], accept_inplace=True) f = compile.function([rng_R, pvals], [post_r, out],
accept_inplace=True)
rng = numpy.random.RandomState(utt.fetch_seed()) rng = numpy.random.RandomState(utt.fetch_seed())
numpy_rng = numpy.random.RandomState(utt.fetch_seed()) numpy_rng = numpy.random.RandomState(utt.fetch_seed())
...@@ -842,15 +877,15 @@ class T_random_function(unittest.TestCase): ...@@ -842,15 +877,15 @@ class T_random_function(unittest.TestCase):
assert pvals_val.shape == (1, 3, 2) assert pvals_val.shape == (1, 3, 2)
out_rng, draw = f(rng, pvals_val) out_rng, draw = f(rng, pvals_val)
assert draw.shape==(10,1,3,2) assert draw.shape == (10, 1, 3, 2)
assert numpy.allclose(draw.sum(axis=3), 9) assert numpy.allclose(draw.sum(axis=3), 9)
def test_dtype(self): def test_dtype(self):
rng_R = random_state_type() rng_R = random_state_type()
low = tensor.lscalar() low = tensor.lscalar()
high = tensor.lscalar() high = tensor.lscalar()
post_r, out = random_integers(rng_R, low=low, high=high, size=(20,), dtype='int8') post_r, out = random_integers(rng_R, low=low, high=high, size=(20, ),
dtype='int8')
assert out.dtype == 'int8' assert out.dtype == 'int8'
f = compile.function([rng_R, low, high], [post_r, out]) f = compile.function([rng_R, low, high], [post_r, out])
...@@ -862,7 +897,6 @@ class T_random_function(unittest.TestCase): ...@@ -862,7 +897,6 @@ class T_random_function(unittest.TestCase):
assert val1.dtype == 'int8' assert val1.dtype == 'int8'
assert numpy.all(abs(val1) <= 1) assert numpy.all(abs(val1) <= 1)
def test_dtype_normal_uniform_687(self): def test_dtype_normal_uniform_687(self):
# Regression test for #687. # Regression test for #687.
rng_R = random_state_type() rng_R = random_state_type()
...@@ -872,6 +906,174 @@ class T_random_function(unittest.TestCase): ...@@ -872,6 +906,174 @@ class T_random_function(unittest.TestCase):
assert normal(rng_R, avg=tensor.constant(0, dtype='float64'), assert normal(rng_R, avg=tensor.constant(0, dtype='float64'),
dtype='float32')[1].dtype == 'float32' dtype='float32')[1].dtype == 'float32'
def setUp(self):
super(T_random_function, self).setUp()
def test_infer_shape(self):
rng_R = random_state_type()
rng_R_val = numpy.random.RandomState(utt.fetch_seed())
# no shape specified, default args
post_r, out = uniform(rng_R)
self._compile_and_check([rng_R], [out], [rng_R_val],
RandomFunction)
post_r, out = uniform(rng_R, size=None, ndim=2)
self._compile_and_check([rng_R], [out], [rng_R_val],
RandomFunction)
"""
#infer_shape don't work for multinomial.
#The parameter ndim_added is set to 1 and in this case, the infer_shape
#inplementation don't know how to infer the shape
post_r, out = multinomial(rng_R)
self._compile_and_check([rng_R], [out], [rng_R_val],
RandomFunction)
"""
# no shape specified, args have to be broadcasted
low = tensor.TensorType(dtype='float64',
broadcastable=(False, True, True))()
high = tensor.TensorType(dtype='float64',
broadcastable=(True, True, True, False))()
post_r, out = uniform(rng_R, size=None, ndim=2, low=low, high=high)
low_val = [[[3]], [[4]], [[-5]]]
high_val = [[[[5, 8]]]]
self._compile_and_check([rng_R, low, high], [out],
[rng_R_val, low_val, high_val],
RandomFunction)
# multinomial, specified shape
"""
#infer_shape don't work for multinomial
n = iscalar()
pvals = dvector()
size_val = (7, 3)
n_val = 6
pvals_val = [0.2] * 5
post_r, out = multinomial(rng_R, size=size_val, n=n, pvals=pvals,
ndim=2)
self._compile_and_check([rng_R, n, pvals], [out],
[rng_R_val, n_val, pvals_val],
RandomFunction)
"""
# uniform vector low and high
low = dvector()
high = dvector()
post_r, out = uniform(rng_R, low=low, high=1)
low_val = [-5, .5, 0, 1]
self._compile_and_check([rng_R, low], [out], [rng_R_val, low_val],
RandomFunction)
low_val = [.9]
self._compile_and_check([rng_R, low], [out], [rng_R_val, low_val],
RandomFunction)
post_r, out = uniform(rng_R, low=low, high=high)
low_val = [-4., -2]
high_val = [-1, 0]
self._compile_and_check([rng_R, low, high], [out], [rng_R_val, low_val,
high_val], RandomFunction)
low_val = [-4.]
high_val = [-1]
self._compile_and_check([rng_R, low, high], [out], [rng_R_val, low_val,
high_val], RandomFunction)
# uniform broadcasting low and high
low = dvector()
high = dcol()
post_r, out = uniform(rng_R, low=low, high=high)
low_val = [-5, .5, 0, 1]
high_val = [[1.]]
self._compile_and_check([rng_R, low, high], [out], [rng_R_val, low_val,
high_val], RandomFunction)
low_val = [.9]
high_val = [[1.], [1.1], [1.5]]
self._compile_and_check([rng_R, low, high], [out], [rng_R_val, low_val,
high_val], RandomFunction)
low_val = [-5, .5, 0, 1]
high_val = [[1.], [1.1], [1.5]]
self._compile_and_check([rng_R, low, high], [out], [rng_R_val, low_val,
high_val], RandomFunction)
# uniform with vector slice
low = dvector()
high = dvector()
post_r, out = uniform(rng_R, low=low, high=high)
low_val = [.1, .2, .3]
high_val = [1.1, 2.2, 3.3]
size_val = (3, )
self._compile_and_check([rng_R, low, high], [out],
[rng_R_val, low_val[:-1],
high_val[:-1]], RandomFunction)
# uniform with explicit size and size implicit in parameters
# NOTE 1: Would it be desirable that size could also be supplied
# as a Theano variable?
post_r, out = uniform(rng_R, size=size_val, low=low, high=high)
self._compile_and_check([rng_R, low, high], [out], [rng_R_val, low_val,
high_val], RandomFunction)
# binomial with vector slice
n = ivector()
prob = dvector()
post_r, out = binomial(rng_R, n=n, p=prob)
n_val = [1, 2, 3]
prob_val = [.1, .2, .3]
size_val = (3, )
self._compile_and_check([rng_R, n, prob], [out],
[rng_R_val, n_val[:-1],
prob_val[:-1]], RandomFunction)
# binomial with explicit size and size implicit in parameters
# cf. NOTE 1
post_r, out = binomial(rng_R, n=n, p=prob, size=size_val)
self._compile_and_check([rng_R, n, prob], [out], [rng_R_val, n_val,
prob_val], RandomFunction)
# normal with vector slice
avg = dvector()
std = dvector()
post_r, out = normal(rng_R, avg=avg, std=std)
avg_val = [1, 2, 3]
std_val = [.1, .2, .3]
size_val = (3, )
self._compile_and_check([rng_R, avg, std], [out],
[rng_R_val, avg_val[:-1],
std_val[:-1]], RandomFunction)
# normal with explicit size and size implicit in parameters
# cf. NOTE 1
post_r, out = normal(rng_R, avg=avg, std=std, size=size_val)
self._compile_and_check([rng_R, avg, std], [out], [rng_R_val, avg_val,
std_val], RandomFunction)
# multinomial with tensor-3 probabilities
"""
#multinomial infer_shape don't work.
pvals = dtensor3()
n = iscalar()
post_r, out = multinomial(rng_R, n=n, pvals=pvals, size=(1, -1))
pvals_val = [[[.1, .9], [.2, .8], [.3, .7]]]
n_val = 9
self._compile_and_check([rng_R, n, pvals], [out],
[rng_R_val, n_val,
pvals_val], RandomFunction)
post_r, out = multinomial(rng_R, n=n, pvals=pvals, size=(10, 1, -1))
self._compile_and_check([rng_R, n, pvals], [out],
[rng_R_val, n_val,
pvals_val], RandomFunction)
"""
if __name__ == '__main__': if __name__ == '__main__':
from theano.tests import main from theano.tests import main
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论