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

Merge pull request #1505 from lamblin/sparse_updates

Sparse updates
...@@ -251,7 +251,7 @@ def sp_zeros_like(x): ...@@ -251,7 +251,7 @@ def sp_zeros_like(x):
# TODO: don't restrict to CSM formats # TODO: don't restrict to CSM formats
_, _, indptr, shape = csm_properties(x) _, _, indptr, shape = csm_properties(x)
return CSM(format=x.format)(data=numpy.array([], dtype=x.type.dtype), return CSM(format=x.format)(data=numpy.array([], dtype=x.type.dtype),
indices=numpy.array([]), indices=numpy.array([], dtype='int32'),
indptr=tensor.zeros_like(indptr), indptr=tensor.zeros_like(indptr),
shape=shape) shape=shape)
...@@ -621,12 +621,22 @@ class CSM(gof.Op): ...@@ -621,12 +621,22 @@ class CSM(gof.Op):
def make_node(self, data, indices, indptr, shape): def make_node(self, data, indices, indptr, shape):
data = tensor.as_tensor_variable(data) data = tensor.as_tensor_variable(data)
if not isinstance(indices, tensor.TensorVariable): if not isinstance(indices, gof.Variable):
indices = theano._asarray(indices, dtype='int32') indices_ = numpy.asarray(indices)
if not isinstance(indptr, tensor.TensorVariable): indices_32 = theano._asarray(indices, dtype='int32')
indptr = theano._asarray(indptr, dtype='int32') assert (indices_ == indices_32).all()
if not isinstance(shape, tensor.TensorVariable): indices = indices_32
shape = theano._asarray(shape, dtype='int32') if not isinstance(indptr, gof.Variable):
indptr_ = numpy.asarray(indptr)
indptr_32 = theano._asarray(indptr, dtype='int32')
assert (indptr_ == indptr_32).all()
indptr = indptr_32
if not isinstance(shape, gof.Variable):
shape_ = numpy.asarray(shape)
shape_32 = theano._asarray(shape, dtype='int32')
assert (shape_ == shape_32).all()
shape = shape_32
indices = tensor.as_tensor_variable(indices) indices = tensor.as_tensor_variable(indices)
indptr = tensor.as_tensor_variable(indptr) indptr = tensor.as_tensor_variable(indptr)
shape = tensor.as_tensor_variable(shape) shape = tensor.as_tensor_variable(shape)
......
...@@ -876,7 +876,8 @@ def local_csm_grad_c(node): ...@@ -876,7 +876,8 @@ def local_csm_grad_c(node):
if node.op == csm_grad(None): if node.op == csm_grad(None):
return [csm_grad_c(*node.inputs)] return [csm_grad_c(*node.inputs)]
return False return False
register_specialize(local_csm_grad_c, 'cxx_only') #DISABLED AS IT IS BROKEN FOR UNSORTED INDICES!
#register_specialize(local_csm_grad_c, 'cxx_only')
class MulSDCSC(gof.Op): class MulSDCSC(gof.Op):
......
...@@ -857,30 +857,17 @@ class test_csm(unittest.TestCase): ...@@ -857,30 +857,17 @@ class test_csm(unittest.TestCase):
z = tensor.ivector() z = tensor.ivector()
s = tensor.ivector() s = tensor.ivector()
# Sparse advanced indexing produces unsorted sparse matrices # Sparse advanced indexing produces unsorted sparse matrices
a = sp_types[format]([[1, 2, 1], a = sparse_random_inputs(format, (4, 3), out_dtype=dtype,
[1, 2, 1], unsorted_indices=True)[1][0]
[1, 2, 1],
[1, 2, 1]],
dtype=dtype)[range(4)]
# Make sure it's unsorted # Make sure it's unsorted
assert not a.has_sorted_indices assert not a.has_sorted_indices
a = as_sparse_variable(a) def my_op(x):
y = tensor.constant(a.indices)
f = theano.function([x, y, z, s], tensor.grad(tensor.sum( z = tensor.constant(a.indptr)
dense_from_sparse(a * CSM(format)(x, y, z, s))), x)) s = tensor.constant(a.shape)
return tensor.sum(
spmat = sp_types[format](random_lil((4, 3), dtype, dense_from_sparse(CSM(format)(x, y, z, s) * a))
12))[range(4)] verify_grad_sparse(my_op, [a.data])
assert not spmat.has_sorted_indices
res = f(spmat.data, spmat.indices, spmat.indptr,
numpy.asarray(spmat.shape, 'int32'))
col1 = sp_types[format]((res, spmat.indices, spmat.indptr),
shape=numpy.asarray(spmat.shape,
'int32'))[:, 1].data
assert numpy.all(col1 == 2)
def test_csm(self): def test_csm(self):
sp_types = {'csc': sp.csc_matrix, sp_types = {'csc': sp.csc_matrix,
...@@ -1252,7 +1239,7 @@ class DotTests(utt.InferShapeTester): ...@@ -1252,7 +1239,7 @@ class DotTests(utt.InferShapeTester):
fI = I.flatten() fI = I.flatten()
data = tensor.ones_like(fI) data = tensor.ones_like(fI)
indptr = tensor.arange(data.shape[0] + 1) indptr = tensor.arange(data.shape[0] + 1, dtype='int32')
m1 = sparse.CSR(data, fI, indptr, (8, size)) m1 = sparse.CSR(data, fI, indptr, (8, size))
m2 = sparse.dot(m1, C) m2 = sparse.dot(m1, C)
......
...@@ -37,6 +37,7 @@ def test_local_csm_properties_csm(): ...@@ -37,6 +37,7 @@ def test_local_csm_properties_csm():
def test_local_csm_grad_c(): def test_local_csm_grad_c():
raise SkipTest("Opt disabled as it don't support unsorted indices")
if not theano.config.cxx: if not theano.config.cxx:
raise SkipTest("G++ not available, so we need to skip this test.") raise SkipTest("G++ not available, so we need to skip this test.")
data = tensor.vector() data = tensor.vector()
......
...@@ -15,7 +15,7 @@ def _is_sparse(x): ...@@ -15,7 +15,7 @@ def _is_sparse(x):
@return: True iff x is a L{scipy.sparse.spmatrix} (and not a @return: True iff x is a L{scipy.sparse.spmatrix} (and not a
L{numpy.ndarray}) L{numpy.ndarray})
""" """
if not isinstance(x, (scipy.sparse.spmatrix, numpy.ndarray)): if not isinstance(x, (scipy.sparse.spmatrix, numpy.ndarray, tuple, list)):
raise NotImplementedError("this function should only be called on " raise NotImplementedError("this function should only be called on "
"sparse.scipy.sparse.spmatrix or " "sparse.scipy.sparse.spmatrix or "
"numpy.ndarray, not,", x) "numpy.ndarray, not,", x)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论