提交 3b3b2a4e authored 作者: Frédéric Bastien's avatar Frédéric Bastien

Merge pull request #3547 from peterjsadowski/neighborhood_grad

Implemented grad for Images2Neibs using scan.
......@@ -109,6 +109,43 @@ class Images2Neibs(Op):
return [neibs2images(gz, neib_shape, x.shape, mode=self.mode),
grad_undefined(self, 1, neib_shape),
grad_undefined(self, 2, neib_step)]
if self.mode in ['valid']:
# Iterate over neighborhood positions, summing contributions.
def pos2map(pidx, pgz, prior_result, neib_shape, neib_step):
'''
Helper function that adds gradient contribution from a single
neighborhood position i,j.
pidx = Index of position within neighborhood.
pgz = Gradient of shape (batch_size*num_channels*neibs)
prior_result = Shape (batch_size, num_channnels, rows, cols)
neib_shape = Number of rows, cols in a neighborhood.
neib_step = Step sizes from image2neibs.
'''
nrows, ncols = neib_shape
rstep, cstep = neib_step
batch_size, num_channels, rows, cols = prior_result.shape
i = pidx // ncols
j = pidx - (i * ncols)
# This position does not touch some img pixels in valid mode.
result_indices = prior_result[:, :,
i:(rows - nrows + i + 1):rstep,
j:(cols - ncols + j + 1):cstep]
newshape = (batch_size, num_channels) + \
((rows - nrows) // rstep + 1,) + \
((cols - ncols) // cstep + 1,)
return T.inc_subtensor(result_indices, pgz.reshape(newshape))
indices = T.arange(neib_shape[0] * neib_shape[1])
pgzs = gz.dimshuffle((1, 0))
result, _ = theano.scan(fn=pos2map,
sequences=[indices, pgzs],
outputs_info=T.zeros(x.shape),
non_sequences=[neib_shape, neib_step])
grad_input = result[-1]
return [grad_input,
grad_undefined(self, 1, neib_shape),
grad_undefined(self, 2, neib_step)]
return [grad_not_implemented(self, 0, x),
grad_undefined(self, 1, neib_shape),
grad_undefined(self, 2, neib_step)]
......
......@@ -287,7 +287,7 @@ class T_Images2Neibs(unittest_tools.InferShapeTester):
fn, [images_val], mode=self.mode)
def test_grad_valid(self):
shape = (2, 3, 4, 4)
shape = (2, 3, 6, 6)
images_val = numpy.random.rand(*shape).astype('float32')
def fn(images):
......@@ -296,13 +296,18 @@ class T_Images2Neibs(unittest_tools.InferShapeTester):
unittest_tools.verify_grad(fn, [images_val], mode=self.mode,
eps=0.1)
# The grad is not defined when the neib_shape and neib_step
# are not the same.
def fn(images):
return images2neibs(images, (2, 2), (1, 1))
self.assertRaises(TypeError,
unittest_tools.verify_grad, fn, [images_val],
mode=self.mode)
return images2neibs(images, (3, 2), (1, 2))
unittest_tools.verify_grad(fn, [images_val], mode=self.mode,
eps=0.1)
def fn(images):
return images2neibs(images, (1, 2), (5, 2))
unittest_tools.verify_grad(fn, [images_val], mode=self.mode,
eps=0.1)
def test_grad_ignore_border(self):
shape = (2, 3, 5, 5)
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论