提交 9345964d authored 作者: Frederic's avatar Frederic

Add theano.sparse_grad interface.

上级 dce26c33
...@@ -48,3 +48,5 @@ There are also some top-level imports that you might find more convenient: ...@@ -48,3 +48,5 @@ There are also some top-level imports that you might find more convenient:
Works like :func:`tensor.dot` for both sparse and dense matrix products Works like :func:`tensor.dot` for both sparse and dense matrix products
.. autofunction:: theano.clone .. autofunction:: theano.clone
.. autofunction:: theano.sparse_grad
...@@ -168,6 +168,20 @@ def get_scalar_constant_value(v): ...@@ -168,6 +168,20 @@ def get_scalar_constant_value(v):
return tensor.get_scalar_constant_value(v) return tensor.get_scalar_constant_value(v)
def sparse_grad(var):
"""This function return a new variable whose gradient will be
stored in a sparse format instead of dense.
Currently only AdvancedSubtensor1 is supported.
"""
assert isinstance(var.owner.op, tensor.AdvancedSubtensor1)
# TODO change the internal representation!!!
# It work, but bad as out.type is shared with var.type!!!
var.owner.inputs[0].tag.sparse_grad = True
return var
import theano.tests import theano.tests
if hasattr(theano.tests, "TheanoNoseTester"): if hasattr(theano.tests, "TheanoNoseTester"):
test = theano.tests.TheanoNoseTester().test test = theano.tests.TheanoNoseTester().test
......
...@@ -418,28 +418,46 @@ class SparseInferShapeTester(utt.InferShapeTester): ...@@ -418,28 +418,46 @@ class SparseInferShapeTester(utt.InferShapeTester):
class TestConstructSparseFromList(unittest.TestCase): class TestConstructSparseFromList(unittest.TestCase):
def test_adv_sub1_sparse_grad(self): def test_adv_sub1_sparse_grad(self):
m = theano.tensor.matrix()
v = theano.tensor.ivector() v = theano.tensor.ivector()
sub = m[v]
# Assert we don't create a sparse grad by default # Assert we don't create a sparse grad by default
m = theano.tensor.matrix()
sub = m[v]
g = theano.grad(sub.sum(), m) g = theano.grad(sub.sum(), m)
assert isinstance(g.owner.op, tensor.AdvancedIncSubtensor1) assert isinstance(g.owner.op, tensor.AdvancedIncSubtensor1)
# Test that we create a sparse grad when asked # Test that we create a sparse grad when asked
# OLD INTERFACE
m = theano.tensor.matrix()
sub = m[v]
m.type.sparse_grad = True
g = theano.grad(sub.sum(), m)
assert isinstance(g.owner.op, ConstructSparseFromList)
# Test that we create a sparse grad when asked
# OLD INTERFACE CONSEQUENCE
m = theano.tensor.matrix()
sub = m[v]
sub.type.sparse_grad = True sub.type.sparse_grad = True
g = theano.grad(sub.sum(), m) g = theano.grad(sub.sum(), m)
assert isinstance(g.owner.op, ConstructSparseFromList) assert isinstance(g.owner.op, ConstructSparseFromList)
# Test that we create a sparse grad when asked
# USER INTERFACE
m = theano.tensor.matrix()
v = theano.tensor.ivector()
sub = theano.sparse_grad(m[v])
g = theano.grad(sub.sum(), m)
assert isinstance(g.owner.op, ConstructSparseFromList)
# Test the sparse grad # Test the sparse grad
valm = numpy.random.rand(5, 4).astype(config.floatX) valm = numpy.random.rand(5, 4).astype(config.floatX)
valv = numpy.random.random_integers(0, 4, 10) valv = numpy.random.random_integers(0, 4, 10)
m = theano.tensor.matrix()
shared_v = theano.shared(valv) shared_v = theano.shared(valv)
def fn(m): def fn(m):
sub = m[shared_v] return theano.sparse_grad(m[shared_v])
sub.type.sparse_grad = True
return sub
verify_grad_sparse(fn, [valm]) verify_grad_sparse(fn, [valm])
def test_err(self): def test_err(self):
...@@ -454,7 +472,7 @@ class TestConstructSparseFromList(unittest.TestCase): ...@@ -454,7 +472,7 @@ class TestConstructSparseFromList(unittest.TestCase):
assert isinstance(g.owner.op, tensor.AdvancedIncSubtensor1) assert isinstance(g.owner.op, tensor.AdvancedIncSubtensor1)
# Test that we create a sparse grad when asked # Test that we create a sparse grad when asked
sub.type.sparse_grad = True sub = theano.sparse_grad(sub)
self.assertRaises(TypeError, theano.grad, sub.sum(), t) self.assertRaises(TypeError, theano.grad, sub.sum(), t)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论