提交 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):
def make_node(self, 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,
[x],
[SparseType(dtype=x.type.dtype,
......@@ -760,7 +771,9 @@ class SparseFromDense(gof.op.Op):
out[0] = SparseType.format_cls[self.format](x)
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):
return [shapes[0]]
......
......@@ -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 AddSS, AddSD, MulSS, MulSD, Transpose, Neg
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 get_item_2d, get_item_scalar
......@@ -423,6 +424,30 @@ class T_conversion(unittest.TestCase):
self.assertTrue(str(val.dtype) == s.dtype)
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):
def setUp(self):
......
......@@ -4085,7 +4085,7 @@ class Rebroadcast(Op):
broadcast_pattern[k] = str(int(v))
return '%s{%s}' % (self.__class__.__name__, ','.join(broadcast_pattern))
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')
t = x.type.__class__(dtype = x.type.dtype,
broadcastable = [self.axis.get(i, b)
......
......@@ -34,7 +34,7 @@ from theano.tensor import (_shared, wvector, bvector, autocast_float_as,
get_constant_value, ivector, reshape, scalar_from_tensor, scal,
iscalars, arange, dscalars, fvector, imatrix, numeric_grad,
opt, ComplexError, TensorDot, lvector, true_div, max, min, Split, roll,
tile)
tile, patternbroadcast)
from theano.tests import unittest_tools as utt
......@@ -5284,6 +5284,15 @@ class test_broadcast(unittest.TestCase):
assert addbroadcast(unbroadcast(x,1),0).owner.inputs[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):
x = matrix()
y = addbroadcast(x, 0)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论