提交 963eac17 authored 作者: Frédéric Bastien's avatar Frédéric Bastien

Merge pull request #4287 from lamblin/fix_neg_bool

Make sure the input of Neg.impl is not a numpy.bool_
...@@ -2399,9 +2399,19 @@ round_half_away_from_zero = RoundHalfAwayFromZero(same_out_float_only) ...@@ -2399,9 +2399,19 @@ round_half_away_from_zero = RoundHalfAwayFromZero(same_out_float_only)
class Neg(UnaryScalarOp): class Neg(UnaryScalarOp):
# We can use numpy.negative here, because even if it gives unexpected
# results on Boolean arrays, it will be passed other dtypes as Theano
# does not have a Boolean type for tensors.
nfunc_spec = ('negative', 1, 1) nfunc_spec = ('negative', 1, 1)
def impl(self, x): def impl(self, x):
# We have to make sure x is not a numpy.bool_, because
# `-numpy.bool_(True)` is `False` (we want 0), and
# `-numpy.bool_(False)` is `True` (we want 1).
# This happens for Composite, as the intermediate results are not
# casted in the dtype of the intermediate variable in general.
if isinstance(x, numpy.bool_):
x = numpy.int8(x)
return -x return -x
def grad(self, inputs, gout): def grad(self, inputs, gout):
......
...@@ -155,6 +155,17 @@ class test_composite(unittest.TestCase): ...@@ -155,6 +155,17 @@ class test_composite(unittest.TestCase):
si3 = theano.scalar.float32() si3 = theano.scalar.float32()
sop.make_node(si0 * si3, si1, si2) sop.make_node(si0 * si3, si1, si2)
def test_composite_neg_bool(self):
# Check that taking the negation of a Boolean intermediate value
# works correctly with Python code. It used to be an issue because
# `-numpy.bool_(True)` is False and `-numpy.bool_(False)` is True.
x = floats('x')
y = - (x > 0)
z = Composite([x], [y]).make_node(x).outputs[0]
f = theano.function([x], z, mode=theano.Mode(linker='py'))
for inp, out in zip([-1, 0, 1], [0, 0, -1]):
self.assertTrue(f(inp) == out)
class test_logical(unittest.TestCase): class test_logical(unittest.TestCase):
def test_gt(self): def test_gt(self):
......
...@@ -8105,6 +8105,15 @@ def test_symbolic_slice(): ...@@ -8105,6 +8105,15 @@ def test_symbolic_slice():
output = a.eval({x: numpy.zeros((5, 4, 3, 2), dtype=theano.config.floatX)}) output = a.eval({x: numpy.zeros((5, 4, 3, 2), dtype=theano.config.floatX)})
assert output == numpy.array(5) assert output == numpy.array(5)
def test_composite_neg_bool():
# Check that taking the negation of a Boolean intermediate value
# works correctly with Python code. It used to be an issue because
# `-numpy.bool_(True)` is False and `-numpy.bool_(False)` is True.
x = theano.tensor.vector()
f = theano.function([x], - (x > 0), mode=theano.Mode(linker='py'))
utt.assert_allclose(f([-1, 0, 1]), [0, 0, -1])
""" """
if __name__ == '__main__': if __name__ == '__main__':
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论