提交 0336b6d1 authored 作者: nouiz's avatar nouiz

Merge pull request #852 from bouchnic/dtype

Add unsigned integers to sparse.
...@@ -108,7 +108,8 @@ The set of all accepted ``dtype`` for the sparse matrices can be found in ...@@ -108,7 +108,8 @@ The set of all accepted ``dtype`` for the sparse matrices can be found in
``sparse.all_dtypes``. ``sparse.all_dtypes``.
>>> sparse.all_dtypes >>> sparse.all_dtypes
set(['int8', 'int16', 'int32', 'int64', 'float32', 'float64', 'complex64', 'complex128']) set(['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64',
'float32', 'float64', 'complex64', 'complex128'])
To and Fro To and Fro
---------- ----------
......
...@@ -535,7 +535,11 @@ class upgrade_to_float(object): ...@@ -535,7 +535,11 @@ class upgrade_to_float(object):
conv = {int8: float32, conv = {int8: float32,
int16: float32, int16: float32,
int32: float64, int32: float64,
int64: float64} int64: float64,
uint8: float32,
uint16: float32,
uint32: float64,
uint64: float64}
return Scalar(Scalar.upcast(*[conv.get(type, type) return Scalar(Scalar.upcast(*[conv.get(type, type)
for type in types])), for type in types])),
......
...@@ -406,6 +406,7 @@ class SparseType(gof.Type): ...@@ -406,6 +406,7 @@ class SparseType(gof.Type):
format_cls = {'csr': scipy.sparse.csr_matrix, format_cls = {'csr': scipy.sparse.csr_matrix,
'csc': scipy.sparse.csc_matrix} 'csc': scipy.sparse.csc_matrix}
dtype_set = set(['int8', 'int16', 'int32', 'int64', 'float32', dtype_set = set(['int8', 'int16', 'int32', 'int64', 'float32',
'uint8', 'uint16', 'uint32', 'uint64',
'float64', 'complex64', 'complex128']) 'float64', 'complex64', 'complex128'])
ndim = 2 ndim = 2
......
...@@ -104,6 +104,8 @@ def sparse_random_inputs(format, shape, n=1, out_dtype=None, p=0.5, gap=None): ...@@ -104,6 +104,8 @@ def sparse_random_inputs(format, shape, n=1, out_dtype=None, p=0.5, gap=None):
assert len(shape) == 2 assert len(shape) == 2
assert out_dtype in sparse.all_dtypes assert out_dtype in sparse.all_dtypes
assert gap is None or isinstance(gap, (tuple, list)) assert gap is None or isinstance(gap, (tuple, list))
if gap is not None and out_dtype.startswith('u'):
assert gap[0] >= 0
def _rand(): def _rand():
where = numpy.random.binomial(1, p, size=shape).astype('int8') where = numpy.random.binomial(1, p, size=shape).astype('int8')
...@@ -2268,17 +2270,30 @@ def elemwise_checker(op, expected_f, gap=None, test_dtypes=None, ...@@ -2268,17 +2270,30 @@ def elemwise_checker(op, expected_f, gap=None, test_dtypes=None,
super(Tester, self).setUp() super(Tester, self).setUp()
self.op = op self.op = op
self.expected_f = expected_f self.expected_f = expected_f
self.gap = gap
def test_op(self): def test_op(self):
for format in sparse.sparse_formats: for format in sparse.sparse_formats:
for dtype in test_dtypes: for dtype in test_dtypes:
if dtype == 'int8': if dtype == 'int8' or dtype == 'uint8':
continue continue
# When testing with unsigned integers,
# we must check if the gap contains
# negative numbers.
if dtype.startswith('uint'):
if self.gap and len(self.gap) == 2 and self.gap[0] < 0:
if self.gap[1] >= 1:
self.gap = (0, self.gap[1])
else:
raise TypeError('Gap not suitable for',
dtype, self.__name__)
variable, data = sparse_random_inputs( variable, data = sparse_random_inputs(
format, format,
shape=(4, 7), shape=(4, 7),
out_dtype=dtype, out_dtype=dtype,
gap=gap) gap=self.gap)
f = theano.function(variable, self.op(*variable)) f = theano.function(variable, self.op(*variable))
...@@ -2303,45 +2318,58 @@ def elemwise_checker(op, expected_f, gap=None, test_dtypes=None, ...@@ -2303,45 +2318,58 @@ def elemwise_checker(op, expected_f, gap=None, test_dtypes=None,
# function. # function.
# Second, the tolerance for the checkup in DebugMode # Second, the tolerance for the checkup in DebugMode
# is too high. # is too high.
if 'int8' in test_dtypes: for dtype in ['int8', 'uint8']:
if gap: if dtype in test_dtypes:
domain = gap if self.gap:
else: domain = self.gap
domain = (0, 5) # When testing with unsigned integers,
variable, data = sparse_random_inputs( # we must check if the gap contains
format, # negative numbers.
shape=(4, 7), if dtype == 'uint8':
out_dtype='int8', if len(domain) == 2 and domain[0] < 0:
gap=domain) if domain[1] >= 1:
domain = (0, domain[1])
else:
raise TypeError('Gap not suitable for',
dtype, self.__name__)
else:
domain = (0, 5)
f = theano.function(variable, self.op(*variable)) variable, data = sparse_random_inputs(
format,
old_value = (tensor.basic.float32_atol, shape=(4, 7),
tensor.basic.float32_rtol, out_dtype=dtype,
tensor.basic.float64_atol, gap=domain)
tensor.basic.float64_rtol)
tensor.basic.float32_atol = 1e-4 f = theano.function(variable, self.op(*variable))
tensor.basic.float32_rtol = 1e-3
tensor.basic.float64_atol = 1e-3 old_value = (tensor.basic.float32_atol,
tensor.basic.float64_rtol = 1e-4 tensor.basic.float32_rtol,
try: tensor.basic.float64_atol,
tested = f(*data) tensor.basic.float64_rtol)
finally: tensor.basic.float32_atol = 1e-4
(tensor.basic.float32_atol, tensor.basic.float32_rtol = 1e-3
tensor.basic.float32_rtol, tensor.basic.float64_atol = 1e-3
tensor.basic.float64_atol, tensor.basic.float64_rtol = 1e-4
tensor.basic.float64_rtol) = old_value try:
tested = f(*data)
data = [m.toarray().astype('float32') for m in data] finally:
expected = self.expected_f(*data) (tensor.basic.float32_atol,
tensor.basic.float32_rtol,
assert tested.format == format tensor.basic.float64_atol,
tested = tested.toarray() tensor.basic.float64_rtol) = old_value
try: data = [m.toarray().astype('float32') for m in data]
assert numpy.allclose(tested, expected, rtol=1e-2) expected = self.expected_f(*data)
except AssertionError:
raise AssertionError(self.__name__) assert tested.format == format
tested = tested.toarray()
try:
assert numpy.allclose(tested, expected, rtol=1e-2)
except AssertionError:
raise AssertionError(self.__name__)
if grad_test: if grad_test:
def test_grad(self): def test_grad(self):
...@@ -2385,7 +2413,9 @@ StructuredSigmoidTester = elemwise_checker( ...@@ -2385,7 +2413,9 @@ StructuredSigmoidTester = elemwise_checker(
sparse.structured_sigmoid, sparse.structured_sigmoid,
structure_function(lambda x: 1.0 / (1.0 + numpy.exp(-x))), structure_function(lambda x: 1.0 / (1.0 + numpy.exp(-x))),
test_dtypes=[m for m in sparse.all_dtypes test_dtypes=[m for m in sparse.all_dtypes
if not m in sparse.complex_dtypes]) if (not m in sparse.complex_dtypes and
not m.startswith('uint'))],
gap=(-5, 5))
StructuredExpTester = elemwise_checker( StructuredExpTester = elemwise_checker(
sparse.structured_exp, sparse.structured_exp,
...@@ -2460,7 +2490,8 @@ SgnTester = elemwise_checker( ...@@ -2460,7 +2490,8 @@ SgnTester = elemwise_checker(
numpy.sign, numpy.sign,
grad_test=False, grad_test=False,
test_dtypes=[m for m in sparse.all_dtypes test_dtypes=[m for m in sparse.all_dtypes
if not m in sparse.complex_dtypes]) if (not m in sparse.complex_dtypes and
not m.startswith('uint'))])
CeilTester = elemwise_checker( CeilTester = elemwise_checker(
sparse.ceil, sparse.ceil,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论