提交 0a56bdff authored 作者: nouiz's avatar nouiz

Merge pull request #448 from lamblin/csx_from_dense_ndim

Broadcast input of sparse_from_dense so ndim=2
...@@ -750,6 +750,17 @@ class SparseFromDense(gof.op.Op): ...@@ -750,6 +750,17 @@ class SparseFromDense(gof.op.Op):
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:
raise TypeError(
"Theano does not have sparse tensor types with more "
"than 2 dimensions, but %s.ndim = %i" % (x, x.ndim))
elif x.ndim == 1:
x = x.dimshuffle('x', 0)
elif x.ndim == 0:
x = x.dimshuffle('x', 'x')
else:
assert x.ndim == 2
return gof.Apply(self, return gof.Apply(self,
[x], [x],
[SparseType(dtype=x.type.dtype, [SparseType(dtype=x.type.dtype,
...@@ -760,7 +771,9 @@ class SparseFromDense(gof.op.Op): ...@@ -760,7 +771,9 @@ class SparseFromDense(gof.op.Op):
out[0] = SparseType.format_cls[self.format](x) out[0] = SparseType.format_cls[self.format](x)
def grad(self, (x, ), (gz, )): def grad(self, (x, ), (gz, )):
return dense_from_sparse(gz), gx = dense_from_sparse(gz)
gx = tensor.patternbroadcast(gx, x.broadcastable)
return gx,
def infer_shape(self, node, shapes): def infer_shape(self, node, shapes):
return [shapes[0]] return [shapes[0]]
......
...@@ -23,7 +23,8 @@ from theano.sparse import as_sparse_variable, CSC, CSR, CSM, CSMProperties ...@@ -23,7 +23,8 @@ from theano.sparse import as_sparse_variable, CSC, CSR, CSM, CSMProperties
from theano.sparse import SparseType, StructuredDotCSC, CSMGrad from theano.sparse import SparseType, StructuredDotCSC, CSMGrad
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)
from theano.sparse import Dot, Usmm, UsmmCscDense from theano.sparse import Dot, Usmm, UsmmCscDense
#from theano.sparse import get_item_2d, get_item_scalar #from theano.sparse import get_item_2d, get_item_scalar
...@@ -423,6 +424,30 @@ class T_conversion(unittest.TestCase): ...@@ -423,6 +424,30 @@ class T_conversion(unittest.TestCase):
self.assertTrue(str(val.dtype) == s.dtype) self.assertTrue(str(val.dtype) == s.dtype)
self.assertTrue(numpy.all(val[0] == [1, 0, 0, 0, 0])) self.assertTrue(numpy.all(val[0] == [1, 0, 0, 0, 0]))
@staticmethod
def check_format_ndim(format, ndim):
x = tensor.tensor(
dtype=config.floatX,
broadcastable=([False] * ndim),
name='x')
s = SparseFromDense(format)(x)
s_m = - s
d = dense_from_sparse(s_m)
c = d.sum()
g = tensor.grad(c, x)
f = theano.function([x], [s, g])
f(numpy.array(0, ndmin=ndim))
f(numpy.array(7, ndmin=ndim))
def test_format_ndim(self):
for format in 'csc', 'csr':
for ndim in 0, 1, 2:
self.check_format_ndim(format, ndim)
self.assertRaises(TypeError, self.check_format_ndim, format, 3)
self.assertRaises(TypeError, self.check_format_ndim, format, 4)
class test_structureddot(unittest.TestCase): class test_structureddot(unittest.TestCase):
def setUp(self): def setUp(self):
......
...@@ -4085,7 +4085,7 @@ class Rebroadcast(Op): ...@@ -4085,7 +4085,7 @@ class Rebroadcast(Op):
broadcast_pattern[k] = str(int(v)) broadcast_pattern[k] = str(int(v))
return '%s{%s}' % (self.__class__.__name__, ','.join(broadcast_pattern)) return '%s{%s}' % (self.__class__.__name__, ','.join(broadcast_pattern))
def make_node(self, x): def make_node(self, x):
if x.ndim <= numpy.max(self.axis.keys()): if self.axis.keys() and (x.ndim <= numpy.max(self.axis.keys())):
raise ValueError('Trying to rebroadcast nonexistant dimension') raise ValueError('Trying to rebroadcast nonexistant dimension')
t = x.type.__class__(dtype = x.type.dtype, t = x.type.__class__(dtype = x.type.dtype,
broadcastable = [self.axis.get(i, b) broadcastable = [self.axis.get(i, b)
......
...@@ -34,7 +34,7 @@ from theano.tensor import (_shared, wvector, bvector, autocast_float_as, ...@@ -34,7 +34,7 @@ from theano.tensor import (_shared, wvector, bvector, autocast_float_as,
get_constant_value, ivector, reshape, scalar_from_tensor, scal, get_constant_value, ivector, reshape, scalar_from_tensor, scal,
iscalars, arange, dscalars, fvector, imatrix, numeric_grad, iscalars, arange, dscalars, fvector, imatrix, numeric_grad,
opt, ComplexError, TensorDot, lvector, true_div, max, min, Split, roll, opt, ComplexError, TensorDot, lvector, true_div, max, min, Split, roll,
tile) tile, patternbroadcast)
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
...@@ -5284,6 +5284,15 @@ class test_broadcast(unittest.TestCase): ...@@ -5284,6 +5284,15 @@ class test_broadcast(unittest.TestCase):
assert addbroadcast(unbroadcast(x,1),0).owner.inputs[0] is x assert addbroadcast(unbroadcast(x,1),0).owner.inputs[0] is x
assert addbroadcast(unbroadcast(x,0),0) is x assert addbroadcast(unbroadcast(x,0),0) is x
def test_patternbroadcast(self):
# Test that patternbroadcast with an empty broadcasting pattern works
x = scalar('x')
m = tensor.matrix('m')
s = patternbroadcast(m, x.broadcastable)
assert s is m
x2 = patternbroadcast(x, x.broadcastable)
assert x2 is x
def test_infer_shape(self): def test_infer_shape(self):
x = matrix() x = matrix()
y = addbroadcast(x, 0) y = addbroadcast(x, 0)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论