提交 8dec19eb authored 作者: lamblin's avatar lamblin

Merge pull request #473 from nouiz/sparse

Sparse
...@@ -525,12 +525,14 @@ class CSMProperties(gof.Op): ...@@ -525,12 +525,14 @@ class CSMProperties(gof.Op):
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) and _kmap_eq(self.kmap, other.kmap) return type(self) == type(other) and _kmap_eq(self.kmap, other.kmap)
def __ne__(self, other):
return not (self == other)
def __hash__(self): def __hash__(self):
return 8234 ^ hash(type(self)) ^ _kmap_hash(self.kmap) return 8234 ^ hash(type(self)) ^ _kmap_hash(self.kmap)
def __str__(self):
return "%s{%s}" % (
self.__class__.__name__,
self.kmap)
def make_node(self, csm): def make_node(self, csm):
csm = as_sparse_variable(csm) csm = as_sparse_variable(csm)
data = tensor.TensorType(dtype=csm.type.dtype, data = tensor.TensorType(dtype=csm.type.dtype,
...@@ -700,12 +702,14 @@ class CSMGrad(gof.op.Op): ...@@ -700,12 +702,14 @@ class CSMGrad(gof.op.Op):
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) and _kmap_eq(self.kmap, other.kmap) return type(self) == type(other) and _kmap_eq(self.kmap, other.kmap)
def __ne__(self, other):
return not (self == other)
def __hash__(self): def __hash__(self):
return 82345 ^ hash(type(self)) ^ _kmap_hash(self.kmap) return 82345 ^ hash(type(self)) ^ _kmap_hash(self.kmap)
def __str__(self):
return "%s{%s}" % (
self.__class__.__name__,
self.kmap)
def make_node(self, data, gout_data, gout_indices): def make_node(self, data, gout_data, gout_indices):
g_data = gout_data.type() g_data = gout_data.type()
return gof.Apply(self, [data, gout_data, gout_indices], [g_data]) return gof.Apply(self, [data, gout_data, gout_indices], [g_data])
...@@ -761,6 +765,11 @@ class DenseFromSparse(gof.op.Op): ...@@ -761,6 +765,11 @@ class DenseFromSparse(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self))^hash(self.sparse_grad) return hash(type(self))^hash(self.sparse_grad)
def __str__(self):
return "%s{structured_grad=%s}" % (
self.__class__.__name__,
self.sparse_grad)
def make_node(self, x): def make_node(self, x):
x = as_sparse_variable(x) x = as_sparse_variable(x)
return gof.Apply(self, return gof.Apply(self,
...@@ -801,12 +810,14 @@ class SparseFromDense(gof.op.Op): ...@@ -801,12 +810,14 @@ class SparseFromDense(gof.op.Op):
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) and self.format == other.format return type(self) == type(other) and self.format == other.format
def __ne__(self, other):
return not (self == other)
def __hash__(self): def __hash__(self):
return 982374 ^ hash(self.format) ^ hash(DenseFromSparse) return 982374 ^ hash(self.format) ^ hash(DenseFromSparse)
def __str__(self):
return "%s{%s}" % (
self.__class__.__name__,
self.format)
def make_node(self, x): def make_node(self, x):
x = tensor.as_tensor_variable(x) x = tensor.as_tensor_variable(x)
if x.ndim > 2: if x.ndim > 2:
...@@ -1005,6 +1016,9 @@ class Transpose(gof.op.Op): ...@@ -1005,6 +1016,9 @@ class Transpose(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return "Sparse" + self.__class__.__name__
def make_node(self, x): def make_node(self, x):
x = as_sparse_variable(x) x = as_sparse_variable(x)
return gof.Apply(self, return gof.Apply(self,
...@@ -1034,6 +1048,9 @@ class Neg(gof.op.Op): ...@@ -1034,6 +1048,9 @@ class Neg(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return "Sparse" + self.__class__.__name__
def make_node(self, x): def make_node(self, x):
x = as_sparse_variable(x) x = as_sparse_variable(x)
return gof.Apply(self, [x], [x.type()]) return gof.Apply(self, [x], [x.type()])
...@@ -1060,6 +1077,9 @@ class AddSS(gof.op.Op): ...@@ -1060,6 +1077,9 @@ class AddSS(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, x, y): def make_node(self, x, y):
x, y = map(as_sparse_variable, [x, y]) x, y = map(as_sparse_variable, [x, y])
if x.type.dtype != y.type.dtype: if x.type.dtype != y.type.dtype:
...@@ -1096,6 +1116,9 @@ class AddSD(gof.op.Op): ...@@ -1096,6 +1116,9 @@ class AddSD(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, x, y): def make_node(self, x, y):
x, y = as_sparse_variable(x), tensor.as_tensor_variable(y) x, y = as_sparse_variable(x), tensor.as_tensor_variable(y)
if x.type.dtype != y.type.dtype: if x.type.dtype != y.type.dtype:
...@@ -1161,6 +1184,9 @@ class MulSS(gof.op.Op): ...@@ -1161,6 +1184,9 @@ class MulSS(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, x, y): def make_node(self, x, y):
x, y = as_sparse_variable(x), as_sparse_variable(y) x, y = as_sparse_variable(x), as_sparse_variable(y)
if x.type != y.type: if x.type != y.type:
...@@ -1195,6 +1221,9 @@ class MulSD(gof.op.Op): ...@@ -1195,6 +1221,9 @@ class MulSD(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, x, y): def make_node(self, x, y):
x, y = as_sparse_variable(x), tensor.as_tensor_variable(y) x, y = as_sparse_variable(x), tensor.as_tensor_variable(y)
...@@ -1304,6 +1333,9 @@ class StructuredDot(gof.Op): ...@@ -1304,6 +1333,9 @@ class StructuredDot(gof.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, a, b): def make_node(self, a, b):
if not _is_sparse_variable(a): if not _is_sparse_variable(a):
raise TypeError('First argument must be of type SparseVariable ' raise TypeError('First argument must be of type SparseVariable '
...@@ -1405,6 +1437,9 @@ class StructuredDotCSC(gof.Op): ...@@ -1405,6 +1437,9 @@ class StructuredDotCSC(gof.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, a_val, a_ind, a_ptr, a_nrows, b): def make_node(self, a_val, a_ind, a_ptr, a_nrows, b):
dtype_out = scalar.upcast(a_val.type.dtype, b.type.dtype) dtype_out = scalar.upcast(a_val.type.dtype, b.type.dtype)
r = gof.Apply(self, [a_val, a_ind, a_ptr, a_nrows, b], r = gof.Apply(self, [a_val, a_ind, a_ptr, a_nrows, b],
...@@ -1577,6 +1612,9 @@ class StructuredDotCSR(gof.Op): ...@@ -1577,6 +1612,9 @@ class StructuredDotCSR(gof.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, a_val, a_ind, a_ptr, b): def make_node(self, a_val, a_ind, a_ptr, b):
self.dtype_out = scalar.upcast(a_val.type.dtype, b.type.dtype) self.dtype_out = scalar.upcast(a_val.type.dtype, b.type.dtype)
r = gof.Apply(self, [a_val, a_ind, a_ptr, b], r = gof.Apply(self, [a_val, a_ind, a_ptr, b],
...@@ -1759,6 +1797,9 @@ class StructuredDotGradCSC(gof.Op): ...@@ -1759,6 +1797,9 @@ class StructuredDotGradCSC(gof.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, a_indices, a_indptr, b, g_ab): def make_node(self, a_indices, a_indptr, b, g_ab):
return gof.Apply(self, [a_indices, a_indptr, b, g_ab], return gof.Apply(self, [a_indices, a_indptr, b, g_ab],
[tensor.tensor(g_ab.dtype, (False,))]) [tensor.tensor(g_ab.dtype, (False,))])
...@@ -1878,6 +1919,9 @@ class StructuredDotGradCSR(gof.Op): ...@@ -1878,6 +1919,9 @@ class StructuredDotGradCSR(gof.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __str__(self):
return self.__class__.__name__
def make_node(self, a_indices, a_indptr, b, g_ab): def make_node(self, a_indices, a_indptr, b, g_ab):
return gof.Apply(self, [a_indices, a_indptr, b, g_ab], return gof.Apply(self, [a_indices, a_indptr, b, g_ab],
[tensor.tensor(b.dtype, (False,))]) [tensor.tensor(b.dtype, (False,))])
...@@ -2005,8 +2049,8 @@ class Dot(gof.op.Op): ...@@ -2005,8 +2049,8 @@ class Dot(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __ne__(self, other): def __str__(self):
return not (self == other) return "Sparse" + self.__class__.__name__
def infer_shape(self, node, shapes): def infer_shape(self, node, shapes):
xshp, yshp = shapes xshp, yshp = shapes
...@@ -2100,9 +2144,6 @@ class Usmm(gof.op.Op): ...@@ -2100,9 +2144,6 @@ class Usmm(gof.op.Op):
def __hash__(self): def __hash__(self):
return hash(type(self)) return hash(type(self))
def __ne__(self, other):
return not (self == other)
def __str__(self): def __str__(self):
return 'Usmm{no_inplace}' return 'Usmm{no_inplace}'
......
...@@ -21,12 +21,14 @@ from theano.sparse.basic import _is_dense, _is_sparse, _mtypes ...@@ -21,12 +21,14 @@ from theano.sparse.basic import _is_dense, _is_sparse, _mtypes
from theano.sparse.basic import _is_dense_variable, _is_sparse_variable from theano.sparse.basic import _is_dense_variable, _is_sparse_variable
from theano.sparse.basic import verify_grad_sparse from theano.sparse.basic import verify_grad_sparse
from theano.sparse import as_sparse_variable, CSC, CSR, CSM, CSMProperties from theano.sparse import as_sparse_variable, CSC, CSR, CSM, CSMProperties
from theano.sparse import SparseType, StructuredDotCSC, CSMGrad from theano.sparse import SparseType, CSMGrad
from theano.sparse import StructuredDot, StructuredDotCSC
from theano.sparse import StructuredDotGradCSC, StructuredDotGradCSR
from theano.sparse import AddSS, AddSD, MulSS, MulSD, Transpose, Neg from theano.sparse import AddSS, AddSD, MulSS, MulSD, Transpose, Neg
from theano.sparse import add, mul, structured_dot, transpose from theano.sparse import add, mul, structured_dot, transpose
from theano.sparse import (csc_from_dense, csr_from_dense, dense_from_sparse, from theano.sparse import (csc_from_dense, csr_from_dense, dense_from_sparse,
SparseFromDense) SparseFromDense)
from theano.sparse import Dot, Usmm, UsmmCscDense, sp_ones_like from theano.sparse import Dot, Usmm, UsmmCscDense, sp_ones_like, GetItemScalar
#from theano.sparse import get_item_2d, get_item_scalar #from theano.sparse import get_item_2d, get_item_scalar
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
...@@ -62,6 +64,7 @@ def random_lil(shape, dtype, nnz): ...@@ -62,6 +64,7 @@ def random_lil(shape, dtype, nnz):
value) value)
return rval return rval
class T_verify_grad_sparse(unittest.TestCase): class T_verify_grad_sparse(unittest.TestCase):
class FailOp(gof.op.Op): class FailOp(gof.op.Op):
def __init__(self, structured): def __init__(self, structured):
...@@ -85,7 +88,7 @@ class T_verify_grad_sparse(unittest.TestCase): ...@@ -85,7 +88,7 @@ class T_verify_grad_sparse(unittest.TestCase):
def grad(self, (x,), (gz,)): def grad(self, (x,), (gz,)):
assert _is_sparse_variable(x) and _is_sparse_variable(gz) assert _is_sparse_variable(x) and _is_sparse_variable(gz)
if self.structured: if self.structured:
return sp_ones_like(x)*dense_from_sparse(gz), return sp_ones_like(x) * dense_from_sparse(gz),
else: else:
return gz, return gz,
...@@ -163,6 +166,14 @@ class SparseInferShapeTester(unittest.TestCase): ...@@ -163,6 +166,14 @@ class SparseInferShapeTester(unittest.TestCase):
def test_getitem_2d(self): def test_getitem_2d(self):
raise SkipTest('infer_shape not implemented for GetItem2d yet') raise SkipTest('infer_shape not implemented for GetItem2d yet')
def test_getitem_scalar(self):
x = SparseType('csr', dtype=config.floatX)()
self._compile_and_check([x],
[x[2, 2]],
[sp.csr_matrix(random_lil((10, 40),
config.floatX, 3))],
GetItemScalar)
def test_csm_grad(self): def test_csm_grad(self):
for sparsetype in ('csr', 'csc'): for sparsetype in ('csr', 'csc'):
x = tensor.vector() x = tensor.vector()
...@@ -240,6 +251,78 @@ class SparseInferShapeTester(unittest.TestCase): ...@@ -240,6 +251,78 @@ class SparseInferShapeTester(unittest.TestCase):
numpy.random.randn(10, 40).astype(config.floatX)], numpy.random.randn(10, 40).astype(config.floatX)],
MulSD) MulSD)
def test_dot(self):
x = SparseType('csc', dtype=config.floatX)()
y = SparseType('csc', dtype=config.floatX)()
self._compile_and_check(
[x, y],
[Dot()(x, y)],
[sp.csc_matrix(random_lil((4, 5),
config.floatX, 3)),
sp.csc_matrix(random_lil((5, 3),
config.floatX, 3))],
Dot)
def test_structured_dot(self):
x = SparseType('csc', dtype=config.floatX)()
y = SparseType('csc', dtype=config.floatX)()
self._compile_and_check(
[x, y],
[structured_dot(x, y)],
[sp.csc_matrix(random_lil((4, 5),
config.floatX, 3)),
sp.csc_matrix(random_lil((5, 3),
config.floatX, 3))],
StructuredDot)
def test_csm(self):
# We also need the grad of CSM to be implemetned.
raise SkipTest('infer_shape not implemented for CSM')
def test_structured_dot_grad(self):
# We also need the grad of CSM to be implemetned.
raise SkipTest('infer_shape not implemented for the grad'
' of structured_dot')
for format, op in [('csc', StructuredDotGradCSC),
('csr', StructuredDotGradCSR)]:
x = SparseType(format, dtype=config.floatX)()
y = SparseType(format, dtype=config.floatX)()
grads = tensor.grad(dense_from_sparse(structured_dot(x, y)).sum(),
[x, y])
self._compile_and_check(
[x, y],
[grads[0]],
[as_sparse_format(random_lil((4, 5),
config.floatX, 3), format),
as_sparse_format(random_lil((5, 3),
config.floatX, 3), format)],
op)
self._compile_and_check(
[x, y],
[grads[1]],
[as_sparse_format(random_lil((4, 5),
config.floatX, 3), format),
as_sparse_format(random_lil((5, 3),
config.floatX, 3), format)],
op)
def test_dense_from_sparse(self):
x = SparseType('csr', dtype=config.floatX)()
self._compile_and_check([x],
[dense_from_sparse(x)],
[sp.csr_matrix(random_lil((10, 40),
config.floatX, 3))],
dense_from_sparse.__class__)
def test_sparse_from_dense(self):
x = tensor.matrix()
self._compile_and_check([x],
[csc_from_dense(x)],
[numpy.random.randn(10, 40).astype(
config.floatX)],
csc_from_dense.__class__)
class T_AddMul(unittest.TestCase): class T_AddMul(unittest.TestCase):
def testAddSS(self): def testAddSS(self):
...@@ -508,11 +591,11 @@ class test_structureddot(unittest.TestCase): ...@@ -508,11 +591,11 @@ class test_structureddot(unittest.TestCase):
mat = numpy.asarray(numpy.random.randn(3, 2), 'float32') mat = numpy.asarray(numpy.random.randn(3, 2), 'float32')
verify_grad_sparse(structured_dot, [spmat, mat], structured=True) verify_grad_sparse(structured_dot, [spmat, mat], structured=True)
def buildgraph_T(spmat, mat): def buildgraph_T(spmat, mat):
return structured_dot(mat.T, spmat.T) return structured_dot(mat.T, spmat.T)
verify_grad_sparse(buildgraph_T, [spmat, mat], structured=True) verify_grad_sparse(buildgraph_T, [spmat, mat], structured=True)
def test_structureddot_csr_grad(self): def test_structureddot_csr_grad(self):
...@@ -530,22 +613,6 @@ class test_structureddot(unittest.TestCase): ...@@ -530,22 +613,6 @@ class test_structureddot(unittest.TestCase):
verify_grad_sparse(buildgraph_T, [spmat, mat], structured=True) verify_grad_sparse(buildgraph_T, [spmat, mat], structured=True)
def test_infer_shape_csr_csc_grad(self):
for sparsetype in ('csr', 'csc'):
a = SparseType(sparsetype, dtype=config.floatX)()
b = SparseType(sparsetype, dtype=config.floatX)()
grads = tensor.grad(dense_from_sparse(structured_dot(a, b)).sum(),
[a, b])
f = theano.function([a, b], [g.shape for g in grads])
topo = f.maker.env.toposort()
assert not any(isinstance(t, self.__class__) for t in topo)
call = getattr(sp, sparsetype + '_matrix')
x = call(random_lil((500, 300), config.floatX, 10))
y = call(random_lil((300, 400), config.floatX, 5))
out1, out2 = f(x, y)
assert numpy.all(out1 == x.shape)
assert numpy.all(out2 == y.shape)
def test_upcast(self): def test_upcast(self):
typenames = ('float32', 'int64', 'int8', 'int32', typenames = ('float32', 'int64', 'int8', 'int32',
...@@ -736,16 +803,6 @@ class test_structureddot(unittest.TestCase): ...@@ -736,16 +803,6 @@ class test_structureddot(unittest.TestCase):
self.assertFalse(theano_time > overhead_rtol * scipy_time + self.assertFalse(theano_time > overhead_rtol * scipy_time +
overhead_tol) overhead_tol)
def test_infer_shape(self):
a = SparseType('csc', dtype=config.floatX)()
b = SparseType('csc', dtype=config.floatX)()
f = theano.function([a, b], structured_dot(a, b).shape)
topo = f.maker.env.toposort()
assert not any(isinstance(t, self.__class__) for t in topo)
x = sp.csc_matrix((4, 5), dtype=config.floatX)
y = sp.csc_matrix((5, 3), dtype=config.floatX)
assert numpy.all(f(x, y) == numpy.array((4, 3)))
class DotTests(unittest.TestCase): class DotTests(unittest.TestCase):
def setUp(self): def setUp(self):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论