提交 8a45c933 authored 作者: David Warde-Farley's avatar David Warde-Farley

Merge.

...@@ -51,9 +51,9 @@ copyright = '2008--2009, LISA lab' ...@@ -51,9 +51,9 @@ copyright = '2008--2009, LISA lab'
# other places throughout the built documents. # other places throughout the built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.1' version = '0.3'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.1' release = '0.3'
# There are two options for replacing |today|: either, you set today to some # There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used: # non-false value, then it is used:
......
...@@ -47,7 +47,7 @@ welcome on the mailing list. ...@@ -47,7 +47,7 @@ welcome on the mailing list.
6) Each release will be uploaded to pypi.python.org, mloss.org and freshmeat.net 6) Each release will be uploaded to pypi.python.org, mloss.org and freshmeat.net
7) Release emails will be sent to theano-users and theano-announce. 7) Release emails will be sent to theano-users, theano-announce, numpy-discussion@scipy.org and scipy-user@scipy.org .
Optional: Optional:
......
...@@ -441,6 +441,26 @@ class test_structureddot(unittest.TestCase): ...@@ -441,6 +441,26 @@ class test_structureddot(unittest.TestCase):
self.failUnless(numpy.allclose(theano_result, scipy_result)) self.failUnless(numpy.allclose(theano_result, scipy_result))
self.failIf(theano_time > overhead_rtol*scipy_time + overhead_tol) self.failIf(theano_time > overhead_rtol*scipy_time + overhead_tol)
def test_shape_i():
sparse_dtype = 'float32'
a = SparseType('csr', dtype=sparse_dtype)()
f = theano.function([a], a.shape[1], mode='FAST_RUN')
assert f(sp.csr_matrix(random_lil((100,10), sparse_dtype, 3)))==(10)
def test_shape():
sparse_dtype = 'float32'
a = SparseType('csr', dtype=sparse_dtype)()
f = theano.function([a], a.shape, mode='FAST_RUN')
assert numpy.all(f(sp.csr_matrix(random_lil((100,10), sparse_dtype, 3)))==(100,10))
if theano.config.mode!='FAST_COMPILE':
topo = f.maker.env.toposort()
assert len(topo)==3
assert isinstance(topo[0].op,tensor.opt.Shape_i)
assert isinstance(topo[1].op,tensor.opt.Shape_i)
assert isinstance(topo[2].op,tensor.opt.MakeVector)
import theano.tensor.tests.test_sharedvar import theano.tensor.tests.test_sharedvar
test_shared_options=theano.tensor.tests.test_sharedvar.makeSharedTester( test_shared_options=theano.tensor.tests.test_sharedvar.makeSharedTester(
theano.sparse.shared, 'float64', theano.sparse.shared, 'float64',
......
...@@ -1444,7 +1444,11 @@ class Shape(Op): ...@@ -1444,7 +1444,11 @@ class Shape(Op):
def __str__(self): def __str__(self):
return self.__class__.__name__ return self.__class__.__name__
def make_node(self, x): def make_node(self, x):
x = as_tensor_variable(x) if not isinstance(x, Variable):
raise TypeError('x must be Variable whose value have a shape attribute', x)
#Must work for all type that have a shape attribute.
#This will fail at execution time.
#x = as_tensor_variable(x)
return Apply(self, [x], [lvector()]) return Apply(self, [x], [lvector()])
def perform(self, node, (x, ), (out, )): def perform(self, node, (x, ), (out, )):
out[0] = theano._asarray(x.shape, dtype = 'int64') out[0] = theano._asarray(x.shape, dtype = 'int64')
......
...@@ -465,7 +465,7 @@ class ShapeFeature(object): ...@@ -465,7 +465,7 @@ class ShapeFeature(object):
""" """
def shape_i(self, i): def shape_i(self, i):
def op_deco(r): def op_deco(r):
if r.type.broadcastable[i]: if hasattr(r.type,"broadcastable") and r.type.broadcastable[i]:
return self.lscalar_one return self.lscalar_one
else: else:
return Shape_i(i)(r) return Shape_i(i)(r)
......
""" test code snipet in the Theano tutorials.
"""
import unittest import unittest
import theano import theano
import theano.tensor as T import theano.tensor as T
...@@ -33,7 +36,7 @@ class T_extending(unittest.TestCase): ...@@ -33,7 +36,7 @@ class T_extending(unittest.TestCase):
return float(x) return float(x)
def values_eq_approx(x, y, tolerance=1e-4): def values_eq_approx(x, y, tolerance=1e-4):
return abs(x - y) / (abs(x) + abs(y)) < tolerance return abs(x - y) / (abs(x) + abs(y)) < tolerance
from theano import gof from theano import gof
...@@ -47,13 +50,13 @@ class T_extending(unittest.TestCase): ...@@ -47,13 +50,13 @@ class T_extending(unittest.TestCase):
class Double(gof.Type): class Double(gof.Type):
def filter(self, x, strict=False): def filter(self, x, strict=False):
if strict and not isinstance(x, float): if strict and not isinstance(x, float):
raise TypeError('Expected a float!') raise TypeError('Expected a float!')
return float(x) return float(x)
def values_eq_approx(self, x, y, tolerance=1e-4): def values_eq_approx(self, x, y, tolerance=1e-4):
return abs(x - y) / (abs(x) + abs(y)) < tolerance return abs(x - y) / (abs(x) + abs(y)) < tolerance
double = Double() double = Double()
...@@ -67,16 +70,16 @@ class T_extending(unittest.TestCase): ...@@ -67,16 +70,16 @@ class T_extending(unittest.TestCase):
class Double(gof.Type): class Double(gof.Type):
def filter(self, x, strict=False, allow_downcast=None): def filter(self, x, strict=False, allow_downcast=None):
if strict and not isinstance(x, float): if strict and not isinstance(x, float):
raise TypeError('Expected a float!') raise TypeError('Expected a float!')
return float(x) return float(x)
def values_eq_approx(self, x, y, tolerance=1e-4): def values_eq_approx(self, x, y, tolerance=1e-4):
return abs(x - y) / (abs(x) + abs(y)) < tolerance return abs(x - y) / (abs(x) + abs(y)) < tolerance
def __str__(self): def __str__(self):
return "double" return "double"
double = Double() double = Double()
...@@ -107,13 +110,13 @@ class T_extending(unittest.TestCase): ...@@ -107,13 +110,13 @@ class T_extending(unittest.TestCase):
def make_node(x, y): def make_node(x, y):
if isinstance(x, (int, float)): if isinstance(x, (int, float)):
x = gof.Constant(double, x) x = gof.Constant(double, x)
if isinstance(y, (int, float)): if isinstance(y, (int, float)):
y = gof.Constant(double, y) y = gof.Constant(double, y)
if x.type != double or y.type != double: if x.type != double or y.type != double:
raise TypeError('mul only works on doubles') raise TypeError('mul only works on doubles')
return gof.Apply(mul, [x, y], [double()]) return gof.Apply(mul, [x, y], [double()])
mul.make_node = make_node mul.make_node = make_node
...@@ -125,30 +128,30 @@ class T_extending(unittest.TestCase): ...@@ -125,30 +128,30 @@ class T_extending(unittest.TestCase):
from theano import gof from theano import gof
class BinaryDoubleOp(gof.Op): class BinaryDoubleOp(gof.Op):
def __init__(self, name, fn): def __init__(self, name, fn):
self.name = name self.name = name
self.fn = fn self.fn = fn
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) and (self.name == other.name) and (self.fn == other.fn) return type(self) == type(other) and (self.name == other.name) and (self.fn == other.fn)
def __hash__(self): def __hash__(self):
return hash(type(self)) ^ hash(self.name) ^ hash(self.fn) return hash(type(self)) ^ hash(self.name) ^ hash(self.fn)
def make_node(self, x, y): def make_node(self, x, y):
if isinstance(x, (int, float)): if isinstance(x, (int, float)):
x = gof.Constant(double, x) x = gof.Constant(double, x)
if isinstance(y, (int, float)): if isinstance(y, (int, float)):
y = gof.Constant(double, y) y = gof.Constant(double, y)
if x.type != double or y.type != double: if x.type != double or y.type != double:
raise TypeError('%s only works on doubles' % self.name) raise TypeError('%s only works on doubles' % self.name)
return gof.Apply(self, [x, y], [double()]) return gof.Apply(self, [x, y], [double()])
def perform(self, node, (x, y), (z, )): def perform(self, node, (x, y), (z, )):
z[0] = self.fn(x, y) z[0] = self.fn(x, y)
def __str__(self): def __str__(self):
return self.name return self.name
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name = 'add',
fn = lambda x, y: x + y) fn = lambda x, y: x + y)
...@@ -175,44 +178,44 @@ class T_extending(unittest.TestCase): ...@@ -175,44 +178,44 @@ class T_extending(unittest.TestCase):
class Double(gof.Type): class Double(gof.Type):
def filter(self, x, strict=False, allow_downcast=None): def filter(self, x, strict=False, allow_downcast=None):
if strict and not isinstance(x, float): if strict and not isinstance(x, float):
raise TypeError('Expected a float!') raise TypeError('Expected a float!')
return float(x) return float(x)
def values_eq_approx(self, x, y, tolerance=1e-4): def values_eq_approx(self, x, y, tolerance=1e-4):
return abs(x - y) / (abs(x) + abs(y)) < tolerance return abs(x - y) / (abs(x) + abs(y)) < tolerance
def __str__(self): def __str__(self):
return "double" return "double"
double = Double() double = Double()
class BinaryDoubleOp(gof.Op): class BinaryDoubleOp(gof.Op):
def __init__(self, name, fn): def __init__(self, name, fn):
self.name = name self.name = name
self.fn = fn self.fn = fn
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) and (self.name == other.name) and (self.fn == other.fn) return type(self) == type(other) and (self.name == other.name) and (self.fn == other.fn)
def __hash__(self): def __hash__(self):
return hash(type(self)) ^ hash(self.name) ^ hash(self.fn) return hash(type(self)) ^ hash(self.name) ^ hash(self.fn)
def make_node(self, x, y): def make_node(self, x, y):
if isinstance(x, (int, float)): if isinstance(x, (int, float)):
x = gof.Constant(double, x) x = gof.Constant(double, x)
if isinstance(y, (int, float)): if isinstance(y, (int, float)):
y = gof.Constant(double, y) y = gof.Constant(double, y)
if x.type != double or y.type != double: if x.type != double or y.type != double:
raise TypeError('%s only works on doubles' % self.name) raise TypeError('%s only works on doubles' % self.name)
return gof.Apply(self, [x, y], [double()]) return gof.Apply(self, [x, y], [double()])
def perform(self, node, (x, y), (z, )): def perform(self, node, (x, y), (z, )):
z[0] = self.fn(x, y) z[0] = self.fn(x, y)
def __str__(self): def __str__(self):
return self.name return self.name
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name = 'add',
fn = lambda x, y: x + y) fn = lambda x, y: x + y)
...@@ -281,87 +284,87 @@ class T_extending(unittest.TestCase): ...@@ -281,87 +284,87 @@ class T_extending(unittest.TestCase):
from theano import gof from theano import gof
class Double(gof.Type): class Double(gof.Type):
def filter(self, x, strict=False, allow_downcast=None): def filter(self, x, strict=False, allow_downcast=None):
if strict and not isinstance(x, float): if strict and not isinstance(x, float):
raise TypeError('Expected a float!') raise TypeError('Expected a float!')
return float(x) return float(x)
def values_eq_approx(self, x, y, tolerance=1e-4): def values_eq_approx(self, x, y, tolerance=1e-4):
return abs(x - y) / (x + y) < tolerance return abs(x - y) / (x + y) < tolerance
def __str__(self): def __str__(self):
return "double" return "double"
def c_declare(self, name, sub): def c_declare(self, name, sub):
return """ return """
double %(name)s; double %(name)s;
""" % dict(name = name) """ % dict(name = name)
def c_init(self, name, sub): def c_init(self, name, sub):
return """ return """
%(name)s = 0.0; %(name)s = 0.0;
""" % dict(name = name) """ % dict(name = name)
def c_extract(self, name, sub): def c_extract(self, name, sub):
return """ return """
if (!PyFloat_Check(py_%(name)s)) { if (!PyFloat_Check(py_%(name)s)) {
PyErr_SetString(PyExc_TypeError, "expected a float"); PyErr_SetString(PyExc_TypeError, "expected a float");
%(fail)s %(fail)s
} }
%(name)s = PyFloat_AsDouble(py_%(name)s); %(name)s = PyFloat_AsDouble(py_%(name)s);
""" % dict(sub, name = name) """ % dict(sub, name = name)
def c_sync(self, name, sub): def c_sync(self, name, sub):
return """ return """
Py_XDECREF(py_%(name)s); Py_XDECREF(py_%(name)s);
py_%(name)s = PyFloat_FromDouble(%(name)s); py_%(name)s = PyFloat_FromDouble(%(name)s);
if (!py_%(name)s) { if (!py_%(name)s) {
printf("PyFloat_FromDouble failed on: %%f\\n", %(name)s); printf("PyFloat_FromDouble failed on: %%f\\n", %(name)s);
Py_XINCREF(Py_None); Py_XINCREF(Py_None);
py_%(name)s = Py_None; py_%(name)s = Py_None;
} }
""" % dict(name = name) """ % dict(name = name)
def c_cleanup(self, name, sub): def c_cleanup(self, name, sub):
return "" return ""
double = Double() double = Double()
def c_code(node, name, input_names, output_names, sub): def c_code(node, name, input_names, output_names, sub):
x_name, y_name = input_names[0], input_names[1] x_name, y_name = input_names[0], input_names[1]
output_name = output_names[0] output_name = output_names[0]
return """ return """
%(output_name)s = %(x_name)s * %(y_name)s; %(output_name)s = %(x_name)s * %(y_name)s;
""" % locals() """ % locals()
mul.c_code = c_code mul.c_code = c_code
from theano import gof from theano import gof
class BinaryDoubleOp(gof.Op): class BinaryDoubleOp(gof.Op):
def __init__(self, name, fn, ccode): def __init__(self, name, fn, ccode):
self.name = name self.name = name
self.fn = fn self.fn = fn
self.ccode = ccode self.ccode = ccode
def make_node(self, x, y): def make_node(self, x, y):
if isinstance(x, (int, float)): if isinstance(x, (int, float)):
x = gof.Constant(double, x) x = gof.Constant(double, x)
if isinstance(y, (int, float)): if isinstance(y, (int, float)):
y = gof.Constant(double, y) y = gof.Constant(double, y)
if x.type != double or y.type != double: if x.type != double or y.type != double:
raise TypeError('%s only works on doubles' % self.name) raise TypeError('%s only works on doubles' % self.name)
return gof.Apply(self, [x, y], [double()]) return gof.Apply(self, [x, y], [double()])
def perform(self, node, (x, y), (z, )): def perform(self, node, (x, y), (z, )):
z[0] = self.fn(x, y) z[0] = self.fn(x, y)
def __str__(self): def __str__(self):
return self.name return self.name
def c_code(self, node, name, (x, y), (z, ), sub): def c_code(self, node, name, (x, y), (z, ), sub):
return self.ccode % locals() return self.ccode % locals()
add = BinaryDoubleOp(name = 'add', add = BinaryDoubleOp(name = 'add',
...@@ -384,19 +387,19 @@ class T_extending(unittest.TestCase): ...@@ -384,19 +387,19 @@ class T_extending(unittest.TestCase):
from theano.gof import toolbox from theano.gof import toolbox
class Simplify(gof.Optimizer): class Simplify(gof.Optimizer):
def add_requirements(self, env): def add_requirements(self, env):
env.extend(toolbox.ReplaceValidate()) env.extend(toolbox.ReplaceValidate())
def apply(self, env): def apply(self, env):
for node in env.toposort(): for node in env.toposort():
if node.op == div: if node.op == div:
x, y = node.inputs x, y = node.inputs
z = node.outputs[0] z = node.outputs[0]
if x.owner and x.owner.op == mul: if x.owner and x.owner.op == mul:
a, b = x.owner.inputs a, b = x.owner.inputs
if y == a: if y == a:
env.replace_validate(z, b) env.replace_validate(z, b)
elif y == b: elif y == b:
env.replace_validate(z, a) env.replace_validate(z, a)
simplify = Simplify() simplify = Simplify()
x = double('x') x = double('x')
...@@ -407,21 +410,21 @@ class T_extending(unittest.TestCase): ...@@ -407,21 +410,21 @@ class T_extending(unittest.TestCase):
simplify.optimize(e) simplify.optimize(e)
class LocalSimplify(gof.LocalOptimizer): class LocalSimplify(gof.LocalOptimizer):
def transform(self, node): def transform(self, node):
if node.op == div: if node.op == div:
x, y = node.inputs x, y = node.inputs
if x.owner and x.owner.op == mul: if x.owner and x.owner.op == mul:
a, b = x.owner.inputs a, b = x.owner.inputs
if y == a: if y == a:
return [b] return [b]
elif y == b: elif y == b:
return [a] return [a]
return False return False
def tracks(self): def tracks(self):
# This should be needed for the EquilibriumOptimizer # This should be needed for the EquilibriumOptimizer
# but it isn't now # but it isn't now
# TODO: do this and explain it # TODO: do this and explain it
return [] # that's not what you should do return [] # that's not what you should do
local_simplify = LocalSimplify() local_simplify = LocalSimplify()
...@@ -595,7 +598,7 @@ class T_examples(unittest.TestCase): ...@@ -595,7 +598,7 @@ class T_examples(unittest.TestCase):
fn_of_state = state * 2 + inc fn_of_state = state * 2 + inc
foo = T.lscalar() # the type (lscalar) must match the shared variable we foo = T.lscalar() # the type (lscalar) must match the shared variable we
# are replacing with the ``givens`` list # are replacing with the ``givens`` list
skip_shared = function([inc, foo], fn_of_state, skip_shared = function([inc, foo], fn_of_state,
givens=[(state, foo)]) givens=[(state, foo)])
assert skip_shared(1, 3) == array(7) assert skip_shared(1, 3) == array(7)
...@@ -967,7 +970,3 @@ class T_graphstructures(unittest.TestCase): ...@@ -967,7 +970,3 @@ class T_graphstructures(unittest.TestCase):
assert e.owner.inputs[1] is mul_variable assert e.owner.inputs[1] is mul_variable
assert e.owner.inputs[1].owner.inputs[0] is y assert e.owner.inputs[1].owner.inputs[0] is y
assert e.owner.inputs[1].owner.inputs[1] is z assert e.owner.inputs[1].owner.inputs[1] is z
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论