提交 a9fc8c3e authored 作者: Olivier Breuleux's avatar Olivier Breuleux

ported Subtensor, fixed some tests

上级 eec75e98
...@@ -698,17 +698,18 @@ class T_subtensor(unittest.TestCase): ...@@ -698,17 +698,18 @@ class T_subtensor(unittest.TestCase):
def test0_err_invalid(self): def test0_err_invalid(self):
#it is impossible to retrieve a view of a 0-d tensor #it is impossible to retrieve a view of a 0-d tensor
n = astensor(numpy.ones(())) n = as_tensor(numpy.ones(()))
try: try:
t = n[0] t = n[0]
except ValueError, e: except ValueError, e:
self.failUnless(e[0] is Subtensor.e_invalid) self.failUnless(e[0] is Subtensor.e_invalid)
return return
self.fail() self.fail()
def test1_err_bounds(self): def test1_err_bounds(self):
n = astensor(numpy.ones(3)) n = as_tensor(numpy.ones(3))
t = n[7] t = n[7]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
try: try:
tval = eval_outputs([t]) tval = eval_outputs([t])
except Exception, e: except Exception, e:
...@@ -717,21 +718,21 @@ class T_subtensor(unittest.TestCase): ...@@ -717,21 +718,21 @@ class T_subtensor(unittest.TestCase):
return return
self.fail() self.fail()
def test1_ok_range_finite(self): def test1_ok_range_finite(self):
n = astensor(numpy.ones(3)*5) n = as_tensor(numpy.ones(3)*5)
t = n[0:2] t = n[0:2]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (2,)) self.failUnless(tval.shape == (2,))
self.failUnless(tval[1] == 5.0) self.failUnless(tval[1] == 5.0)
def test2_ok_range_finite(self): def test2_ok_range_finite(self):
n = astensor(numpy.ones((3,4))*5) n = as_tensor(numpy.ones((3,4))*5)
t = n[0:2,3] t = n[0:2,3]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (2,)) self.failUnless(tval.shape == (2,))
self.failUnless(tval[1] == 5.0) self.failUnless(tval[1] == 5.0)
def test1_err_invalid(self): def test1_err_invalid(self):
n = astensor(numpy.ones(1)) n = as_tensor(numpy.ones(1))
try: try:
t = n[0,0] t = n[0,0]
except ValueError, e: except ValueError, e:
...@@ -739,24 +740,24 @@ class T_subtensor(unittest.TestCase): ...@@ -739,24 +740,24 @@ class T_subtensor(unittest.TestCase):
return return
self.fail() self.fail()
def test1_ok_elem(self): def test1_ok_elem(self):
n = astensor(numpy.ones(1)*5) n = as_tensor(numpy.ones(1)*5)
t = n[0] t = n[0]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == ()) self.failUnless(tval.shape == ())
self.failUnless(tval == 5.0) self.failUnless(tval == 5.0)
def test1_ok_range_infinite(self): def test1_ok_range_infinite(self):
#Subtensor.debug = True #Subtensor.debug = True
n = astensor(numpy.ones(3)*5) n = as_tensor(numpy.ones(3)*5)
t = n[1:] t = n[1:]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (2,)) self.failUnless(tval.shape == (2,))
self.failUnless(tval[1] == 5.0) self.failUnless(tval[1] == 5.0)
def test1_ok_strided(self): def test1_ok_strided(self):
n = astensor(numpy.ones(5)*5) n = as_tensor(numpy.ones(5)*5)
t = n[1::2] t = n[1::2]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (2,)) self.failUnless(tval.shape == (2,))
self.failUnless(tval[1] == 5.0) self.failUnless(tval[1] == 5.0)
...@@ -766,83 +767,83 @@ class T_subtensor(unittest.TestCase): ...@@ -766,83 +767,83 @@ class T_subtensor(unittest.TestCase):
self.failUnless(tval[1] == 5.0) self.failUnless(tval[1] == 5.0)
def test2_err_bounds0(self): def test2_err_bounds0(self):
n = astensor(numpy.ones((2,3))*5) n = as_tensor(numpy.ones((2,3))*5)
t = n[0,4] t = n[0,4]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
try: try:
tval = eval_outputs([t]) tval = eval_outputs([t])
except IndexError, e: except IndexError, e:
return return
self.fail() self.fail()
def test2_err_bounds1(self): def test2_err_bounds1(self):
n = astensor(numpy.ones((2,3))*5) n = as_tensor(numpy.ones((2,3))*5)
t = n[4:5,2] t = n[4:5,2]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
try: try:
tval = eval_outputs([t]) tval = eval_outputs([t])
except Exception, e: except Exception, e:
if e[0] != 'index out of bounds': if e[0] != 'index out of bounds':
raise raise
def test2_ok_elem(self): def test2_ok_elem(self):
n = astensor(numpy.asarray(range(6)).reshape((2,3))) n = as_tensor(numpy.asarray(range(6)).reshape((2,3)))
t = n[0,2] t = n[0,2]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == ()) self.failUnless(tval.shape == ())
self.failUnless(numpy.all(tval == 2)) self.failUnless(numpy.all(tval == 2))
def test2_ok_row(self): def test2_ok_row(self):
n = astensor(numpy.asarray(range(6)).reshape((2,3))) n = as_tensor(numpy.asarray(range(6)).reshape((2,3)))
t = n[1] t = n[1]
self.failIf(any(n.broadcastable)) self.failIf(any(n.type.broadcastable))
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (3,)) self.failUnless(tval.shape == (3,))
self.failUnless(numpy.all(tval == [3,4,5])) self.failUnless(numpy.all(tval == [3,4,5]))
def test2_ok_col(self): def test2_ok_col(self):
n = astensor(numpy.ones((2,3))*5) n = as_tensor(numpy.ones((2,3))*5)
t = n[:,0] t = n[:,0]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
self.failIf(any(n.broadcastable)) self.failIf(any(n.type.broadcastable))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (2,)) self.failUnless(tval.shape == (2,))
self.failUnless(numpy.all(tval == 5.0)) self.failUnless(numpy.all(tval == 5.0))
def test2_ok_rows_finite(self): def test2_ok_rows_finite(self):
n = astensor(numpy.ones((4,3))*5) n = as_tensor(numpy.ones((4,3))*5)
t = n[1:3,0] t = n[1:3,0]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (2,)) self.failUnless(tval.shape == (2,))
self.failUnless(numpy.all(tval == 5.0)) self.failUnless(numpy.all(tval == 5.0))
def test2_ok_cols_infinite(self): def test2_ok_cols_infinite(self):
n = astensor(numpy.asarray(range(12)).reshape((4,3))) n = as_tensor(numpy.asarray(range(12)).reshape((4,3)))
t = n[1,2:] t = n[1,2:]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (1,)) self.failUnless(tval.shape == (1,))
self.failUnless(numpy.all(tval == 5)) self.failUnless(numpy.all(tval == 5))
def test2_ok_strided(self): def test2_ok_strided(self):
n = astensor(numpy.asarray(range(20)).reshape((4,5))) n = as_tensor(numpy.asarray(range(20)).reshape((4,5)))
t = n[1:4:2,1:5:2] t = n[1:4:2,1:5:2]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == (2,2)) self.failUnless(tval.shape == (2,2))
self.failUnless(numpy.all(tval == [[6, 8],[16, 18]])) self.failUnless(numpy.all(tval == [[6, 8],[16, 18]]))
def test3_ok_mat(self): def test3_ok_mat(self):
n = astensor(numpy.asarray(range(24)).reshape((2,3,4))) n = as_tensor(numpy.asarray(range(24)).reshape((2,3,4)))
t = n[0,0,0] t = n[0,0,0]
self.failUnless(t.owner.__class__ is Subtensor) self.failUnless(isinstance(t.owner.op, Subtensor))
tval = eval_outputs([t]) tval = eval_outputs([t])
self.failUnless(tval.shape == ()) self.failUnless(tval.shape == ())
self.failUnless(numpy.all(tval == 0)) self.failUnless(numpy.all(tval == 0))
def test_grad_1d(self): def test_grad_1d(self):
n = astensor(numpy.random.rand(2,3)) n = as_tensor(numpy.random.rand(2,3))
z = scal.constant(0) z = scal.constant(0)
t = n[z:,z] t = n[z:,z]
gn = gradient.grad(sum(exp(t)), n) gn = gradient.grad(sum(exp(t)), n)
...@@ -853,7 +854,7 @@ class T_subtensor(unittest.TestCase): ...@@ -853,7 +854,7 @@ class T_subtensor(unittest.TestCase):
self.failUnless(repr(gval[1,:]) == s1) self.failUnless(repr(gval[1,:]) == s1)
def test_grad_0d(self): def test_grad_0d(self):
n = astensor(numpy.random.rand(2,3)) n = as_tensor(numpy.random.rand(2,3))
t = n[1,0] t = n[1,0]
gn = gradient.grad(sum(exp(t)), n) gn = gradient.grad(sum(exp(t)), n)
gval = eval_outputs([gn]) gval = eval_outputs([gn])
...@@ -868,14 +869,14 @@ class T_subtensor(unittest.TestCase): ...@@ -868,14 +869,14 @@ class T_subtensor(unittest.TestCase):
class T_Stack(unittest.TestCase): class T_Stack(unittest.TestCase):
def test_hstack(self): def test_hstack(self):
a = astensor(numpy.array([[1, 2, 3], [4, 5, 6]]), broadcastable=[False,False]) a = as_tensor(numpy.array([[1, 2, 3], [4, 5, 6]]))
b = astensor(numpy.array([[7], [8]]), broadcastable=[False,False]) b = as_tensor(numpy.array([[7], [8]]))
s = horizontal_stack(a, b) s = horizontal_stack(a, b)
c = numpy.array([[1, 2, 3, 7], [4, 5, 6, 8]]) c = numpy.array([[1, 2, 3, 7], [4, 5, 6, 8]])
self.failUnless((eval_outputs([s]) == c).all()) self.failUnless((eval_outputs([s]) == c).all())
def test_vstack(self): def test_vstack(self):
a = astensor(numpy.array([[1, 2, 3], [4, 5, 6]]), broadcastable=[False,False]) a = as_tensor(numpy.array([[1, 2, 3], [4, 5, 6]]))
b = astensor(numpy.array([[7, 8, 9]]), broadcastable=[False,False]) b = as_tensor(numpy.array([[7, 8, 9]]))
s = vertical_stack(a, b) s = vertical_stack(a, b)
c = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) c = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
self.failUnless((eval_outputs([s]) == c).all()) self.failUnless((eval_outputs([s]) == c).all())
...@@ -888,8 +889,8 @@ class T_Stack(unittest.TestCase): ...@@ -888,8 +889,8 @@ class T_Stack(unittest.TestCase):
# def test_complex_all_ops(self): # def test_complex_all_ops(self):
# for nbits in (64, 128): # for nbits in (64, 128):
# a = astensor(numpy.ones(3, dtype='complex%i' % nbits)+0.5j) # a = as_tensor(numpy.ones(3, dtype='complex%i' % nbits)+0.5j)
# b = astensor(numpy.ones(3, dtype='complex%i' % nbits)+1.5j) # b = as_tensor(numpy.ones(3, dtype='complex%i' % nbits)+1.5j)
# tests = (("+", lambda x,y: x+y), # tests = (("+", lambda x,y: x+y),
# ("-", lambda x,y: x-y), # ("-", lambda x,y: x-y),
# ("*", lambda x,y: x*y), # ("*", lambda x,y: x*y),
...@@ -910,12 +911,12 @@ class T_Stack(unittest.TestCase): ...@@ -910,12 +911,12 @@ class T_Stack(unittest.TestCase):
# class T_abs(unittest.TestCase): # class T_abs(unittest.TestCase):
# def test_impl(self): # def test_impl(self):
# t = astensor(1.0) # t = as_tensor(1.0)
# check_eq(self, t, abs(t), 1.0, 1.0) # check_eq(self, t, abs(t), 1.0, 1.0)
# check_eq(self, t, abs(t), -1.0, 1.0) # check_eq(self, t, abs(t), -1.0, 1.0)
# for shape in (2,), (3,4): # for shape in (2,), (3,4):
# t = astensor(numpy.ones(shape)) # t = as_tensor(numpy.ones(shape))
# d = numpy.random.rand(*shape)*2-1.0 # d = numpy.random.rand(*shape)*2-1.0
# check_eq(self, t, abs(t), d, abs(d)) # check_eq(self, t, abs(t), d, abs(d))
# check_eq(self, t, abs(t), -d, abs(-d)) # check_eq(self, t, abs(t), -d, abs(-d))
...@@ -950,7 +951,7 @@ class T_Stack(unittest.TestCase): ...@@ -950,7 +951,7 @@ class T_Stack(unittest.TestCase):
# self.failUnless(numpy.all(eval_outputs([t]) == [9,9,9])) # self.failUnless(numpy.all(eval_outputs([t]) == [9,9,9]))
# def test1(self): # def test1(self):
# x = astensor(numpy.ones((4,5))) # x = as_tensor(numpy.ones((4,5)))
# l = ones_like(x[:,0:1]) # l = ones_like(x[:,0:1])
# r = ones_like(x[0:1,:]) # r = ones_like(x[0:1,:])
# xx = x + dot(l,r) # xx = x + dot(l,r)
...@@ -958,11 +959,11 @@ class T_Stack(unittest.TestCase): ...@@ -958,11 +959,11 @@ class T_Stack(unittest.TestCase):
# class T_sum(unittest.TestCase): # class T_sum(unittest.TestCase):
# def test_impl(self): # def test_impl(self):
# t = astensor(0.0) # t = as_tensor(0.0)
# check_eq(self, t, Sum(t).out, 1.0, 1.0) # check_eq(self, t, Sum(t).out, 1.0, 1.0)
# check_eq(self, t, Sum(t).out, -1.0, -1.0) # check_eq(self, t, Sum(t).out, -1.0, -1.0)
# t = astensor([0.0, 0.0]) # t = as_tensor([0.0, 0.0])
# d = numpy.asarray([-0.4, 1.2]) # d = numpy.asarray([-0.4, 1.2])
# check_eq(self, t, Sum(t).out, d, numpy.sum(d)) # check_eq(self, t, Sum(t).out, d, numpy.sum(d))
# check_eq(self, t, Sum(t).out, -d, -numpy.sum(d)) # check_eq(self, t, Sum(t).out, -d, -numpy.sum(d))
...@@ -972,13 +973,13 @@ class T_Stack(unittest.TestCase): ...@@ -972,13 +973,13 @@ class T_Stack(unittest.TestCase):
# numpy.random.seed([1,2,3,4]) # numpy.random.seed([1,2,3,4])
# def test_elemwise(self): # def test_elemwise(self):
# a = astensor(0.0) # a = as_tensor(0.0)
# b = astensor(0.0) # b = as_tensor(0.0)
# check_eq2_both(self, [a,b], mul(a,b), [3.0, 4.0], 12.0) # check_eq2_both(self, [a,b], mul(a,b), [3.0, 4.0], 12.0)
# check_eq2_both(self, [a,b], mul(b,a), [-1.0,2.0], -2.0) # check_eq2_both(self, [a,b], mul(b,a), [-1.0,2.0], -2.0)
# a = astensor(numpy.ones(2)) # a = as_tensor(numpy.ones(2))
# b = astensor(numpy.ones(2)) # b = as_tensor(numpy.ones(2))
# aa = numpy.asarray([-0.5, 4.0]) # aa = numpy.asarray([-0.5, 4.0])
# bb = numpy.asarray([-0.5, 2.0]) # bb = numpy.asarray([-0.5, 2.0])
# check_eq2_both(self, [a,b], mul(a,b), [aa,bb], numpy.asarray([0.25, 8.0])) # check_eq2_both(self, [a,b], mul(a,b), [aa,bb], numpy.asarray([0.25, 8.0]))
...@@ -986,8 +987,8 @@ class T_Stack(unittest.TestCase): ...@@ -986,8 +987,8 @@ class T_Stack(unittest.TestCase):
# def test_scalar(self): # def test_scalar(self):
# r = numpy.random.rand(2,3) # r = numpy.random.rand(2,3)
# a = astensor(r) # a = as_tensor(r)
# b = astensor(2.0) # b = as_tensor(2.0)
# check_eq2_both(self, [a,b], mul(a,b), [r, 2.0], r*2.0) # check_eq2_both(self, [a,b], mul(a,b), [r, 2.0], r*2.0)
# check_eq2_both(self, [a,b], mul(a,b), [r, 4.0], r*4.0) # check_eq2_both(self, [a,b], mul(a,b), [r, 4.0], r*4.0)
# self.failUnless(b.data == 2.0) # self.failUnless(b.data == 2.0)
...@@ -996,7 +997,7 @@ class T_Stack(unittest.TestCase): ...@@ -996,7 +997,7 @@ class T_Stack(unittest.TestCase):
# r1 = numpy.random.rand(3,5) # r1 = numpy.random.rand(3,5)
# r2 = numpy.random.rand(1,5) # r2 = numpy.random.rand(1,5)
# r3 = numpy.random.rand(3,1) # r3 = numpy.random.rand(3,1)
# a1, a2, a3 = astensor(r1), astensor(r2), astensor(r3) # a1, a2, a3 = as_tensor(r1), as_tensor(r2), as_tensor(r3)
# check_eq2_both(self, [a1,a2], mul(a1,a2), [r1, r2], r1*r2) # check_eq2_both(self, [a1,a2], mul(a1,a2), [r1, r2], r1*r2)
# check_eq2_both(self, [a1,a3], mul(a1,a3), [r1, r3], r1*r3) # check_eq2_both(self, [a1,a3], mul(a1,a3), [r1, r3], r1*r3)
...@@ -1015,8 +1016,8 @@ class T_Stack(unittest.TestCase): ...@@ -1015,8 +1016,8 @@ class T_Stack(unittest.TestCase):
# verify_grad(self, Mul, [numpy.random.rand(3, 5), numpy.random.rand(3, 1)]) # verify_grad(self, Mul, [numpy.random.rand(3, 5), numpy.random.rand(3, 1)])
# def test_wrong_shapes(self): # def test_wrong_shapes(self):
# a = astensor(numpy.ones(3)) # a = as_tensor(numpy.ones(3))
# b = astensor(numpy.ones(4)) # b = as_tensor(numpy.ones(4))
# try: # try:
# check_eq2(self, [a,b], Mul(a,b).out, # check_eq2(self, [a,b], Mul(a,b).out,
# [numpy.ones(3), numpy.ones(4)], 1.0) # [numpy.ones(3), numpy.ones(4)], 1.0)
...@@ -1051,8 +1052,8 @@ class T_Stack(unittest.TestCase): ...@@ -1051,8 +1052,8 @@ class T_Stack(unittest.TestCase):
# def test0(self): # def test0(self):
# verify_grad(self, Log, [numpy.random.rand(3,1)+0.0001]) # verify_grad(self, Log, [numpy.random.rand(3,1)+0.0001])
# def test1(self): # def test1(self):
# a = astensor(numpy.ones(2)) # a = as_tensor(numpy.ones(2))
# b = astensor(numpy.ones(2)) # b = as_tensor(numpy.ones(2))
# aa = numpy.asarray([0.5, 4.0]) # aa = numpy.asarray([0.5, 4.0])
# bb = numpy.asarray([0.5, 2.0]) # bb = numpy.asarray([0.5, 2.0])
# check_eq2(self, [a], log(a), [aa], numpy.log(numpy.asarray(aa))) # check_eq2(self, [a], log(a), [aa], numpy.log(numpy.asarray(aa)))
...@@ -1204,8 +1205,8 @@ class t_gemm(unittest.TestCase): ...@@ -1204,8 +1205,8 @@ class t_gemm(unittest.TestCase):
else: else:
self.failIf(numpy.all(z_orig == z)) self.failIf(numpy.all(z_orig == z))
#cmp_linker(copy(z), a, x, y, b, gof.cc.OpWiseCLinker) cmp_linker(copy(z), a, x, y, b, gof.cc.OpWiseCLinker)
#cmp_linker(copy(z), a, x, y, b, gof.cc.CLinker) cmp_linker(copy(z), a, x, y, b, gof.cc.CLinker)
cmp_linker(copy(z), a, x, y, b, gof.link.PerformLinker) cmp_linker(copy(z), a, x, y, b, gof.link.PerformLinker)
def test0a(self): def test0a(self):
...@@ -1346,10 +1347,10 @@ class T_tensorfromscalar(unittest.TestCase): ...@@ -1346,10 +1347,10 @@ class T_tensorfromscalar(unittest.TestCase):
def test0(self): def test0(self):
s = scal.constant(56) s = scal.constant(56)
t = tensor_from_scalar(s) t = tensor_from_scalar(s)
self.failUnless(t.owner.__class__ is TensorFromScalar) self.failUnless(t.owner.op is tensor_from_scalar)
self.failUnless(t.broadcastable == (), t.broadcastable) self.failUnless(t.type.broadcastable == (), t.type.broadcastable)
self.failUnless(t.ndim == 0, t.ndim) self.failUnless(t.type.ndim == 0, t.type.ndim)
self.failUnless(t.dtype == s.dtype) self.failUnless(t.type.dtype == s.type.dtype)
v = eval_outputs([t]) v = eval_outputs([t])
...@@ -1359,11 +1360,11 @@ class T_tensorfromscalar(unittest.TestCase): ...@@ -1359,11 +1360,11 @@ class T_tensorfromscalar(unittest.TestCase):
def test1(self): def test1(self):
s = scal.constant(56) s = scal.constant(56)
t = astensor(s) t = as_tensor(s)
self.failUnless(t.owner.__class__ is TensorFromScalar) self.failUnless(t.owner.op is tensor_from_scalar)
self.failUnless(t.broadcastable == (), t.broadcastable) self.failUnless(t.type.broadcastable == (), t.type.broadcastable)
self.failUnless(t.ndim == 0, t.ndim) self.failUnless(t.type.ndim == 0, t.type.ndim)
self.failUnless(t.dtype == s.dtype) self.failUnless(t.type.dtype == s.type.dtype)
v = eval_outputs([t]) v = eval_outputs([t])
...@@ -1509,8 +1510,6 @@ class T_tensorfromscalar(unittest.TestCase): ...@@ -1509,8 +1510,6 @@ class T_tensorfromscalar(unittest.TestCase):
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
<<<<<<< /u/breuleuo/hg/theano2/_test_tensor.py # suite = unittest.TestLoader()
#AddTester('test_grad').debug() # suite = suite.loadTestsFromTestCase(T_subtensor)
======= # unittest.TextTestRunner(verbosity=2).run(suite)
>>>>>>> /tmp/_test_tensor.py~other.dM43H3
...@@ -126,14 +126,14 @@ class _test_inputs(testcase): ...@@ -126,14 +126,14 @@ class _test_inputs(testcase):
# self.fail() # self.fail()
class _test_orphans(testcase): # class _test_orphans(testcase):
def test_straightforward(self): # def test_straightforward(self):
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5) # r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
node = MyOp.make_node(r1, r2) # node = MyOp.make_node(r1, r2)
node2 = MyOp.make_node(node.outputs[0], r5) # node2 = MyOp.make_node(node.outputs[0], r5)
orph = orphans([r1, r2], node2.outputs) # orph = orphans([r1, r2], node2.outputs)
self.failUnless(orph == [r5], orph) # self.failUnless(orph == [r5], orph)
class _test_as_string(testcase): class _test_as_string(testcase):
...@@ -215,15 +215,15 @@ def prenode(obj): ...@@ -215,15 +215,15 @@ def prenode(obj):
if isinstance(obj, Result): if isinstance(obj, Result):
if obj.owner: if obj.owner:
return [obj.owner] return [obj.owner]
if isinstance(obj, Op): if isinstance(obj, Apply):
return obj.inputs return obj.inputs
class _test_toposort(testcase): class _test_toposort(testcase):
def test0(self): def test0(self):
"""Test a simple graph""" """Test a simple graph"""
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5) r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
o = MyOp(r1, r2) o = MyOp.make_node(r1, r2)
o2 = MyOp(o.outputs[0], r5) o2 = MyOp.make_node(o.outputs[0], r5)
all = general_toposort(o2.outputs, prenode) all = general_toposort(o2.outputs, prenode)
self.failUnless(all == [r5, r2, r1, o, o.outputs[0], o2, o2.outputs[0]], all) self.failUnless(all == [r5, r2, r1, o, o.outputs[0], o2, o2.outputs[0]], all)
...@@ -234,45 +234,45 @@ class _test_toposort(testcase): ...@@ -234,45 +234,45 @@ class _test_toposort(testcase):
def test1(self): def test1(self):
"""Test a graph with double dependencies""" """Test a graph with double dependencies"""
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5) r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
o = MyOp(r1, r1) o = MyOp.make_node(r1, r1)
o2 = MyOp(o.outputs[0], r5) o2 = MyOp.make_node(o.outputs[0], r5)
all = general_toposort(o2.outputs, prenode) all = general_toposort(o2.outputs, prenode)
self.failUnless(all == [r5, r1, o, o.outputs[0], o2, o2.outputs[0]], all) self.failUnless(all == [r5, r1, o, o.outputs[0], o2, o2.outputs[0]], all)
def test2(self): def test2(self):
"""Test a graph where the inputs have owners""" """Test a graph where the inputs have owners"""
r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5) r1, r2, r5 = MyResult(1), MyResult(2), MyResult(5)
o = MyOp(r1, r1) o = MyOp.make_node(r1, r1)
r2b = o.outputs[0] r2b = o.outputs[0]
o2 = MyOp(r2b, r2b) o2 = MyOp.make_node(r2b, r2b)
all = io_toposort([r2b], o2.outputs) all = io_toposort([r2b], o2.outputs)
self.failUnless(all == [o2], all) self.failUnless(all == [o2], all)
o2 = MyOp(r2b, r5) o2 = MyOp.make_node(r2b, r5)
all = io_toposort([r2b], o2.outputs) all = io_toposort([r2b], o2.outputs)
self.failUnless(all == [o2], all) self.failUnless(all == [o2], all)
def test3(self): def test3(self):
"""Test a graph which is not connected""" """Test a graph which is not connected"""
r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4) r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4)
o0 = MyOp(r1, r2) o0 = MyOp.make_node(r1, r2)
o1 = MyOp(r3, r4) o1 = MyOp.make_node(r3, r4)
all = io_toposort([r1, r2, r3, r4], o0.outputs + o1.outputs) all = io_toposort([r1, r2, r3, r4], o0.outputs + o1.outputs)
self.failUnless(all == [o1,o0], all) self.failUnless(all == [o1,o0], all)
def test4(self): def test4(self):
"""Test inputs and outputs mixed together in a chain graph""" """Test inputs and outputs mixed together in a chain graph"""
r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4) r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4)
o0 = MyOp(r1, r2) o0 = MyOp.make_node(r1, r2)
o1 = MyOp(o0.outputs[0], r1) o1 = MyOp.make_node(o0.outputs[0], r1)
all = io_toposort([r1, o0.outputs[0]], [o0.outputs[0], o1.outputs[0]]) all = io_toposort([r1, o0.outputs[0]], [o0.outputs[0], o1.outputs[0]])
self.failUnless(all == [o1], all) self.failUnless(all == [o1], all)
def test5(self): def test5(self):
"""Test when outputs have clients""" """Test when outputs have clients"""
r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4) r1, r2, r3, r4 = MyResult(1), MyResult(2), MyResult(3), MyResult(4)
o0 = MyOp(r1, r2) o0 = MyOp.make_node(r1, r2)
o1 = MyOp(o0.outputs[0], r4) o1 = MyOp.make_node(o0.outputs[0], r4)
all = io_toposort([], o0.outputs) all = io_toposort([], o0.outputs)
self.failUnless(all == [o0], all) self.failUnless(all == [o0], all)
......
...@@ -18,26 +18,26 @@ import traceback ...@@ -18,26 +18,26 @@ import traceback
def compile_dir(): def compile_dir():
"""Return the directory in which scipy.weave should store code objects. """Return the directory in which scipy.weave should store code objects.
If the environment variable OMEGA_COMPILEDIR is set, its value is returned. If the environment variable THEANO_COMPILEDIR is set, its value is returned.
If not, a directory of the form $HOME/.omega/compiledir_<platform Id>. If not, a directory of the form $HOME/.theano/compiledir_<platform Id>.
As a test, this function touches the file __init__.py in the returned As a test, this function touches the file __init__.py in the returned
directory, and raises OSError if there's a problem. directory, and raises OSError if there's a problem.
A directory coming from OMEGA_COMPILEDIR is not created automatically, but A directory coming from THEANO_COMPILEDIR is not created automatically, but
a directory in $HOME/.omega is created automatically. a directory in $HOME/.theano is created automatically.
This directory is appended to the sys.path search path before being This directory is appended to the sys.path search path before being
returned, if the touch was successful. returned, if the touch was successful.
""" """
if os.getenv('OMEGA_COMPILEDIR'): if os.getenv('THEANO_COMPILEDIR'):
cachedir = os.getenv('OMEGA_COMPILEDIR') cachedir = os.getenv('THEANO_COMPILEDIR')
else: else:
# use (and possibly create) a default code cache location # use (and possibly create) a default code cache location
platform_id = platform.platform() + '-' + platform.processor() platform_id = platform.platform() + '-' + platform.processor()
import re import re
platform_id = re.sub("[\(\)\s]+", "_", platform_id) platform_id = re.sub("[\(\)\s]+", "_", platform_id)
cachedir = os.path.join(os.getenv('HOME'), '.omega', 'compiledir_'+platform_id) cachedir = os.path.join(os.getenv('HOME'), '.theano', 'compiledir_'+platform_id)
if not os.access(cachedir, os.R_OK | os.W_OK): if not os.access(cachedir, os.R_OK | os.W_OK):
#this may raise a number of problems, I think all of which are serious. #this may raise a number of problems, I think all of which are serious.
os.makedirs(cachedir, 7<<6) os.makedirs(cachedir, 7<<6)
...@@ -345,7 +345,7 @@ class CLinker(Linker): ...@@ -345,7 +345,7 @@ class CLinker(Linker):
env = self.env env = self.env
self.inputs = env.inputs self.inputs = env.inputs
self.outputs = env.outputs self.outputs = env.outputs
self.results = list(env.results) self.results = graph.results(self.inputs, self.outputs) # list(env.results)
# The orphans field is listified to ensure a consistent order. # The orphans field is listified to ensure a consistent order.
self.orphans = list(r for r in self.results if isinstance(r, Value) and r not in self.inputs) #list(env.orphans.difference(self.outputs)) self.orphans = list(r for r in self.results if isinstance(r, Value) and r not in self.inputs) #list(env.orphans.difference(self.outputs))
self.temps = list(set(self.results).difference(self.inputs).difference(self.outputs).difference(self.orphans)) self.temps = list(set(self.results).difference(self.inputs).difference(self.outputs).difference(self.orphans))
...@@ -391,7 +391,7 @@ class CLinker(Linker): ...@@ -391,7 +391,7 @@ class CLinker(Linker):
sub = dict(failure_var = failure_var) sub = dict(failure_var = failure_var)
for result in set(self.results): for result in self.results:
# it might be possible to inline constant results as C literals # it might be possible to inline constant results as C literals
## if getattr(result, 'constant', False): ## if getattr(result, 'constant', False):
......
...@@ -294,7 +294,7 @@ class Env(object): #(graph.Graph): ...@@ -294,7 +294,7 @@ class Env(object): #(graph.Graph):
for feature in env._features: for feature in env._features:
if hasattr(feature, 'orderings'): if hasattr(feature, 'orderings'):
for op, prereqs in feature.orderings(env).items(): for op, prereqs in feature.orderings(env).items():
ords.setdefault(op, set()).update(prereqs) ords.setdefault(op, []).extend(prereqs)
order = graph.io_toposort(env.inputs, env.outputs, ords) order = graph.io_toposort(env.inputs, env.outputs, ords)
return order return order
......
...@@ -283,23 +283,36 @@ def inputs(result_list): ...@@ -283,23 +283,36 @@ def inputs(result_list):
def results_and_orphans(i, o): def results_and_orphans(i, o):
results = set() """
orphans = set() """
def helper(r): def expand(r):
if r in results: if r.owner and r not in i:
return l = list(r.owner.inputs)
results.add(r) l.reverse()
if r.owner is None: return l
if r not in i: results = stack_search(deque(o), expand, 'dfs')
orphans.add(r) orphans = [r for r in results if r.owner is None and r not in i]
else:
for r2 in r.owner.inputs:
helper(r2)
for output in o:
helper(output)
return results, orphans return results, orphans
#def results_and_orphans(i, o):
# results = set()
# orphans = set()
# def helper(r):
# if r in results:
# return
# results.add(r)
# if r.owner is None:
# if r not in i:
# orphans.add(r)
# else:
# for r2 in r.owner.inputs:
# helper(r2)
# for output in o:
# helper(output)
# return results, orphans
def ops(i, o): def ops(i, o):
""" """
@type i: list @type i: list
...@@ -469,17 +482,17 @@ def io_toposort(i, o, orderings = {}): ...@@ -469,17 +482,17 @@ def io_toposort(i, o, orderings = {}):
def deps(obj): def deps(obj):
rval = [] rval = []
if obj not in iset: if obj not in iset:
if isinstance(obj, result.Result): if isinstance(obj, Result):
if obj.owner: if obj.owner:
rval = [obj.owner] rval = [obj.owner]
if isinstance(obj, op.Op): if isinstance(obj, Apply):
rval = list(obj.inputs) rval = list(obj.inputs)
rval.extend(orderings.get(obj, [])) rval.extend(orderings.get(obj, []))
else: else:
assert not orderings.get(obj, []) assert not orderings.get(obj, [])
return rval return rval
topo = general_toposort(o, deps) topo = general_toposort(o, deps)
return [o for o in topo if isinstance(o, op.Op)] return [o for o in topo if isinstance(o, Apply)]
......
...@@ -24,6 +24,8 @@ def as_tensor(x, name = None): ...@@ -24,6 +24,8 @@ def as_tensor(x, name = None):
else: else:
x = x.outputs[0] x = x.outputs[0]
if isinstance(x, Result): if isinstance(x, Result):
if isinstance(x.type, scal.Scalar):
return tensor_from_scalar(x)
if not isinstance(x.type, Tensor): if not isinstance(x.type, Tensor):
raise TypeError("Result type field must be a Tensor.", x, x.type) raise TypeError("Result type field must be a Tensor.", x, x.type)
return x return x
...@@ -233,8 +235,8 @@ class Tensor(Type): ...@@ -233,8 +235,8 @@ class Tensor(Type):
# Easy constructors # Easy constructors
def tensor(*args): def tensor(*args, **kwargs):
return Tensor(*args).make_result() return Tensor(*args, **kwargs).make_result()
def _multi(*fns): def _multi(*fns):
def f2(f, names): def f2(f, names):
...@@ -334,10 +336,17 @@ class _tensor_py_operators: ...@@ -334,10 +336,17 @@ class _tensor_py_operators:
T = property(lambda self: transpose(self)) T = property(lambda self: transpose(self))
#SLICING #SLICING
def __getitem__(self, args): return Subtensor.from_idxs(self, # def __getitem__(self, args): return Subtensor.from_idxs(self,
args).outputs[0] # args).outputs[0]
def __getslice__(self, *args): return Subtensor.from_idxs(self, # def __getslice__(self, *args): return Subtensor.from_idxs(self,
(slice(*args),)).outputs[0] # (slice(*args),)).outputs[0]
def __getitem__(self, args):
if not isinstance(args, tuple):
args = args,
return Subtensor(args)(self, *Subtensor.collapse(args, lambda entry: isinstance(entry, Result)))
def __getslice__(self, *args):
args = slice(*args),
return Subtensor(args)(self, *Subtensor.collapse(args, lambda entry: isinstance(entry, Result)))
#COPYING #COPYING
def copy(self): return tensor_copy(self) def copy(self): return tensor_copy(self)
...@@ -479,7 +488,8 @@ class TransposeInplace(Op): ...@@ -479,7 +488,8 @@ class TransposeInplace(Op):
view_map = {0: [0]} view_map = {0: [0]}
def make_node(self, input): def make_node(self, input):
return Apply(self, [input], [input.type()]) return Apply(self, [input], [tensor(dtype = input.type.dtype,
broadcastable = reversed(input.type.broadcastable))])
def perform(self, node, (x, ), (z, )): def perform(self, node, (x, ), (z, )):
z[0] = x.T z[0] = x.T
...@@ -546,7 +556,9 @@ class Subtensor_dx(Op, Viewer): ...@@ -546,7 +556,9 @@ class Subtensor_dx(Op, Viewer):
assert len(self.inputs) == len(new_inputs) assert len(self.inputs) == len(new_inputs)
return Subtensor_dx(new_inputs, self.idx_list) return Subtensor_dx(new_inputs, self.idx_list)
class Subtensor(Op, Viewer):
class Subtensor(Op):
"""Return a subtensor view """Return a subtensor view
This class uses a relatively complex internal representation of the inputs This class uses a relatively complex internal representation of the inputs
...@@ -558,110 +570,151 @@ class Subtensor(Op, Viewer): ...@@ -558,110 +570,151 @@ class Subtensor(Op, Viewer):
@todo: add support for advanced tensor indexing (in Subtensor_dx too). @todo: add support for advanced tensor indexing (in Subtensor_dx too).
""" """
e_invalid = 'invalid index' e_invalid = 'The index list is longer than the number of dimensions of the tensor.'
debug = 0 debug = 0
@staticmethod view_map = {0: [0]}
def from_idxs(x, idxs, **kwargs):
if Subtensor.debug:
print idxs, sys.maxint
def asidx(i):
if isinstance(i, int): return scal.constant(i)
if isinstance(i, scal.Scalar) and ('int' in i.dtype): return i
raise TypeError(Subtensor.e_invalid, i)
x = _as_tensor(x)
idx_list = [] # like args, but with int -> scalar.constant
inputs = [x] # like args, but with slices flattened
if not isinstance(idxs, (list, tuple)):
idxs = (idxs,)
@staticmethod
def collapse(idxs, cond):
ret = []
def helper(entry):
if cond(entry):
ret.append(entry)
elif isinstance(entry, slice):
helper(entry.start)
helper(entry.stop)
helper(entry.step)
for idx in idxs: for idx in idxs:
try: helper(idx)
ai = asidx(idx) return ret
idx_list.append(len(inputs))
inputs.append(ai) def __init__(self, idx_list):
except TypeError: def convert(entry):
if isinstance(idx, slice): if isinstance(entry, gof.Result) and entry.type == scal.int64:
start = None if idx.start is None else asidx(idx.start) return entry.type
stop = None if idx.stop is None else asidx(idx.stop) elif isinstance(entry, gof.Type) and entry == scal.int64:
step = None if idx.step is None else asidx(idx.step) return entry
elif isinstance(entry, slice):
# If we get here, then everything got turned (successfully) a = entry.start
# into a scal.Scalar (with integer dtype) or None b = entry.stop
if start: c = entry.step
startpos = len(inputs) return slice(convert(a) if a is not None else None,
inputs.append(start) convert(b) if b is not None else None,
convert(c) if c is not None else None)
elif isinstance(entry, int):
return entry
else: else:
startpos = None raise TypeError("Invalid index type or slice for Subtensor", entry)
self.idx_list = map(convert, idx_list)
if stop: def make_node(self, x, *inputs):
stoppos = len(inputs) x = as_tensor(x)
inputs.append(stop) inputs = tuple(map(scal.as_scalar, inputs))
else:
stoppos = None
if step: idx_list = list(self.idx_list)
steppos = len(inputs) if len(idx_list) > x.type.ndim:
inputs.append(step) raise ValueError(Subtensor.e_invalid,
else: (len(idx_list), x.type.ndim))
steppos = None
idx_list.append(slice(startpos, stoppos, steppos)) #infer the broadcasting pattern
padded = idx_list + [slice(0,sys.maxint,1)] * (x.type.ndim - len(idx_list))
broadcastable = [bc for p, bc in zip(padded, x.type.broadcastable) if isinstance(p, slice)]
input_types = Subtensor.collapse(idx_list, lambda entry: isinstance(entry, gof.Type))
if len(inputs) != len(input_types):
raise IndexError("Not enough inputs to fill in the Subtensor template.", inputs, idx_list)
for input, expected_type in zip(inputs, input_types):
if input.type != expected_type:
raise TypeError("Wrong type for the Subtensor template. Expected %s, got %s." % (input.type, expected_type))
return gof.Apply(self,
(x, ) + inputs,
[tensor(dtype = x.type.dtype,
broadcastable = broadcastable)])
def perform(self, node, inputs, (out, )):
x = inputs[0]
indices = list(reversed(inputs[1:]))
def convert(entry):
if isinstance(entry, gof.Type):
return indices.pop()
elif isinstance(entry, slice):
return slice(convert(entry.start),
convert(entry.stop),
convert(entry.step))
else: else:
raise return entry
assert len(idxs) == len(idx_list) cdata = tuple(map(convert, self.idx_list))
return Subtensor( inputs, idx_list, **kwargs) if len(cdata) == 1:
cdata = cdata[0]
out[0] = x.__getitem__(cdata)
def __init__(self, inputs, idx_list, **kwargs): def grad(self, inputs, (gz,)):
x = inputs[0]
rest = inputs[1:]
return [SetSubtensor(self.idx_list)(zeros_like(x), gz, *rest)] + [None] * len(rest)
if len(idx_list) > len(inputs[0].broadcastable): def __eq__(self, others):
raise ValueError(Subtensor.e_invalid, return type(self) == type(other) and self.idx_list == other.idx_list
(len(idx_list), len(inputs[0].broadcastable)))
#infer the broadcasting pattern def __hash__(self):
padded = list(idx_list) \ # FIXME: this doesn't work if there are slices in the list because for some mysterious reason slice is unhashable
+ [slice(0,sys.maxint,1)] * (len(inputs[0].broadcastable) - len(idx_list)) return hash(tuple(self.idx_list))
broadcastable = [False for p in padded if isinstance(p, slice)]
Op.__init__(self, **kwargs)
self.inputs = inputs
self.outputs = [Tensor(self.inputs[0].dtype, broadcastable)]
self.idx_list = idx_list
def view_map(self): class SetSubtensor(Subtensor):
return {self.out: [self.inputs[0]]} view_map = {}
destroy_map = {0: [0]}
def perform(self): def make_node(self, x, y, *inputs):
x = self.inputs[0].data x, y = map(as_tensor, [x, y])
cdata = [] inputs = tuple(map(scal.as_scalar, inputs))
for c in self.idx_list:
if isinstance(c, slice):
cdata.append(slice(
None if c.start is None else self.inputs[c.start].data,
None if c.stop is None else self.inputs[c.stop].data,
None if c.step is None else self.inputs[c.step].data))
else:
d = self.inputs[c].data
assert 'int' in str(d.dtype)
cdata.append(d)
if len(cdata) > 1:
cdata = tuple(cdata) #there's a diff between tuple and list here...
else:
cdata = cdata[0]
self.outputs[0].data = x.__getitem__(cdata) idx_list = list(self.idx_list)
if Subtensor.debug: if len(idx_list) > x.type.ndim:
print self.inputs[0].data, cdata, self.outputs[0].data raise ValueError(Subtensor.e_invalid,
(len(idx_list), x.type.ndim))
def grad(self, inputs, (gz,)): #infer the broadcasting pattern
return [Subtensor_dx(self.inputs + [gz], self.idx_list).outputs[0]]\ padded = idx_list + [slice(0,sys.maxint,1)] * (x.type.ndim - len(idx_list))
+ [None] * (len(inputs)-1) broadcastable = [bc for p, bc in zip(padded, x.type.broadcastable) if isinstance(p, slice)]
if y.type.broadcastable != tuple(broadcastable):
raise TypeError("Invalid broadcastable pattern for y in SetSubtensor.make_node")
input_types = Subtensor.collapse(idx_list, lambda entry: isinstance(entry, gof.Type))
if len(inputs) != len(input_types):
raise IndexError("Not enough inputs to fill in the Subtensor template.", inputs, idx_list)
for input, expected_type in zip(inputs, input_types):
if input.type != expected_type:
raise TypeError("Wrong type for the Subtensor template. Expected %s, got %s." % (input.type, expected_type))
return gof.Apply(self,
(x, y) + inputs,
[x.type()])
def perform(self, node, inputs, (out, )):
x, y = inputs[:2]
indices = list(reversed(inputs[2:]))
def convert(entry):
if isinstance(entry, gof.Type):
return indices.pop()
elif isinstance(entry, slice):
return slice(convert(entry.start),
convert(entry.stop),
convert(entry.step))
else:
return entry
def clone_with_new_inputs(self, *new_inputs): cdata = tuple(map(convert, self.idx_list))
assert len(self.inputs) == len(new_inputs) if len(cdata) == 1:
return Subtensor(new_inputs, self.idx_list) cdata = cdata[0]
x.__setitem__(cdata, y)
out[0] = x
class VerticalStack(Op): class VerticalStack(Op):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论