提交 efdaacec authored 作者: Li Yao's avatar Li Yao

python code for max pool grad grad

上级 d8c0f365
...@@ -563,12 +563,12 @@ class DownsampleFactorMaxGrad(Op): ...@@ -563,12 +563,12 @@ class DownsampleFactorMaxGrad(Op):
def grad(self, inp, grads): def grad(self, inp, grads):
x, maxout, gz = inp x, maxout, gz = inp
ggx, = grads ggx, = grads
if self.padding == (0, 0) and self.mode == 'max': if self.mode == 'max':
return [theano.tensor.zeros_like(x), return [theano.tensor.zeros_like(x),
theano.tensor.zeros_like(maxout), theano.tensor.zeros_like(maxout),
DownsampleFactorMaxGradGrad( DownsampleFactorMaxGradGrad(
self.ds, ignore_border=self.ignore_border, self.ds, ignore_border=self.ignore_border,
st=self.st)(x, maxout, ggx)] st=self.st, padding=self.padding)(x, maxout, ggx)]
else: else:
return [theano.tensor.zeros_like(x), return [theano.tensor.zeros_like(x),
theano.tensor.zeros_like(maxout), theano.tensor.zeros_like(maxout),
...@@ -694,10 +694,10 @@ class DownsampleFactorMaxGrad(Op): ...@@ -694,10 +694,10 @@ class DownsampleFactorMaxGrad(Op):
return (0, 7) return (0, 7)
class DownsampleFactorMaxGradGrad(Op): class DownsampleFactorMaxGradGrad(Op):
__props__ = ('ds', 'ignore_border', 'st') __props__ = ('ds', 'ignore_border', 'st', 'padding')
@staticmethod @staticmethod
def out_shape(imgshape, ds, ignore_border=False, st=None): def out_shape(imgshape, ds, ignore_border=False, st=None, padding=(0, 0)):
"""Return the shape of the output from this op, for input of given """Return the shape of the output from this op, for input of given
shape and flags. shape and flags.
...@@ -718,6 +718,11 @@ class DownsampleFactorMaxGradGrad(Op): ...@@ -718,6 +718,11 @@ class DownsampleFactorMaxGradGrad(Op):
extra row/col of partial downsampling (False) or ignore it (True). extra row/col of partial downsampling (False) or ignore it (True).
:type ignore_border: bool :type ignore_border: bool
:param padding: (pad_h, pad_w), pad zeros to extend beyond four borders
of the images, pad_h is the size of the top and bottom margins,
and pad_w is the size of the left and right margins.
:type padding: tuple of two ints
:rtype: list :rtype: list
:returns: the shape of the output from this op, for input of given :returns: the shape of the output from this op, for input of given
shape. This will have the same length as imgshape, but with last shape. This will have the same length as imgshape, but with last
...@@ -730,6 +735,8 @@ class DownsampleFactorMaxGradGrad(Op): ...@@ -730,6 +735,8 @@ class DownsampleFactorMaxGradGrad(Op):
if st is None: if st is None:
st = ds st = ds
r, c = imgshape[-2:] r, c = imgshape[-2:]
r += padding[0] * 2
c += padding[1] * 2
if ignore_border: if ignore_border:
out_r = (r - ds[0]) // st[0] + 1 out_r = (r - ds[0]) // st[0] + 1
...@@ -766,12 +773,25 @@ class DownsampleFactorMaxGradGrad(Op): ...@@ -766,12 +773,25 @@ class DownsampleFactorMaxGradGrad(Op):
rval = list(imgshape[:-2]) + [nr, nc] rval = list(imgshape[:-2]) + [nr, nc]
return rval return rval
def __init__(self, ds, ignore_border, st=None): def __init__(self, ds, ignore_border, st=None, padding=(0,0)):
self.ds = tuple(ds) self.ds = tuple(ds)
self.ignore_border = ignore_border if not all([isinstance(d, int) for d in ds]):
raise ValueError(
"DownsampleFactorMax downsample parameters must be ints."
" Got %s" % str(ds))
if st is None: if st is None:
st = ds st = ds
assert isinstance(st, (tuple, list))
self.st = tuple(st) self.st = tuple(st)
self.ignore_border = ignore_border
self.padding = tuple(padding)
if self.padding != (0, 0) and not ignore_border:
raise NotImplementedError(
'padding works only with ignore_border=True')
if self.padding[0] >= self.ds[0] or self.padding[1] >= self.ds[1]:
raise NotImplementedError(
'padding_h and padding_w must be smaller than strides')
def make_node(self, x, maxout, gz): def make_node(self, x, maxout, gz):
# make_node should only be called by the grad function of # make_node should only be called by the grad function of
...@@ -788,26 +808,38 @@ class DownsampleFactorMaxGradGrad(Op): ...@@ -788,26 +808,38 @@ class DownsampleFactorMaxGradGrad(Op):
def perform(self, node, inp, out): def perform(self, node, inp, out):
x, maxout, ggx = inp x, maxout, ggx = inp
z, = out z, = out
if len(x.shape) != 4: if len(x.shape) != 4:
raise NotImplementedError( raise NotImplementedError(
'DownsampleFactorMaxGradGrad requires 4D input for now') 'DownsampleFactorMaxGradGrad requires 4D input for now')
z_shape = self.out_shape(x.shape, self.ds, self.ignore_border, self.st) z_shape = self.out_shape(x.shape, self.ds, self.ignore_border,
self.st, self.padding)
if (z[0] is None) or (z[0].shape != z_shape): if (z[0] is None) or (z[0].shape != z_shape):
z[0] = numpy.zeros(self.out_shape(x.shape, self.ds, z[0] = numpy.zeros(z_shape, dtype=x.dtype)
self.ignore_border, self.st),
dtype=x.dtype)
ggz = z[0] ggz = z[0]
# number of pooling output rows # number of pooling output rows
pr = ggz.shape[-2] pr = ggz.shape[-2]
# number of pooling output cols # number of pooling output cols
pc = ggz.shape[-1] pc = ggz.shape[-1]
ds0, ds1 = self.ds ds0, ds1 = self.ds
st0, st1 = self.st st0, st1 = self.st
img_rows = x.shape[-2] pd0, pd1 = self.padding
img_cols = x.shape[-1] img_rows = x.shape[-2] + 2 * pd0
img_cols = x.shape[-1] + 2 * pd1
# pad the image and its gradients
if self.padding != (0, 0):
y_padded = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype) + x.min() - 1
y_padded[:, :, pd0:(img_rows-pd0), pd1:(img_cols-pd1)] = x
ggx_padded = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype)
ggx_padded[:, :, pd0:(img_rows-pd0), pd1:(img_cols-pd1)] = ggx
else:
y_padded = x
ggx_padded = ggx
for n in xrange(x.shape[0]): for n in xrange(x.shape[0]):
for k in xrange(x.shape[1]): for k in xrange(x.shape[1]):
for r in xrange(pr): for r in xrange(pr):
...@@ -818,8 +850,8 @@ class DownsampleFactorMaxGradGrad(Op): ...@@ -818,8 +850,8 @@ class DownsampleFactorMaxGradGrad(Op):
col_end = __builtin__.min(col_st + ds1, img_cols) col_end = __builtin__.min(col_st + ds1, img_cols)
for row_ind in xrange(row_st, row_end): for row_ind in xrange(row_st, row_end):
for col_ind in xrange(col_st, col_end): for col_ind in xrange(col_st, col_end):
if (maxout[n, k, r, c] == x[n, k, row_ind, col_ind]): if (maxout[n, k, r, c] == y_padded[n, k, row_ind, col_ind]):
ggz[n, k, r, c] = ggx[n, k, row_ind, col_ind] ggz[n, k, r, c] = ggx_padded[n, k, row_ind, col_ind]
def infer_shape(self, node, in_shapes): def infer_shape(self, node, in_shapes):
return [in_shapes[0]] return [in_shapes[0]]
...@@ -8,7 +8,9 @@ import theano ...@@ -8,7 +8,9 @@ import theano
import theano.tensor as tensor import theano.tensor as tensor
from theano.tests import unittest_tools as utt from theano.tests import unittest_tools as utt
from theano.tensor.signal.downsample import (DownsampleFactorMax, max_pool_2d, from theano.tensor.signal.downsample import (DownsampleFactorMax, max_pool_2d,
DownsampleFactorMaxGrad, max_pool_2d_same_size) DownsampleFactorMaxGrad,
DownsampleFactorMaxGradGrad,
max_pool_2d_same_size)
from theano import function from theano import function
...@@ -461,7 +463,36 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -461,7 +463,36 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
if numpy.prod(grad_shape) == 0: if numpy.prod(grad_shape) == 0:
continue continue
utt.verify_grad(mp, [imval, grad_val], rng=rng) utt.verify_grad(mp, [imval, grad_val], rng=rng)
def test_DownsampleFactorMaxPaddingStride_grad_grad(self):
rng = numpy.random.RandomState(utt.fetch_seed())
imgsizes = ((10, 10), (10, 5), (5, 5))
maxpoolsizes = ((5, 3), (3, 5), (3, 3))
stridesizes = ((3, 2), (2, 3), (3, 3))
paddingsizes = ((2, 2), (2, 1), (2, 2))
for i in range(len(imgsizes)):
imgsize = imgsizes[i]
imval = rng.rand(1, 1, imgsize[0], imgsize[1]) * 10.0
maxpoolsize = maxpoolsizes[i]
stridesize = stridesizes[i]
paddingsize = paddingsizes[i]
grad_shape = DownsampleFactorMaxGradGrad.out_shape(
imval.shape, maxpoolsize, st=stridesize,
ignore_border=True, padding=paddingsize)
grad_val = rng.rand(*grad_shape) * 10.0
def mp(input, grad):
out = DownsampleFactorMax(
maxpoolsize, ignore_border=True,
st=stridesize,
padding=paddingsize,
)(input)
grad_op = DownsampleFactorMaxGrad(maxpoolsize, ignore_border=True,
st=stridesize, padding=paddingsize)
return grad_op(input, out, grad)
utt.verify_grad(mp, [imval, grad_val], rng=rng)
def test_DownsampleFactorMax_hessian(self): def test_DownsampleFactorMax_hessian(self):
# Example provided by Frans Cronje, see # Example provided by Frans Cronje, see
# https://groups.google.com/d/msg/theano-users/qpqUy_3glhw/JMwIvlN5wX4J # https://groups.google.com/d/msg/theano-users/qpqUy_3glhw/JMwIvlN5wX4J
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论