提交 c6398151 authored 作者: lamblin's avatar lamblin

Merge pull request #1416 from nouiz/reduce_dtype_noaxis

[BUGFIX] Reduce dtype noaxis
......@@ -301,6 +301,12 @@ class Scalar(Type):
ret.imag = -this->imag;
return ret;
}
bool operator ==(const complex_type &y) const {
return (this->real == y.real) && (this->imag == y.imag);
}
bool operator ==(const npy_float%(nbits)s &y) const {
return (this->real == y) && (this->imag == 0);
}
complex_type operator -(const complex_type &y) const {
complex_type ret;
ret.real = this->real - y.real;
......
......@@ -1463,8 +1463,13 @@ class CAReduce(Op):
axis = range(len(input.type.broadcastable))
if len(axis) == 0:
op = Elemwise(scalar.identity)
return op._c_all(op.make_node(input), name, inames, onames, sub)
# The acc_dtype is never a downcast compared to the input dtype
# So we just need a cast to the output dtype.
var = theano.tensor.cast(input, node.outputs[0].dtype)
if var is input:
var = Elemwise(scalar.identity)(input)
assert var.dtype == node.outputs[0].dtype
return var.owner.op._c_all(var.owner, name, inames, onames, sub)
order1 = [i for i in xrange(input.type.ndim) if i not in axis]
order = order1 + list(axis)
......
......@@ -617,11 +617,12 @@ class T_sum_dtype(unittest.TestCase):
Test the default dtype of a sum().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
for idx, dtype in enumerate(imap(str, theano.scalar.all_types)):
axis = axes[idx % len(axes)]
x = tensor.matrix(dtype=dtype).sum(axis=axis)
assert x.dtype == dict(
x = tensor.matrix(dtype=dtype)
s = x.sum(axis=axis)
assert s.dtype == dict(
int8='int64',
int16='int64',
int32='int64',
......@@ -629,15 +630,20 @@ class T_sum_dtype(unittest.TestCase):
uint16='uint64',
uint32='uint64',
).get(dtype, dtype)
f = theano.function([x], s)
data = numpy.random.rand(3, 4) * 10
data = data.astype(dtype)
f(data)
def test_sum_default_acc_dtype(self):
##Test the default acc_dtype of a sum().
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
for idx, dtype in enumerate(imap(str, theano.scalar.all_types)):
axis = axes[idx % len(axes)]
x = tensor.matrix(dtype=dtype).sum(axis=axis)
assert x.owner.op.acc_dtype == dict(
x = tensor.matrix(dtype=dtype)
s = x.sum(axis=axis)
assert s.owner.op.acc_dtype == dict(
int8='int64',
int16='int64',
int32='int64',
......@@ -647,13 +653,17 @@ class T_sum_dtype(unittest.TestCase):
float32='float64',
complex64='complex128',
).get(dtype, dtype)
f = theano.function([x], s)
data = numpy.random.rand(3, 4) * 10
data = data.astype(dtype)
f(data)
def test_sum_custom_dtype(self):
"""
Test the ability to provide your own output dtype for a sum.
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
idx = 0
for input_dtype in imap(str, theano.scalar.all_types):
x = tensor.matrix(dtype=input_dtype)
......@@ -669,6 +679,10 @@ class T_sum_dtype(unittest.TestCase):
sum_var = x.sum(dtype=output_dtype, axis=axis)
assert sum_var.dtype == output_dtype
f = theano.function([x], sum_var)
data = numpy.random.rand(3, 4) * 10
data = data.astype(input_dtype)
f(data)
if "complex" in input_dtype:
continue
# Check that we can take the gradient
......@@ -681,7 +695,7 @@ class T_sum_dtype(unittest.TestCase):
Test the ability to provide your own accumulator dtype for a sum.
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
idx = 0
for input_dtype in imap(str, theano.scalar.all_types):
x = tensor.matrix(dtype=input_dtype)
......@@ -730,21 +744,26 @@ class T_mean_dtype(unittest.TestCase):
Test the default dtype of a mean().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
for idx, dtype in enumerate(imap(str, theano.scalar.all_types)):
axis = axes[idx % len(axes)]
x = tensor.matrix(dtype=dtype).mean(axis=axis)
if dtype in tensor.discrete_dtypes:
assert x.dtype == 'float64'
x = tensor.matrix(dtype=dtype)
m = x.mean(axis=axis)
if dtype in tensor.discrete_dtypes and axis != []:
assert m.dtype == 'float64'
else:
assert x.dtype == dtype, (x, x.dtype, dtype)
assert m.dtype == dtype, (m, m.dtype, dtype)
f = theano.function([x], m)
data = numpy.random.rand(3, 4) * 10
data = data.astype(dtype)
f(data)
def test_mean_custom_dtype(self):
"""
Test the ability to provide your own output dtype for a mean.
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
idx = 0
for input_dtype in imap(str, theano.scalar.all_types):
x = tensor.matrix(dtype=input_dtype)
......@@ -758,12 +777,20 @@ class T_mean_dtype(unittest.TestCase):
pass
else:
# Executed if no TypeError was raised
if sum_dtype in tensor.discrete_dtypes:
if sum_dtype in tensor.discrete_dtypes and axis != []:
assert mean_var.dtype == 'float64', (
(mean_var.dtype, sum_dtype))
else:
assert mean_var.dtype == sum_dtype, (
(mean_var.dtype, sum_dtype))
if (('complex' in input_dtype or
'complex' in sum_dtype) and
input_dtype != sum_dtype):
continue
f = theano.function([x], mean_var)
data = numpy.random.rand(3, 4) * 10
data = data.astype(input_dtype)
f(data)
# Check that we can take the gradient, when implemented
if "complex" in mean_var.dtype:
continue
......@@ -795,11 +822,12 @@ class T_prod_dtype(unittest.TestCase):
Test the default dtype of a prod().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
for idx, dtype in enumerate(imap(str, theano.scalar.all_types)):
axis = axes[idx % len(axes)]
x = tensor.matrix(dtype=dtype).prod(axis=axis)
assert x.dtype == dict(
x = tensor.matrix(dtype=dtype)
p = x.prod(axis=axis)
assert p.dtype == dict(
int8='int64',
int16='int64',
int32='int64',
......@@ -807,17 +835,22 @@ class T_prod_dtype(unittest.TestCase):
uint16='uint64',
uint32='uint64',
).get(dtype, dtype)
f = theano.function([x], p)
data = numpy.random.rand(3, 4) * 10
data = data.astype(dtype)
f(data)
def test_prod_default_acc_dtype(self):
"""
Test the default acc_dtype of a prod().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
for idx, dtype in enumerate(imap(str, theano.scalar.all_types)):
axis = axes[idx % len(axes)]
x = tensor.matrix(dtype=dtype).prod(axis=axis)
assert x.owner.op.acc_dtype == dict(
x = tensor.matrix(dtype=dtype)
p = x.prod(axis=axis)
assert p.owner.op.acc_dtype == dict(
int8='int64',
int16='int64',
int32='int64',
......@@ -827,34 +860,48 @@ class T_prod_dtype(unittest.TestCase):
float32='float64',
complex64='complex128',
).get(dtype, dtype)
f = theano.function([x], p)
data = numpy.random.rand(3, 4) * 10
data = data.astype(dtype)
f(data)
def test_prod_custom_dtype(self):
"""
Test the ability to provide your own output dtype for a prod.
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
idx = 0
for input_dtype in imap(str, theano.scalar.all_types):
x = tensor.matrix(dtype=input_dtype)
for output_dtype in imap(str, theano.scalar.all_types):
axis = axes[idx % len(axes)]
idx += 1
prod_var = x.prod(dtype=output_dtype, axis=axis)
assert prod_var.dtype == output_dtype
if (('complex' in output_dtype or
'complex' in input_dtype) and
input_dtype != output_dtype):
continue
f = theano.function([x], prod_var)
data = numpy.random.rand(3, 4) * 10
data = data.astype(input_dtype)
f(data)
if "complex" in output_dtype or "complex" in input_dtype:
continue
# Check that we can take the gradient
tensor.grad(prod_var.sum(), x,
disconnected_inputs='ignore')
idx += 1
def test_prod_custom_acc_dtype(self):
"""
Test the ability to provide your own acc_dtype for a prod.
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
idx = 0
for input_dtype in imap(str, theano.scalar.all_types):
x = tensor.matrix(dtype=input_dtype)
......@@ -870,6 +917,14 @@ class T_prod_dtype(unittest.TestCase):
prod_var = x.prod(acc_dtype=acc_dtype, axis=axis)
assert prod_var.owner.op.acc_dtype == acc_dtype
if (acc_dtype.startswith('complex') and
input_dtype != acc_dtype):
continue
f = theano.function([x], prod_var)
data = numpy.random.rand(3, 4) * 10
data = data.astype(input_dtype)
f(data)
if "complex" in acc_dtype:
continue
# Check that we can take the gradient
......@@ -888,7 +943,7 @@ class T_prod_without_zeros_dtype(unittest.TestCase):
Test the default dtype of a ProdWithoutZeros().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
for idx, dtype in enumerate(imap(str, theano.scalar.all_types)):
axis = axes[idx % len(axes)]
x = ProdWithoutZeros(axis=axis)(tensor.matrix(dtype=dtype))
......@@ -906,11 +961,12 @@ class T_prod_without_zeros_dtype(unittest.TestCase):
Test the default dtype of a ProdWithoutZeros().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
for idx, dtype in enumerate(imap(str, theano.scalar.all_types)):
axis = axes[idx % len(axes)]
x = ProdWithoutZeros(axis=axis)(tensor.matrix(dtype=dtype))
assert x.owner.op.acc_dtype == dict(
x = tensor.matrix(dtype=dtype)
p = ProdWithoutZeros(axis=axis)(x)
assert p.owner.op.acc_dtype == dict(
int8='int64',
int16='int64',
int32='int64',
......@@ -921,12 +977,19 @@ class T_prod_without_zeros_dtype(unittest.TestCase):
complex64='complex128'
).get(dtype, dtype)
if 'complex' in dtype:
continue
f = theano.function([x], p)
data = numpy.random.rand(2, 3) * 3
data = data.astype(dtype)
f(data)
def test_prod_without_zeros_custom_dtype(self):
"""
Test ability to provide your own output dtype for a ProdWithoutZeros().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
idx = 0
for input_dtype in imap(str, theano.scalar.all_types):
x = tensor.matrix(dtype=input_dtype)
......@@ -936,13 +999,20 @@ class T_prod_without_zeros_dtype(unittest.TestCase):
axis=axis, dtype=output_dtype)(x)
assert prod_woz_var.dtype == output_dtype
idx += 1
if ('complex' in output_dtype or
'complex' in input_dtype):
continue
f = theano.function([x], prod_woz_var)
data = numpy.random.rand(2, 3) * 3
data = data.astype(input_dtype)
f(data)
def test_prod_without_zeros_custom_acc_dtype(self):
"""
Test ability to provide your own acc_dtype for a ProdWithoutZeros().
"""
# We try multiple axis combinations even though axis should not matter.
axes = [None, 0, 1, [0], [1], [0, 1]]
axes = [None, 0, 1, [], [0], [1], [0, 1]]
idx = 0
for input_dtype in imap(str, theano.scalar.all_types):
x = tensor.matrix(dtype=input_dtype)
......@@ -958,6 +1028,14 @@ class T_prod_without_zeros_dtype(unittest.TestCase):
prod_woz_var = ProdWithoutZeros(
axis=axis, acc_dtype=acc_dtype)(x)
assert prod_woz_var.owner.op.acc_dtype == acc_dtype
if (acc_dtype.startswith('complex') and
input_dtype != acc_dtype):
continue
f = theano.function([x], prod_woz_var)
data = numpy.random.rand(2, 3) * 3
data = data.astype(input_dtype)
f(data)
else:
self.assertRaises(TypeError,
ProdWithoutZeros(axis=axis, acc_dtype=acc_dtype),
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论