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

ported Subtensor, fixed some tests

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