提交 156ef0a0 authored 作者: Nicolas Bouchard's avatar Nicolas Bouchard

Review col_scale and row_scale.

上级 a2f0692e
...@@ -1287,10 +1287,26 @@ neg = Neg() ...@@ -1287,10 +1287,26 @@ neg = Neg()
class ColScaleCSC(gof.op.Op): class ColScaleCSC(gof.op.Op):
"""Scale each columns of a sparse matrix by the corresponding
element of a dense vector
:param x: A sparse matrix.
:param s: A dense vector with length equal to the number
of columns of `x`.
:return: A sparse matrix in the same format as `x` which
each column had been multiply by the corresponding
element of `s`.
:note:
- The grad implemented is structured.
""" """
Scale each columns of a sparse matrix by the corresponding element
of a dense vector def __eq__(self, other):
""" return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def make_node(self, x, s): def make_node(self, x, s):
if x.format != 'csc': if x.format != 'csc':
...@@ -1300,7 +1316,7 @@ class ColScaleCSC(gof.op.Op): ...@@ -1300,7 +1316,7 @@ class ColScaleCSC(gof.op.Op):
def perform(self, node, (x, s), (z,)): def perform(self, node, (x, s), (z,)):
M, N = x.shape M, N = x.shape
assert x.format == 'csc' assert x.format == 'csc'
assert s.shape == (N,) assert s.shape == (N, )
y = x.copy() y = x.copy()
...@@ -1312,20 +1328,42 @@ class ColScaleCSC(gof.op.Op): ...@@ -1312,20 +1328,42 @@ class ColScaleCSC(gof.op.Op):
def grad(self, (x, s), (gz,)): def grad(self, (x, s), (gz,)):
return [col_scale(gz, s), sp_sum(x * gz, axis=0)] return [col_scale(gz, s), sp_sum(x * gz, axis=0)]
def infer_shape(self, node, ins_shapes):
return [ins_shapes[0]]
def __str__(self):
return self.__class__.__name__
class RowScaleCSC(gof.op.Op): class RowScaleCSC(gof.op.Op):
""" """Scale each row of a sparse matrix by the corresponding element of
Scale each row of a sparse matrix by the corresponding element of
a dense vector a dense vector
:param x: A sparse matrix.
:param s: A dense vector with length equal to the number
of rows of `x`.
:return: A sparse matrix in the same format as `x` which
each row had been multiply by the corresponding
element of `s`.
:note:
- The grad implemented is structured.
""" """
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
def make_node(self, x, s): def make_node(self, x, s):
return gof.Apply(self, [x, s], [x.type()]) return gof.Apply(self, [x, s], [x.type()])
def perform(self, node, (x, s), (z,)): def perform(self, node, (x, s), (z,)):
M, N = x.shape M, N = x.shape
assert x.format == 'csc' assert x.format == 'csc'
assert s.shape == (M,) assert s.shape == (M, )
indices = x.indices indices = x.indices
indptr = x.indptr indptr = x.indptr
...@@ -1341,6 +1379,12 @@ class RowScaleCSC(gof.op.Op): ...@@ -1341,6 +1379,12 @@ class RowScaleCSC(gof.op.Op):
def grad(self, (x, s), (gz,)): def grad(self, (x, s), (gz,)):
return [row_scale(gz, s), sp_sum(x * gz, axis=1)] return [row_scale(gz, s), sp_sum(x * gz, axis=1)]
def infer_shape(self, node, ins_shapes):
return [ins_shapes[0]]
def __str__(self):
return self.__class__.__name__
def col_scale(x, s): def col_scale(x, s):
if x.format == 'csc': if x.format == 'csc':
......
...@@ -428,56 +428,6 @@ def test_diag_grad(): ...@@ -428,56 +428,6 @@ def test_diag_grad():
utt.verify_grad(d, [diag_mat], utt.verify_grad(d, [diag_mat],
mode=theano.Mode(linker='py', optimizer='fast_compile')) mode=theano.Mode(linker='py', optimizer='fast_compile'))
def test_row_scale():
x = theano.sparse.csc_dmatrix()
s = theano.tensor.dvector()
rng = numpy.random.RandomState(8723)
R = 5
C = 8
x_val_dense = numpy.zeros((R, C), dtype='d')
for idx in [(0, 0), (4, 1), (2, 1), (3, 3), (4, 4), (3, 7), (2, 7)]:
x_val_dense.__setitem__(idx, rng.randn())
x_val = scipy.sparse.csc_matrix(x_val_dense)
s_val = rng.randn(R)
f = theano.function([x, s], sp.row_scale(x, s))
# print 'A', f(x_val, s_val).toarray()
# print 'B', (x_val_dense.T * s_val).T
assert numpy.all(f(x_val, s_val).toarray() == (x_val_dense.T * s_val).T)
verify_grad_sparse(sp.row_scale, [x_val, s_val], structured=False)
def test_col_scale():
x = theano.sparse.csc_dmatrix()
s = theano.tensor.dvector()
rng = numpy.random.RandomState(8723)
R = 5
C = 8
x_val_dense = numpy.zeros((R, C), dtype='d')
for idx in [(0, 0), (4, 1), (2, 1), (3, 3), (4, 4), (3, 7), (2, 7)]:
x_val_dense.__setitem__(idx, rng.randn())
x_val = scipy.sparse.csc_matrix(x_val_dense)
s_val = rng.randn(C)
f = theano.function([x, s], sp.col_scale(x, s))
# print 'A', f(x_val, s_val).toarray()
# print 'B', (x_val_dense * s_val)
assert numpy.all(f(x_val, s_val).toarray() == (x_val_dense * s_val))
verify_grad_sparse(sp.col_scale, [x_val, s_val], structured=False)
if __name__ == '__main__': if __name__ == '__main__':
if 0: if 0:
test_remove0() test_remove0()
......
...@@ -1370,6 +1370,88 @@ def test_size(): ...@@ -1370,6 +1370,88 @@ def test_size():
check() check()
class ColScaleCSCTester(utt.InferShapeTester):
def setUp(self):
super(ColScaleCSCTester, self).setUp()
self.op = sparse.col_scale
def test_op(self):
for format in sparse.sparse_formats:
variable, data = sparse_random_inputs(format, shape=(8, 10))
variable.append(tensor.vector())
data.append(numpy.random.random(10))
f = theano.function(variable, self.op(*variable))
tested = f(*data)
x, s = data[0].toarray(), data[1][numpy.newaxis, :]
expected = x * s
assert tested.format == format
assert numpy.allclose(tested.toarray(), expected)
def test_infer_shape(self):
for format, cls in [('csc', sparse.ColScaleCSC),
('csr', sparse.RowScaleCSC)]:
variable, data = sparse_random_inputs(format, shape=(8, 10))
variable.append(tensor.vector())
data.append(numpy.random.random(10))
self._compile_and_check(variable,
[self.op(*variable)],
data,
cls)
def test_grad(self):
for format in sparse.sparse_formats:
variable, data = sparse_random_inputs(format, shape=(8, 10))
variable.append(tensor.vector())
data.append(numpy.random.random(10))
verify_grad_sparse(self.op, data, structured=True)
class RowScaleCSCTester(utt.InferShapeTester):
def setUp(self):
super(RowScaleCSCTester, self).setUp()
self.op = sparse.row_scale
def test_op(self):
for format in sparse.sparse_formats:
variable, data = sparse_random_inputs(format, shape=(8, 10))
variable.append(tensor.vector())
data.append(numpy.random.random(8))
f = theano.function(variable, self.op(*variable))
tested = f(*data)
x, s = data[0].toarray(), data[1][:, numpy.newaxis]
expected = x * s
assert tested.format == format
assert numpy.allclose(tested.toarray(), expected)
def test_infer_shape(self):
for format, cls in [('csc', sparse.RowScaleCSC),
('csr', sparse.ColScaleCSC)]:
variable, data = sparse_random_inputs(format, shape=(8, 10))
variable.append(tensor.vector())
data.append(numpy.random.random(8))
self._compile_and_check(variable,
[self.op(*variable)],
data,
cls)
def test_grad(self):
for format in sparse.sparse_formats:
variable, data = sparse_random_inputs(format, shape=(8, 10))
variable.append(tensor.vector())
data.append(numpy.random.random(8))
verify_grad_sparse(self.op, data, structured=True)
class SpSumTester(utt.InferShapeTester): class SpSumTester(utt.InferShapeTester):
possible_axis = [None, 0, 1] possible_axis = [None, 0, 1]
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论