提交 7982862b authored 作者: James Bergstra's avatar James Bergstra

merge

THEANO THEANO
Documentation et al is in Trac: Documentation et al is in Trac:
http://lgcm:8000/testenv/wiki/WikiStart http://lgcm.iro.umontreal.ca:8000/theano/wiki/WikiStart
The lisa twiki is deprecated for documenting Theano. The lisa twiki is deprecated for documenting Theano.
......
import gof import gof
import base_tensor
import tensor import tensor
import sparse import sparse
import compile import compile
import gradient import gradient
import opt import opt
from base_tensor import *
from tensor import * from tensor import *
from compile import * from compile import *
from opt import * from opt import *
......
from base_tensor import *
import unittest
from copy import copy
from compile import Function
import gof
def _tensor(data, broadcastable=None, name=None):
"""Return a BaseTensor containing given data"""
data = numpy.asarray(data)
if broadcastable is None:
broadcastable = [s==1 for s in data.shape]
elif broadcastable in [0, 1]:
broadcastable = [broadcastable] * len(data.shape)
rval = BaseTensor(data.dtype, broadcastable, name)
rval.data = data # will raise if broadcastable was mis-specified
return rval
class T_tensor(unittest.TestCase):
def test0(self): # allocate from a scalar float
t = _tensor(1.0)
self.failUnless(isinstance(t, BaseTensor))
self.failUnless(t.dtype == 'float64')
self.failUnless(t.broadcastable == ())
self.failUnless(t.role == None)
self.failUnless(isinstance(t.data, numpy.ndarray))
self.failUnless(str(t.data.dtype) == 'float64')
self.failUnless(t.data == 1.0)
def test0_int(self): # allocate from a scalar float
t = _tensor(1)
self.failUnless(isinstance(t, BaseTensor))
self.failUnless(t.dtype == 'int64' or t.dtype == 'int32')
def test1(self): # allocate from a vector of ints, not broadcastable
t = _tensor(numpy.ones(5,dtype='int32'))
self.failUnless(isinstance(t, BaseTensor))
self.failUnless(t.dtype == 'int32')
self.failUnless(t.broadcastable == (0,))
self.failUnless(isinstance(t.data, numpy.ndarray))
self.failUnless(str(t.data.dtype) == 'int32')
def test2(self): # allocate from a column matrix of complex with name
t = _tensor(numpy.ones((5,1),dtype='complex64'),name='bart')
self.failUnless(isinstance(t, BaseTensor))
self.failUnless(t.dtype == 'complex64')
self.failUnless(t.broadcastable == (0,1))
self.failUnless(isinstance(t.data, numpy.ndarray))
self.failUnless(t.name == 'bart')
def test2b(self): # allocate from a column matrix, not broadcastable
t = _tensor(numpy.ones((5,1),dtype='complex64'),broadcastable=0)
self.failUnless(isinstance(t, BaseTensor))
self.failUnless(t.dtype == 'complex64')
self.failUnless(t.broadcastable == (0,0))
self.failUnless(isinstance(t.data, numpy.ndarray))
f = Function([t], [t], linker_cls=gof.CLinker)
self.failUnless(numpy.all(t.data == f(t.data)))
def test_data_normal(self): #test that assigning to .data works when it should
t = _tensor(numpy.ones((5,1),dtype='complex64'), broadcastable=0)
o27 = numpy.ones((2,7), dtype='complex64')
t.data = o27
lst = t._data
self.failUnless(t.data.shape == (2,7))
self.failUnless(t.data is o27)
self.failUnless(t._data is lst)
def test_data_badrank0(self):
t = _tensor(numpy.ones((5,1),dtype='complex64'), broadcastable=0)
try:
t.data = numpy.ones((2,7,1))
self.fail()
except ValueError, e:
self.failUnless(e[0] is BaseTensor.filter.E_rank)
try:
t.data = numpy.ones(1)
self.fail()
except ValueError, e:
self.failUnless(e[0] is BaseTensor.filter.E_rank)
def test_data_badrank1(self):
t = _tensor(numpy.ones((1,1),dtype='complex64'), broadcastable=1)
try:
t.data = numpy.ones((1,1,1))
self.fail()
except ValueError, e:
self.failUnless(e[0] is BaseTensor.filter.E_rank)
try:
t.data = numpy.ones(1)
self.fail()
except ValueError, e:
self.failUnless(e[0] is BaseTensor.filter.E_rank)
def test_data_badshape0(self):
t = _tensor(numpy.ones((1,1),dtype='complex64'), broadcastable=1)
try:
t.data = numpy.ones((1,2))
self.fail()
except ValueError, e:
self.failUnless(e[0] is BaseTensor.filter.E_shape)
try:
t.data = numpy.ones((0,1))
self.fail()
except ValueError, e:
self.failUnless(e[0] is BaseTensor.filter.E_shape)
def test_cast0(self):
t = BaseTensor('float32', [0])
t.data = numpy.random.rand(4) > 0.5
self.failUnless(str(t.data.dtype) == t.dtype)
class T_stdlib(unittest.TestCase):
def test0(self):
t = _tensor(1.0)
tt = t.clone(False)
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data is None)
self.failUnless(t.data == 1.0)
def test0b(self):
t = _tensor(1.0)
tt = t.clone()
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data is None)
self.failUnless(t.data == 1.0)
def test1(self):
t = _tensor(1.0)
tt = t.clone(True)
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data == 1.0)
self.failUnless(t.data == 1.0)
self.failUnless(t.data is not tt.data)
def test1b(self):
t = _tensor(1.0)
tt = copy(t)
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data == 1.0)
self.failUnless(t.data == 1.0)
self.failUnless(t.data is not tt.data)
if __name__ == '__main__':
unittest.main()
...@@ -1280,5 +1280,142 @@ class t_gemm(unittest.TestCase): ...@@ -1280,5 +1280,142 @@ class t_gemm(unittest.TestCase):
self.fail() self.fail()
def _tensor(data, broadcastable=None, name=None):
"""Return a Tensor containing given data"""
data = numpy.asarray(data)
if broadcastable is None:
broadcastable = [s==1 for s in data.shape]
elif broadcastable in [0, 1]:
broadcastable = [broadcastable] * len(data.shape)
rval = Tensor(data.dtype, broadcastable, name)
rval.data = data # will raise if broadcastable was mis-specified
return rval
class T_tensor(unittest.TestCase):
def test0(self): # allocate from a scalar float
t = _tensor(1.0)
self.failUnless(isinstance(t, Tensor))
self.failUnless(t.dtype == 'float64')
self.failUnless(t.broadcastable == ())
self.failUnless(t.role == None)
self.failUnless(isinstance(t.data, numpy.ndarray))
self.failUnless(str(t.data.dtype) == 'float64')
self.failUnless(t.data == 1.0)
def test0_int(self): # allocate from a scalar float
t = _tensor(1)
self.failUnless(isinstance(t, Tensor))
self.failUnless(t.dtype == 'int64' or t.dtype == 'int32')
def test1(self): # allocate from a vector of ints, not broadcastable
t = _tensor(numpy.ones(5,dtype='int32'))
self.failUnless(isinstance(t, Tensor))
self.failUnless(t.dtype == 'int32')
self.failUnless(t.broadcastable == (0,))
self.failUnless(isinstance(t.data, numpy.ndarray))
self.failUnless(str(t.data.dtype) == 'int32')
def test2(self): # allocate from a column matrix of complex with name
t = _tensor(numpy.ones((5,1),dtype='complex64'),name='bart')
self.failUnless(isinstance(t, Tensor))
self.failUnless(t.dtype == 'complex64')
self.failUnless(t.broadcastable == (0,1))
self.failUnless(isinstance(t.data, numpy.ndarray))
self.failUnless(t.name == 'bart')
def test2b(self): # allocate from a column matrix, not broadcastable
t = _tensor(numpy.ones((5,1),dtype='complex64'),broadcastable=0)
self.failUnless(isinstance(t, Tensor))
self.failUnless(t.dtype == 'complex64')
self.failUnless(t.broadcastable == (0,0))
self.failUnless(isinstance(t.data, numpy.ndarray))
f = Function([t], [t], linker_cls=gof.CLinker)
self.failUnless(numpy.all(t.data == f(t.data)))
def test_data_normal(self): #test that assigning to .data works when it should
t = _tensor(numpy.ones((5,1),dtype='complex64'), broadcastable=0)
o27 = numpy.ones((2,7), dtype='complex64')
t.data = o27
lst = t._data
self.failUnless(t.data.shape == (2,7))
self.failUnless(t.data is o27)
self.failUnless(t._data is lst)
def test_data_badrank0(self):
t = _tensor(numpy.ones((5,1),dtype='complex64'), broadcastable=0)
try:
t.data = numpy.ones((2,7,1))
self.fail()
except ValueError, e:
self.failUnless(e[0] is Tensor.filter.E_rank)
try:
t.data = numpy.ones(1)
self.fail()
except ValueError, e:
self.failUnless(e[0] is Tensor.filter.E_rank)
def test_data_badrank1(self):
t = _tensor(numpy.ones((1,1),dtype='complex64'), broadcastable=1)
try:
t.data = numpy.ones((1,1,1))
self.fail()
except ValueError, e:
self.failUnless(e[0] is Tensor.filter.E_rank)
try:
t.data = numpy.ones(1)
self.fail()
except ValueError, e:
self.failUnless(e[0] is Tensor.filter.E_rank)
def test_data_badshape0(self):
t = _tensor(numpy.ones((1,1),dtype='complex64'), broadcastable=1)
try:
t.data = numpy.ones((1,2))
self.fail()
except ValueError, e:
self.failUnless(e[0] is Tensor.filter.E_shape)
try:
t.data = numpy.ones((0,1))
self.fail()
except ValueError, e:
self.failUnless(e[0] is Tensor.filter.E_shape)
def test_cast0(self):
t = Tensor('float32', [0])
t.data = numpy.random.rand(4) > 0.5
self.failUnless(str(t.data.dtype) == t.dtype)
class T_stdlib(unittest.TestCase):
def test0(self):
t = _tensor(1.0)
tt = t.clone(False)
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data is None)
self.failUnless(t.data == 1.0)
def test0b(self):
t = _tensor(1.0)
tt = t.clone()
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data is None)
self.failUnless(t.data == 1.0)
def test1(self):
t = _tensor(1.0)
tt = t.clone(True)
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data == 1.0)
self.failUnless(t.data == 1.0)
self.failUnless(t.data is not tt.data)
def test1b(self):
t = _tensor(1.0)
tt = copy(t)
self.failUnless(t.dtype == tt.dtype)
self.failUnless(t.broadcastable is tt.broadcastable)
self.failUnless(tt.data == 1.0)
self.failUnless(t.data == 1.0)
self.failUnless(t.data is not tt.data)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import unittest import unittest
import gof import gof
from opt import * from tensor_opt import *
import tensor import tensor
from tensor import Tensor from tensor import Tensor
from gof import Env from gof import Env
......
差异被折叠。
try:
from cutils_ext import *
except ImportError:
from scipy import weave
single_runner = """
if (!PyCObject_Check(py_cthunk)) {
PyErr_SetString(PyExc_ValueError,
"Argument to run_cthunk must be a PyCObject returned by the c_thunk method of an omega_op.");
return NULL;
}
void * ptr_addr = PyCObject_AsVoidPtr(py_cthunk);
int (*fn)(void*) = reinterpret_cast<int (*)(void*)>(ptr_addr);
//int (*fn)(void*) = static_cast<int (*)(void*)>(PyCObject_AsVoidPtr(py_cthunk));
//int (*fn)(void*) = NULL;
//fn += PyCObject_AsVoidPtr(py_cthunk);
//int (*fn)(void*) =
void* it = PyCObject_GetDesc(py_cthunk);
int failure = fn(it);
if (failure) {
return NULL;
}
"""
cthunk = object()
mod = weave.ext_tools.ext_module('cutils_ext')
fun =weave.ext_tools.ext_function('run_cthunk', single_runner, ['cthunk'])
fun.customize.add_extra_compile_arg('--permissive')
mod.add_function(fun)
mod.compile()
from cutils_ext import *
...@@ -3,7 +3,6 @@ import elemwise_cgen as cgen ...@@ -3,7 +3,6 @@ import elemwise_cgen as cgen
import numpy import numpy
from gof import Op, Viewer, Destroyer from gof import Op, Viewer, Destroyer
#from base_tensor import BaseTensor as Tensor
import scalar import scalar
from scalar import upcast, Scalar from scalar import upcast, Scalar
import gof import gof
......
...@@ -17,7 +17,9 @@ __all__ = ['Op', ...@@ -17,7 +17,9 @@ __all__ = ['Op',
def constructor(op_cls, name = None): def constructor(op_cls, name = None):
"""Make an Op look like a L{Result}-valued function.""" """
Make an L{Op} look like a L{Result}-valued function.
"""
def f(*args, **kwargs): def f(*args, **kwargs):
op = op_cls(*args, **kwargs) op = op_cls(*args, **kwargs)
if len(op.outputs) > 1: if len(op.outputs) > 1:
......
...@@ -27,27 +27,14 @@ def grad_sources_inputs(sources, graph_inputs): ...@@ -27,27 +27,14 @@ def grad_sources_inputs(sources, graph_inputs):
calling L{Op.grad}(...) when it is provided by an L{Op}, and at least one of the calling L{Op.grad}(...) when it is provided by an L{Op}, and at least one of the
outputs of the L{Op} has an associated gradient. outputs of the L{Op} has an associated gradient.
The L{Op.grad}(...) functions may be called in several ways (for the The L{Op.grad}(...) functions are called as such:
convenience of the L{Op} implementer) depending on the number of inputs and
outputs.
If there is one input and one output::
op.grad( op.inputs[0], grad(op.outputs[0])) op.grad( op.inputs[0], grad(op.outputs[0]))
If there are several inputs and one output::
op.grad( op.inputs, grad(op.outputs[0]))
If there is one input and several outputs::
op.grad( op.inputs[0], [grad(o) for o in op.outputs[0]])
If there are multiple inputs and outputs::
op.grad( op.inputs, [grad(o) for o in op.outputs[0]])
This function expects the L{Op.grad}(...) function to return the gradient This function expects the L{Op.grad}(...) function to return the gradient
expression [results] associated with the inputs of the L{Op}. If the L{Op} has a expression [results] associated with the inputs of the L{Op}. The L{Op} should
single input, it should return a single result; if the L{Op} has multiple return a list of results corresponding to the gradients in the same order
inputs, it should return a list of results corresponding to the gradients in as the inputs. If it has a single output it should return a list or tuple
the same order as the inputs. of length 1.
For each input wrt to which an L{Op} is not differentiable, it should return For each input wrt to which an L{Op} is not differentiable, it should return
None instead of a result instance. None instead of a result instance.
...@@ -79,9 +66,6 @@ def grad_sources_inputs(sources, graph_inputs): ...@@ -79,9 +66,6 @@ def grad_sources_inputs(sources, graph_inputs):
#if all output gradients are None, continue #if all output gradients are None, continue
if all(map(lambda x:x is None, g_outputs)): continue if all(map(lambda x:x is None, g_outputs)): continue
# output_arg = _unpack_result(g_outputs)
# input_arg = _unpack_result(op.inputs)
output_arg = g_outputs output_arg = g_outputs
input_arg = op.inputs input_arg = op.inputs
...@@ -90,8 +74,6 @@ def grad_sources_inputs(sources, graph_inputs): ...@@ -90,8 +74,6 @@ def grad_sources_inputs(sources, graph_inputs):
except AttributeError: except AttributeError:
dinputs = [] dinputs = []
# input_arg = [input in dinputs and input.copy() or input for input in input_arg]
new_input_arg = [] new_input_arg = []
for input in input_arg: for input in input_arg:
if input in dinputs: if input in dinputs:
......
...@@ -11,7 +11,7 @@ import numpy ...@@ -11,7 +11,7 @@ import numpy
from scipy import sparse from scipy import sparse
import gof.op, gof.result import gof.op, gof.result
import tensor, base_tensor import tensor
...@@ -20,19 +20,19 @@ import tensor, base_tensor ...@@ -20,19 +20,19 @@ import tensor, base_tensor
def _is_sparse_result(x): def _is_sparse_result(x):
""" """
@rtype: boolean @rtype: boolean
@return: True iff x is a L{SparseResult} (and not a L{base_tensor.BaseTensor}) @return: True iff x is a L{SparseResult} (and not a L{tensor.Tensor})
""" """
if not isinstance(x, SparseResult) and not isinstance(x, base_tensor.BaseTensor): if not isinstance(x, SparseResult) and not isinstance(x, tensor.Tensor):
raise NotImplementedError("_is_sparse should only be called on sparse.SparseResult or base_tensor.BaseTensor, not,", x) raise NotImplementedError("_is_sparse should only be called on sparse.SparseResult or tensor.Tensor, not,", x)
return isinstance(x, SparseResult) return isinstance(x, SparseResult)
def _is_dense_result(x): def _is_dense_result(x):
""" """
@rtype: boolean @rtype: boolean
@return: True unless x is a L{SparseResult} (and not a L{base_tensor.BaseTensor}) @return: True unless x is a L{SparseResult} (and not a L{tensor.Tensor})
""" """
if not isinstance(x, SparseResult) and not isinstance(x, base_tensor.BaseTensor): if not isinstance(x, SparseResult) and not isinstance(x, tensor.Tensor):
raise NotImplementedError("_is_sparse should only be called on sparse.SparseResult or base_tensor.BaseTensor, not,", x) raise NotImplementedError("_is_sparse should only be called on sparse.SparseResult or tensor.Tensor, not,", x)
return isinstance(x, base_tensor.BaseTensor) return isinstance(x, tensor.Tensor)
def _is_sparse(x): def _is_sparse(x):
""" """
......
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论