提交 85c30d7b authored 作者: Nicolas Bouchard's avatar Nicolas Bouchard 提交者: Frederic

Made corrections.

上级 bc1d0d86
...@@ -1286,6 +1286,103 @@ class Neg(gof.op.Op): ...@@ -1286,6 +1286,103 @@ class Neg(gof.op.Op):
neg = Neg() neg = Neg()
class SpSum(gof.op.Op):
"""
TODO: rewrite
Scale each columns of a sparse matrix by the
corresponding element of a dense vector
"""
axis = None
sparse_grad = False
def __init__(self, axis, sparse_grad=True):
"""
:param sparse_grad: if True, this instance ignores the
gradient on matrix elements which are implicitly 0.
"""
super(SpSum, self).__init__()
self.axis = axis
self.sparse_grad = sparse_grad
if self.axis not in (None, 0, 1):
raise ValueError('illegal value for self.axis')
def __eq__(self, other):
#WARNING: judgement call...
#not using the sparse_grad in the comparison or hashing
#because it doesn't change the perform method therefore, we
#*do* want Sums with different sparse_grad values to be merged
#by the merge optimization.
# This requires them to compare equal.
return type(self) == type(other) and self.axis == other.axis
def __hash__(self):
return 76324 ^ hash(type(self)) ^ hash(self.axis)
def __str__(self):
return self.__class__.__name__ + "{axis=%s}" % str(self.axis)
def make_node(self, x):
###
# At least for small matrices (5x5), the .sum() method of a
# csc matrix returns a dense matrix as the result whether axis
# is 0 or 1... weird!
###
assert isinstance(x.type, theano.sparse.SparseType)
b = ()
if self.axis is not None:
b = (False,)
z = tensor.tensor(broadcastable=b, dtype=x.dtype)
return gof.Apply(self, [x], [z])
def infer_shape(self, node, shapes):
r = None
if self.axis is None:
r = [()]
elif self.axis == 0:
r = [(shapes[0][1],)]
else:
r = [(shapes[0][0],)]
return r
def perform(self, node, (x,), (z,)):
if self.axis is None:
z[0] = numpy.asarray(x.sum())
else:
if self.axis == 0:
if x.format == 'csc':
z[0] = numpy.asarray(x.sum(axis=self.axis)).reshape(
(x.shape[1],))
else:
z[0] = numpy.asarray(x.asformat(x.format).sum(
axis=self.axis)).reshape((x.shape[1],))
elif self.axis == 1:
if x.format == 'csr':
z[0] = numpy.asarray(x.sum(axis=self.axis)).reshape(
(x.shape[0],))
else:
z[0] = numpy.asarray(x.asformat(x.format).sum(
axis=self.axis)).reshape((x.shape[0],))
def grad(self, (x,), (gz,)):
if self.axis is None:
r = gz * theano.sparse.sp_ones_like(x)
elif self.axis == 0:
r = col_scale(theano.sparse.sp_ones_like(x), gz)
elif self.axis == 1:
r = row_scale(theano.sparse.sp_ones_like(x), gz)
else:
assert False
if not self.sparse_grad:
r = theano.sparse.dense_from_sparse(r)
return [r]
def sp_sum(x, axis=None, sparse_grad=False):
return SpSum(axis, sparse_grad)(x)
class AddSS(gof.op.Op): class AddSS(gof.op.Op):
'''Add two sparse matrices ''' '''Add two sparse matrices '''
def __eq__(self, other): def __eq__(self, other):
...@@ -1460,7 +1557,7 @@ class StructuredAddSV(gof.op.Op): ...@@ -1460,7 +1557,7 @@ class StructuredAddSV(gof.op.Op):
def grad(self, (x, y), (gz,)): def grad(self, (x, y), (gz,)):
assert _is_sparse_variable(x) and not _is_sparse_variable(y) assert _is_sparse_variable(x) and not _is_sparse_variable(y)
assert _is_sparse_variable(gz) assert _is_sparse_variable(gz)
return gz, theano.sparse.sandbox.sp.sp_sum(gz, axis=0, sparse_grad=True) return gz, sp_sum(gz, axis=0, sparse_grad=True)
def infer_shape(self, node, ins_shapes): def infer_shape(self, node, ins_shapes):
return [ins_shapes[0]] return [ins_shapes[0]]
...@@ -2006,7 +2103,7 @@ class MulSV(gof.op.Op): ...@@ -2006,7 +2103,7 @@ class MulSV(gof.op.Op):
def grad(self, (x, y), (gz,)): def grad(self, (x, y), (gz,)):
assert _is_sparse_variable(x) and _is_dense_variable(y) assert _is_sparse_variable(x) and _is_dense_variable(y)
assert _is_sparse_variable(gz) assert _is_sparse_variable(gz)
return mul_s_v(gz, y), theano.sparse.sandbox.sp.sp_sum(x * gz, axis=0, sparse_grad=True) return mul_s_v(gz, y), sp_sum(x * gz, axis=0, sparse_grad=True)
def infer_shape(self, node, ins_shapes): def infer_shape(self, node, ins_shapes):
return [ins_shapes[0]] return [ins_shapes[0]]
......
...@@ -17,109 +17,16 @@ from theano import sparse, gof, Op, tensor ...@@ -17,109 +17,16 @@ from theano import sparse, gof, Op, tensor
from theano.gof.python25 import all, any from theano.gof.python25 import all, any
from theano.sparse.basic import Remove0, remove0 from theano.sparse.basic import Remove0, remove0
# To maintain compatibility
from theano.sparse import SpSum, sp_sum
def register_specialize(lopt, *tags, **kwargs): def register_specialize(lopt, *tags, **kwargs):
theano.compile.optdb['specialize'].register( theano.compile.optdb['specialize'].register(
(kwargs and kwargs.pop('name')) or lopt.__name__, lopt, 'fast_run', (kwargs and kwargs.pop('name')) or lopt.__name__, lopt, 'fast_run',
*tags) *tags)
class SpSum(Op):
"""
TODO: rewrite
Scale each columns of a sparse matrix by the
corresponding element of a dense vector
"""
axis = None
sparse_grad = False
def __init__(self, axis, sparse_grad=True):
"""
:param sparse_grad: if True, this instance ignores the
gradient on matrix elements which are implicitly 0.
"""
super(SpSum, self).__init__()
self.axis = axis
self.sparse_grad = sparse_grad
if self.axis not in (None, 0, 1):
raise ValueError('illegal value for self.axis')
def __eq__(self, other):
#WARNING: judgement call...
#not using the sparse_grad in the comparison or hashing
#because it doesn't change the perform method therefore, we
#*do* want Sums with different sparse_grad values to be merged
#by the merge optimization.
# This requires them to compare equal.
return type(self) == type(other) and self.axis == other.axis
def __hash__(self):
return 76324 ^ hash(type(self)) ^ hash(self.axis)
def __str__(self):
return self.__class__.__name__ + "{axis=%s}" % str(self.axis)
def make_node(self, x):
###
# At least for small matrices (5x5), the .sum() method of a
# csc matrix returns a dense matrix as the result whether axis
# is 0 or 1... weird!
###
assert isinstance(x.type, theano.sparse.SparseType)
b = ()
if self.axis is not None:
b = (False,)
z = tensor.tensor(broadcastable=b, dtype=x.dtype)
return gof.Apply(self, [x], [z])
def infer_shape(self, node, shapes):
r = None
if self.axis is None:
r = [()]
elif self.axis == 0:
r = [(shapes[0][1],)]
else:
r = [(shapes[0][0],)]
return r
def perform(self, node, (x,), (z,)):
if self.axis is None:
z[0] = numpy.asarray(x.sum())
else:
if self.axis == 0:
if x.format == 'csc':
z[0] = numpy.asarray(x.sum(axis=self.axis)).reshape(
(x.shape[1],))
else:
z[0] = numpy.asarray(x.asformat(x.format).sum(
axis=self.axis)).reshape((x.shape[1],))
elif self.axis == 1:
if x.format == 'csr':
z[0] = numpy.asarray(x.sum(axis=self.axis)).reshape(
(x.shape[0],))
else:
z[0] = numpy.asarray(x.asformat(x.format).sum(
axis=self.axis)).reshape((x.shape[0],))
def grad(self, (x,), (gz,)):
if self.axis is None:
r = gz * theano.sparse.sp_ones_like(x)
elif self.axis == 0:
r = col_scale(theano.sparse.sp_ones_like(x), gz)
elif self.axis == 1:
r = row_scale(theano.sparse.sp_ones_like(x), gz)
else:
assert False
if not self.sparse_grad:
r = theano.sparse.dense_from_sparse(r)
return [r]
def sp_sum(x, axis=None, sparse_grad=False):
return SpSum(axis, sparse_grad)(x)
class Diag(Op): class Diag(Op):
""" """
Extract the diagonal of a square sparse matrix as a dense vector. Extract the diagonal of a square sparse matrix as a dense vector.
......
...@@ -363,7 +363,7 @@ class TestSP(unittest.TestCase): ...@@ -363,7 +363,7 @@ class TestSP(unittest.TestCase):
utt.verify_grad(d, [kvals]) utt.verify_grad(d, [kvals])
def test_sp_sum(self): def test_sp_sum(self):
from theano.sparse.sandbox.sp import SpSum from theano.sparse import SpSum
# TODO: test both grad. # TODO: test both grad.
rng = numpy.random.RandomState(42) rng = numpy.random.RandomState(42)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论