提交 177cc884 authored 作者: Frédéric Bastien's avatar Frédéric Bastien 提交者: GitHub

Merge pull request #5908 from nouiz/compute_test_value

crash fix and opt warning fix(make opt apply)
...@@ -271,6 +271,7 @@ class OpFromGraph(gof.Op): ...@@ -271,6 +271,7 @@ class OpFromGraph(gof.Op):
is_inline = self.is_inline is_inline = self.is_inline
return '%(name)s{inline=%(is_inline)s}' % locals() return '%(name)s{inline=%(is_inline)s}' % locals()
@theano.configparser.change_flags(compute_test_value='off')
def _recompute_grad_op(self): def _recompute_grad_op(self):
''' '''
converts self._grad_op from user supplied form to type(self) instance converts self._grad_op from user supplied form to type(self) instance
......
...@@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function, division ...@@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function, division
from functools import partial from functools import partial
import numpy as np import numpy as np
import theano
from theano import config, shared from theano import config, shared
from theano.gradient import DisconnectedType from theano.gradient import DisconnectedType
...@@ -313,3 +314,14 @@ class T_OpFromGraph(unittest_tools.InferShapeTester): ...@@ -313,3 +314,14 @@ class T_OpFromGraph(unittest_tools.InferShapeTester):
[np.ones([3, 4], dtype=config.floatX), [np.ones([3, 4], dtype=config.floatX),
np.ones([3, 4], dtype=config.floatX)], np.ones([3, 4], dtype=config.floatX)],
OpFromGraph) OpFromGraph)
@theano.configparser.change_flags(compute_test_value='raise')
def test_compute_test_value(self):
x = T.scalar('x')
x.tag.test_value = np.array(1., dtype=config.floatX)
op = OpFromGraph([x], [x ** 3])
y = T.scalar('y')
y.tag.test_value = np.array(1., dtype=config.floatX)
f = op(y)
grad_f = T.grad(f, y)
assert grad_f.tag.test_value is not None
...@@ -5710,41 +5710,50 @@ def local_opt_alloc(node): ...@@ -5710,41 +5710,50 @@ def local_opt_alloc(node):
if node_inps.owner and isinstance(node_inps.owner.op, T.Alloc): if node_inps.owner and isinstance(node_inps.owner.op, T.Alloc):
input = node_inps.owner.inputs[0] input = node_inps.owner.inputs[0]
shapes = node_inps.owner.inputs[1:] shapes = node_inps.owner.inputs[1:]
if (node.op.axis is None or try:
node.op.axis == tuple(range(input.ndim))): val = get_scalar_constant_value(input,
try: only_process_constants=True)
val = get_scalar_constant_value(input, assert val.size == 1
only_process_constants=True) val = val.reshape(1)[0]
assert val.size == 1 # check which type of op
# check which type of op size = T.mul(*shapes)
casted = T.mul(*shapes).astype(str(input.dtype)) if input.dtype in ["float16", "float32"]:
# shapes are ints and normally int64.
# We don't want to have a float64 upcast
# We don't want to downcast to float16
# as we fear it could loose too much precision
# that will be amplified by the mul/pow below.
size = size.astype('float32')
if (node.op.axis is None or
node.op.axis == tuple(range(input.ndim))):
if isinstance(node.op, T.Sum): if isinstance(node.op, T.Sum):
val = val.reshape(1)[0] * casted val = val * size
else: else:
val = val.reshape(1)[0] ** casted val = val ** size
# Sum can change the input dtype (upcast or bool
# -> float32) by default or by user request.
# We can ignore the acc_dtype, as there is only 1
# elemwise we will do and not a sequence, so there is no
# accumulation of errors.
# So mostly, we just need to cast the output to the old
# dtype.
val = val.astype(node.outputs[0].dtype)
return [val] return [val]
to_prod = [shapes[i] for i in xrange(len(shapes))
except NotScalarConstantError: if i in node.op.axis]
pass if to_prod:
else: size = T.mul(*to_prod)
try: if isinstance(node.op, T.Sum):
val = get_scalar_constant_value(input, val *= size
only_process_constants=True) else:
assert val.size == 1 val = val ** size
val = val.reshape(1)[0] # See comments above.
to_prod = [shapes[i] for i in xrange(len(shapes)) val = val.astype(node.outputs[0].dtype)
if i in node.op.axis] return [T.alloc(val,
if to_prod: *[shapes[i] for i in xrange(len(shapes))
casted = T.mul(*to_prod).astype(str(input.dtype)) if i not in node.op.axis])]
if isinstance(node.op, T.Sum): except NotScalarConstantError:
val *= casted pass
else:
val = val ** casted
return [T.alloc(val,
*[shapes[i] for i in xrange(len(shapes))
if i not in node.op.axis])]
except NotScalarConstantError:
pass
@register_specialize @register_specialize
......
...@@ -5558,9 +5558,11 @@ class T_local_sum_prod(unittest.TestCase): ...@@ -5558,9 +5558,11 @@ class T_local_sum_prod(unittest.TestCase):
class T_local_opt_alloc(unittest.TestCase): class T_local_opt_alloc(unittest.TestCase):
dtype = 'float32'
def test_sum_upcast(self): def test_sum_upcast(self):
s = theano.tensor.lscalar() s = theano.tensor.lscalar()
a = theano.tensor.alloc(np.asarray(5, dtype='float32'), s, s) a = theano.tensor.alloc(np.asarray(5, dtype=self.dtype), s, s)
orig = theano.config.warn_float64 orig = theano.config.warn_float64
theano.config.warn_float64 = "raise" theano.config.warn_float64 = "raise"
try: try:
...@@ -5571,7 +5573,7 @@ class T_local_opt_alloc(unittest.TestCase): ...@@ -5571,7 +5573,7 @@ class T_local_opt_alloc(unittest.TestCase):
def test_prod_upcast(self): def test_prod_upcast(self):
s = theano.tensor.lscalar() s = theano.tensor.lscalar()
a = theano.tensor.alloc(np.asarray(5, dtype='float32'), s, s) a = theano.tensor.alloc(np.asarray(5, dtype=self.dtype), s, s)
orig = theano.config.warn_float64 orig = theano.config.warn_float64
theano.config.warn_float64 = "raise" theano.config.warn_float64 = "raise"
try: try:
...@@ -5580,6 +5582,24 @@ class T_local_opt_alloc(unittest.TestCase): ...@@ -5580,6 +5582,24 @@ class T_local_opt_alloc(unittest.TestCase):
finally: finally:
theano.config.warn_float64 = orig theano.config.warn_float64 = orig
@theano.configparser.change_flags(on_opt_error='raise')
def test_sum_bool_upcast(self):
s = theano.tensor.lscalar()
a = theano.tensor.alloc(np.asarray(True, dtype='bool'), s, s)
f = theano.function([s], a.sum())
f(5)
# test with user specified dtype
f = theano.function([s], a.sum(dtype=self.dtype))
f(5)
# test only 1 axis summed
f = theano.function([s], a.sum(axis=0, dtype=self.dtype))
f(5)
print(self.dtype)
class T_local_opt_alloc_f16(T_local_opt_alloc):
dtype = 'float16'
class T_local_reduce(unittest.TestCase): class T_local_reduce(unittest.TestCase):
def setUp(self): def setUp(self):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论