提交 06c15dc1 authored 作者: James Bergstra's avatar James Bergstra

added grad to IncSubtensor

上级 563bdb57
...@@ -2465,7 +2465,7 @@ class IncSubtensor(Op): ...@@ -2465,7 +2465,7 @@ class IncSubtensor(Op):
This is like numpy's This is like numpy's
z[i,j,k] += <something> x[i,j,k] += y
It is used internally to implement the gradient on SubTensor. It is used internally to implement the gradient on SubTensor.
...@@ -2583,6 +2583,15 @@ class IncSubtensor(Op): ...@@ -2583,6 +2583,15 @@ class IncSubtensor(Op):
x.__setitem__(cdata, y) x.__setitem__(cdata, y)
out[0] = x out[0] = x
def grad(self, inputs, (g_output,)):
x, y = inputs[:2]
idx_list = inputs[2:]
gx = g_output
gy = Subtensor(idx_list = self.idx_list)(g_output, *idx_list)
return [gx, gy] + [None]*len(idx_list)
def split(x, splits_size, n_splits, axis=0): def split(x, splits_size, n_splits, axis=0):
the_split = Split(n_splits) the_split = Split(n_splits)
return the_split(x, axis, splits_size) return the_split(x, axis, splits_size)
...@@ -3906,7 +3915,7 @@ class numeric_grad: ...@@ -3906,7 +3915,7 @@ class numeric_grad:
apt[i] = x[cur_pos:cur_pos+p_size].reshape(p.shape) apt[i] = x[cur_pos:cur_pos+p_size].reshape(p.shape)
self.gf.append(gx[cur_pos:cur_pos+p_size].reshape(p.shape)) self.gf.append(gx[cur_pos:cur_pos+p_size].reshape(p.shape))
# initialize with p's value # initialize with p's value
apt[i][:] = p apt[i][...] = p
cur_pos += p_size cur_pos += p_size
f_x = f(*[p.copy() for p in apt]) f_x = f(*[p.copy() for p in apt])
...@@ -3945,7 +3954,10 @@ class numeric_grad: ...@@ -3945,7 +3954,10 @@ class numeric_grad:
def verify_grad(op, pt, n_tests=2, rng=None, eps=None, tol=None, mode=None, cast_to_output_type=False): def verify_grad(op, pt, n_tests=2, rng=None, eps=None, tol=None, mode=None, cast_to_output_type=False):
""" WRITEME """ Test an Op's gradient by side effect. Return None on success, raise error on failure.
Example:
>>> verify_grad(theano.tensor.tanh, (numpy.asarray([[2,3,4], [-1, 3.3, 9.9]]),))
Raises an Exception if the difference between the analytic gradient and Raises an Exception if the difference between the analytic gradient and
numerical gradient (computed through the Finite Difference Method) exceeds numerical gradient (computed through the Finite Difference Method) exceeds
...@@ -3953,7 +3965,8 @@ def verify_grad(op, pt, n_tests=2, rng=None, eps=None, tol=None, mode=None, cast ...@@ -3953,7 +3965,8 @@ def verify_grad(op, pt, n_tests=2, rng=None, eps=None, tol=None, mode=None, cast
:param op: something that behaves like an Op instance with a single output :param op: something that behaves like an Op instance with a single output
(can be a python function combining multiple ops, but see note below) (can be a python function combining multiple ops, but see note below)
:param pt: the list of numpy.ndarrays to use as inputs to the op :param pt: the list of numpy.ndarrays to use as inputs to the op. These arrays must be
either float32 or float64 arrays.
:param n_tests: number of times to run the test :param n_tests: number of times to run the test
:param rng: random number generator from which to draw random samples :param rng: random number generator from which to draw random samples
:param eps: stepsize used in the Finite Difference Method (Default None is type-dependent) :param eps: stepsize used in the Finite Difference Method (Default None is type-dependent)
......
import numpy as N import numpy
import unittest import unittest
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
import theano import theano
...@@ -36,18 +36,49 @@ class Test_incsubtensor(unittest.TestCase): ...@@ -36,18 +36,49 @@ class Test_incsubtensor(unittest.TestCase):
f = theano.function([a, increment, sl2_end], resut) f = theano.function([a, increment, sl2_end], resut)
val_a = N.ones((5,5)) val_a = numpy.ones((5,5))
val_inc = 2.3 val_inc = 2.3
val_sl2_end = 2 val_sl2_end = 2
result = f(val_a, val_inc, val_sl2_end) result = f(val_a, val_inc, val_sl2_end)
expected_result = N.copy(val_a) expected_result = numpy.copy(val_a)
if do_set: if do_set:
expected_result[:,:val_sl2_end] = val_inc expected_result[:,:val_sl2_end] = val_inc
else: else:
expected_result[:,:val_sl2_end] += val_inc expected_result[:,:val_sl2_end] += val_inc
self.failUnless(N.array_equal(result, expected_result)) self.failUnless(numpy.array_equal(result, expected_result))
return return
def test_grad(self):
a = T.dvector()
b = T.dvector()
def inc_slice(*s):
def just_numeric_args(a,b):
return T.incsubtensor(a, b, s)
return just_numeric_args
# vector
utt.verify_grad(
inc_slice(slice(2,4,None)),
(numpy.asarray([0,1,2,3,4,5.]),
numpy.asarray([9,9.]),))
# matrix
utt.verify_grad(
inc_slice(slice(1,2,None), slice(None, None, None)),
(numpy.asarray([[0,1],[2,3],[4,5.]]),
numpy.asarray([[9,9.]]),))
#single element
utt.verify_grad(
inc_slice(2, 1),
(numpy.asarray([[0,1],[2,3],[4,5.]]),
numpy.asarray(9.),))
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论