提交 0a64e511 authored 作者: Cesar Laurent's avatar Cesar Laurent

Changed the interfaces of pool. Still some tests errors.

上级 f70948ab
...@@ -14,6 +14,7 @@ from six.moves import xrange ...@@ -14,6 +14,7 @@ from six.moves import xrange
import six.moves.builtins as builtins import six.moves.builtins as builtins
import theano import theano
from theano import gof, OpenMPOp, tensor, Variable, Apply from theano import gof, OpenMPOp, tensor, Variable, Apply
from theano.gradient import DisconnectedType
def max_pool_2d_same_size(input, patch_size): def max_pool_2d_same_size(input, patch_size):
...@@ -32,8 +33,8 @@ def max_pool_2d_same_size(input, patch_size): ...@@ -32,8 +33,8 @@ def max_pool_2d_same_size(input, patch_size):
(2,2) will retain only one non-zero value per patch of 4 values. (2,2) will retain only one non-zero value per patch of 4 values.
""" """
output = Pool(patch_size, True)(input) output = Pool(True)(input, patch_size)
outs = MaxPoolGrad(patch_size, True)(input, output, output) outs = MaxPoolGrad(True)(input, output, output, patch_size)
return outs return outs
...@@ -85,9 +86,8 @@ def pool_2d(input, ds, ignore_border=None, st=None, padding=(0, 0), ...@@ -85,9 +86,8 @@ def pool_2d(input, ds, ignore_border=None, st=None, padding=(0, 0),
stacklevel=2) stacklevel=2)
ignore_border = False ignore_border = False
if input.ndim == 4: if input.ndim == 4:
op = Pool(ds, ignore_border, st=st, padding=padding, op = Pool(ignore_border, mode=mode)
mode=mode) output = op(input, ds, st, padding)
output = op(input)
return output return output
# extract image dimensions # extract image dimensions
...@@ -104,9 +104,8 @@ def pool_2d(input, ds, ignore_border=None, st=None, padding=(0, 0), ...@@ -104,9 +104,8 @@ def pool_2d(input, ds, ignore_border=None, st=None, padding=(0, 0),
input_4D = tensor.reshape(input, new_shape, ndim=4) input_4D = tensor.reshape(input, new_shape, ndim=4)
# downsample mini-batch of images # downsample mini-batch of images
op = Pool(ds, ignore_border, st=st, padding=padding, op = Pool(ignore_border, mode=mode)
mode=mode) output = op(input_4D, ds, st, padding)
output = op(input_4D)
# restore to original shape # restore to original shape
outshp = tensor.join(0, input.shape[:-2], output.shape[-2:]) outshp = tensor.join(0, input.shape[:-2], output.shape[-2:])
...@@ -143,7 +142,7 @@ class Pool(OpenMPOp): ...@@ -143,7 +142,7 @@ class Pool(OpenMPOp):
""" """
__props__ = ('ds', 'ignore_border', 'st', 'padding', 'mode') __props__ = ('ignore_border', 'mode')
@staticmethod @staticmethod
def out_shape(imgshape, ds, ignore_border=False, st=None, padding=(0, 0)): def out_shape(imgshape, ds, ignore_border=False, st=None, padding=(0, 0)):
...@@ -234,50 +233,55 @@ class Pool(OpenMPOp): ...@@ -234,50 +233,55 @@ class Pool(OpenMPOp):
rval = list(imgshape[:-2]) + [nr, nc] rval = list(imgshape[:-2]) + [nr, nc]
return rval return rval
def __init__(self, ds, ignore_border=False, st=None, padding=(0, 0), def __init__(self, ignore_border=False, mode='max', openmp=None):
mode='max', openmp=None):
super(Pool, self).__init__(openmp=openmp) super(Pool, self).__init__(openmp=openmp)
self.ds = tuple(ds)
if not all([isinstance(d, integer_types) for d in ds]):
raise ValueError(
"Pool downsample parameters must be ints."
" Got %s" % str(ds))
if st is None:
st = ds
assert isinstance(st, (tuple, list))
self.st = tuple(st)
self.ignore_border = ignore_border 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')
if mode not in ['max', 'average_inc_pad', 'average_exc_pad', 'sum']: if mode not in ['max', 'average_inc_pad', 'average_exc_pad', 'sum']:
raise ValueError( raise ValueError(
"Pool mode parameter only support 'max', 'sum'," "Pool mode parameter only support 'max', 'sum',"
" 'average_inc_pad' and 'average_exc_pad'. Got %s" % mode) " 'average_inc_pad' and 'average_exc_pad'. Got %s" % mode)
self.mode = mode self.mode = mode
def make_node(self, x): def make_node(self, x, ws, stride=None, pad=(0, 0)):
# TODO: consider restricting the dtype? # TODO: consider restricting the dtype?
x = tensor.as_tensor_variable(x) x = tensor.as_tensor_variable(x)
# TODO CESAR: How can we check the theano variables?
if isinstance(ws, (tuple, list)):
if not all([isinstance(w, integer_types) for w in ws]):
raise ValueError(
"Pool downsample parameters must be ints."
" Got %s" % str(ws))
if stride is None:
stride = ws
if isinstance(pad, (tuple, list)):
pad = tuple(pad)
if pad != (0, 0) and not self.ignore_border:
raise NotImplementedError(
'padding works only with ignore_border=True')
# TODO CESAR: Again, how can we check against theano variables?
if pad[0] >= ws[0] or pad[1] >= ws[1]: #TODO CESAR this is wrong if ws is a theano variable
raise NotImplementedError(
'padding_h and padding_w must be smaller than strides')
ws = tensor.as_tensor_variable(ws)
stride = tensor.as_tensor_variable(stride)
pad = tensor.as_tensor_variable(pad)
assert ws.ndim == 1
assert stride.ndim == 1
assert pad.ndim == 1
if x.type.ndim != 4: if x.type.ndim != 4:
raise TypeError() raise TypeError()
# If the input shape are broadcastable we can have 0 in the output shape # If the input shape are broadcastable we can have 0 in the output shape
broad = x.broadcastable[:2] + (False, False) broad = x.broadcastable[:2] + (False, False)
out = tensor.TensorType(x.dtype, broad) out = tensor.TensorType(x.dtype, broad)
return gof.Apply(self, [x], [out()]) return gof.Apply(self, [x, ws, stride, pad], [out()])
def perform(self, node, inp, out): def perform(self, node, inp, out):
x, = inp x, ws, stride, pad = inp
z, = out z, = out
if len(x.shape) != 4: if len(x.shape) != 4:
raise NotImplementedError( raise NotImplementedError(
'Pool requires 4D input for now') 'Pool 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, ws, self.ignore_border, stride, pad)
self.padding)
if not self.ignore_border: if not self.ignore_border:
assert z_shape[2] > 0 assert z_shape[2] > 0
assert z_shape[3] > 0 assert z_shape[3] > 0
...@@ -288,16 +292,16 @@ class Pool(OpenMPOp): ...@@ -288,16 +292,16 @@ class Pool(OpenMPOp):
pr = zz.shape[-2] pr = zz.shape[-2]
# number of pooling output cols # number of pooling output cols
pc = zz.shape[-1] pc = zz.shape[-1]
ds0, ds1 = self.ds ws0, ws1 = ws
st0, st1 = self.st st0, st1 = stride
pad_h = self.padding[0] pad_h = pad[0]
pad_w = self.padding[1] pad_w = pad[1]
img_rows = x.shape[-2] + 2 * pad_h img_rows = x.shape[-2] + 2 * pad_h
img_cols = x.shape[-1] + 2 * pad_w img_cols = x.shape[-1] + 2 * pad_w
inc_pad = self.mode == 'average_inc_pad' inc_pad = self.mode == 'average_inc_pad'
# pad the image # pad the image
if self.padding != (0, 0): if pad_h != 0 and pad_w != 0:
y = numpy.zeros( y = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols), (x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype) dtype=x.dtype)
...@@ -314,47 +318,48 @@ class Pool(OpenMPOp): ...@@ -314,47 +318,48 @@ class Pool(OpenMPOp):
for k in xrange(x.shape[1]): for k in xrange(x.shape[1]):
for r in xrange(pr): for r in xrange(pr):
row_st = r * st0 row_st = r * st0
row_end = builtins.min(row_st + ds0, img_rows) row_end = builtins.min(row_st + ws0, img_rows)
if not inc_pad: if not inc_pad:
row_st = builtins.max(row_st, self.padding[0]) row_st = builtins.max(row_st, pad_h)
row_end = builtins.min(row_end, x.shape[-2] + pad_h) row_end = builtins.min(row_end, x.shape[-2] + pad_h)
for c in xrange(pc): for c in xrange(pc):
col_st = c * st1 col_st = c * st1
col_end = builtins.min(col_st + ds1, img_cols) col_end = builtins.min(col_st + ws1, img_cols)
if not inc_pad: if not inc_pad:
col_st = builtins.max(col_st, self.padding[1]) col_st = builtins.max(col_st, pad_w)
col_end = builtins.min(col_end, col_end = builtins.min(col_end,
x.shape[-1] + pad_w) x.shape[-1] + pad_w)
zz[n, k, r, c] = func(y[ zz[n, k, r, c] = func(y[
n, k, row_st:row_end, col_st:col_end]) n, k, row_st:row_end, col_st:col_end])
def infer_shape(self, node, in_shapes): def infer_shape(self, node, in_shapes):
shp = self.out_shape(in_shapes[0], self.ds, ws, stride, pad = [node.inputs[1], node.inputs[2], node.inputs[3]]
self.ignore_border, self.st, self.padding) shp = self.out_shape(in_shapes[0], ws, self.ignore_border, stride,
pad)
return [shp] return [shp]
def grad(self, inp, grads): def grad(self, inp, grads):
x, = inp x, ws, stride, pad = inp
gz, = grads gz, = grads
disc = [DisconnectedType()() for i in inp[1:]]
if self.mode == 'max': if self.mode == 'max':
maxout = self(x) maxout = self(x, ws, stride, pad)
return [MaxPoolGrad(self.ds, return [MaxPoolGrad(ignore_border=self.ignore_border)(x, maxout,
ignore_border=self.ignore_border, gz, ws=ws, stride=stride, pad=pad)] + disc
st=self.st, padding=self.padding)(
x, maxout, gz)]
else: else:
return [AveragePoolGrad(self.ds, return [AveragePoolGrad(ignore_border=self.ignore_border,
ignore_border=self.ignore_border, mode=self.mode)(x, gz, ws=ws,
st=self.st, padding=self.padding, stride=stride, pad=pad)] + disc
mode=self.mode)(
x, gz)] def connection_pattern(self, node):
return [[1], [0], [0], [0]]
def c_headers(self): def c_headers(self):
headers = ['<algorithm>'] headers = ['<algorithm>']
headers += super(Pool, self).c_headers() headers += super(Pool, self).c_headers()
return headers return headers
def c_code(self, node, name, inp, out, sub): def c_code_(self, node, name, inp, out, sub):
if self.mode not in ('max', 'sum', 'average_exc_pad', 'average_inc_pad'): if self.mode not in ('max', 'sum', 'average_exc_pad', 'average_inc_pad'):
raise theano.gof.utils.MethodNotDefined() raise theano.gof.utils.MethodNotDefined()
x, = inp x, = inp
...@@ -542,7 +547,7 @@ class Pool(OpenMPOp): ...@@ -542,7 +547,7 @@ class Pool(OpenMPOp):
class PoolGrad(OpenMPOp): class PoolGrad(OpenMPOp):
__props__ = ('ds', 'ignore_border', 'st', 'padding', 'mode') __props__ = ('ignore_border', 'mode')
@staticmethod @staticmethod
def out_shape(imgshape, ds, ignore_border=False, st=None, padding=(0, 0)): def out_shape(imgshape, ds, ignore_border=False, st=None, padding=(0, 0)):
...@@ -624,13 +629,8 @@ class PoolGrad(OpenMPOp): ...@@ -624,13 +629,8 @@ class PoolGrad(OpenMPOp):
rval = list(imgshape[:-2]) + [nr, nc] rval = list(imgshape[:-2]) + [nr, nc]
return rval return rval
def __init__(self, ds, ignore_border, st=None, padding=(0, 0), mode='max', openmp=None): def __init__(self, ignore_border, mode='max', openmp=None):
self.ds = tuple(ds)
self.ignore_border = ignore_border self.ignore_border = ignore_border
if st is None:
st = ds
self.st = tuple(st)
self.padding = tuple(padding)
if mode not in ['max', 'sum', 'average_inc_pad', 'average_exc_pad']: if mode not in ['max', 'sum', 'average_inc_pad', 'average_exc_pad']:
raise ValueError( raise ValueError(
"Pool mode parameter only support 'max', 'sum'," "Pool mode parameter only support 'max', 'sum',"
...@@ -643,38 +643,43 @@ class PoolGrad(OpenMPOp): ...@@ -643,38 +643,43 @@ class PoolGrad(OpenMPOp):
class MaxPoolGrad(PoolGrad): class MaxPoolGrad(PoolGrad):
def __init__(self, ds, ignore_border, st=None, padding=(0, 0), openmp=None): def __init__(self, ignore_border, openmp=None):
PoolGrad.__init__(self, ds, ignore_border, st, padding, 'max', openmp) PoolGrad.__init__(self, ignore_border, mode='max', openmp=openmp)
def make_node(self, x, maxout, gz): def make_node(self, x, maxout, gz, ws, stride=None, pad=(0, 0)):
# make_node should only be called by the grad function of # make_node should only be called by the grad function of
# Pool, so these asserts should not fail. # Pool, so these asserts should not fail.
x = tensor.as_tensor_variable(x) x = tensor.as_tensor_variable(x)
maxout = tensor.as_tensor_variable(maxout) maxout = tensor.as_tensor_variable(maxout)
gz = tensor.as_tensor_variable(gz) gz = tensor.as_tensor_variable(gz)
if stride is None:
stride = ws
ws = tensor.as_tensor_variable(ws)
stride = tensor.as_tensor_variable(stride)
pad = tensor.as_tensor_variable(pad)
assert isinstance(x, Variable) and x.ndim == 4 assert isinstance(x, Variable) and x.ndim == 4
assert isinstance(maxout, Variable) and maxout.ndim == 4 assert isinstance(maxout, Variable) and maxout.ndim == 4
assert isinstance(gz, Variable) and gz.ndim == 4 assert isinstance(gz, Variable) and gz.ndim == 4
#TODO CESAR: ASSERT
return Apply(self, [x, maxout, gz], [x.type()]) return Apply(self, [x, maxout, gz, ws, stride, pad], [x.type()])
def perform(self, node, inp, out): def perform(self, node, inp, out):
assert self.mode == 'max' assert self.mode == 'max'
x, maxout, gz = inp x, maxout, gz, ws, stride, pad = inp
gx_stg, = out gx_stg, = out
# number of pooling output rows # number of pooling output rows
pr = maxout.shape[-2] pr = maxout.shape[-2]
# number of pooling output cols # number of pooling output cols
pc = maxout.shape[-1] pc = maxout.shape[-1]
ds0, ds1 = self.ds ws0, ws1 = ws
st0, st1 = self.st st0, st1 = stride
pad_h = self.padding[0] pad_h = pad[0]
pad_w = self.padding[1] pad_w = pad[1]
img_rows = x.shape[-2] + 2 * pad_h img_rows = x.shape[-2] + 2 * pad_h
img_cols = x.shape[-1] + 2 * pad_w img_cols = x.shape[-1] + 2 * pad_w
# pad the image # pad the image
if self.padding != (0, 0): if pad_h != 0 and pad_w != 0:
y = numpy.zeros( y = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols), (x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype) dtype=x.dtype)
...@@ -685,11 +690,11 @@ class MaxPoolGrad(PoolGrad): ...@@ -685,11 +690,11 @@ class MaxPoolGrad(PoolGrad):
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):
row_st = builtins.max(r * st0, self.padding[0]) row_st = builtins.max(r * st0, pad_h)
row_end = builtins.min(row_st + ds0, img_rows) row_end = builtins.min(row_st + ws0, img_rows)
for c in xrange(pc): for c in xrange(pc):
col_st = builtins.max(c * st1, self.padding[1]) col_st = builtins.max(c * st1, pad_w)
col_end = builtins.min(col_st + ds1, img_cols) col_end = builtins.min(col_st + ws1, 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] == y[n, k, row_ind, col_ind]): if (maxout[n, k, r, c] == y[n, k, row_ind, col_ind]):
...@@ -699,15 +704,18 @@ class MaxPoolGrad(PoolGrad): ...@@ -699,15 +704,18 @@ class MaxPoolGrad(PoolGrad):
gx_stg[0] = gx gx_stg[0] = gx
def grad(self, inp, grads): def grad(self, inp, grads):
x, maxout, gz = inp x, maxout, gz, ws, stride, pad = inp
ggx, = grads ggx, = grads
return [theano.tensor.zeros_like(x), return ([theano.tensor.zeros_like(x),
theano.tensor.zeros_like(maxout), theano.tensor.zeros_like(maxout),
DownsampleFactorMaxGradGrad( DownsampleFactorMaxGradGrad(ignore_border=self.ignore_border)(
self.ds, ignore_border=self.ignore_border, x, maxout, ggx, ws, stride, pad)] +
st=self.st, padding=self.padding)(x, maxout, ggx)] [DisconnectedType()() for i in inp[3:]])
def connection_pattern(self, node):
return [[1], [1], [1], [0], [0], [0]]
def c_code(self, node, name, inp, out, sub): def c_code_(self, node, name, inp, out, sub):
assert self.mode == 'max' assert self.mode == 'max'
x, z, gz = inp x, z, gz = inp
gx, = out gx, = out
...@@ -824,32 +832,35 @@ class MaxPoolGrad(PoolGrad): ...@@ -824,32 +832,35 @@ class MaxPoolGrad(PoolGrad):
class AveragePoolGrad(PoolGrad): class AveragePoolGrad(PoolGrad):
def __init__(self, ds, ignore_border, st=None, padding=(0, 0), def __init__(self, ignore_border, mode='average_inc_pad'):
mode='average_inc_pad'):
assert mode in ['sum', 'average_inc_pad', 'average_exc_pad'] assert mode in ['sum', 'average_inc_pad', 'average_exc_pad']
PoolGrad.__init__(self, ds, ignore_border, st, padding, mode) PoolGrad.__init__(self, ignore_border, mode)
# There is an extra dummy parameter to match the parameter count # There is an extra dummy parameter to match the parameter count
# of MaxPoolGrad. They have to keep the same interface because of # of MaxPoolGrad. They have to keep the same interface because of
# the DownsampleFactorMaxGrad trick to keep old scripts working # the DownsampleFactorMaxGrad trick to keep old scripts working
# (see downsample.py for details on this). # (see downsample.py for details on this).
def make_node(self, x, gz, dummy=None): def make_node(self, x, gz, ws, stride=None, pad=(0, 0), dummy=None): # TODO CESAR check if it works!
# make_node should only be called by the grad function of # make_node should only be called by the grad function of
# Pool, so these asserts should not fail. # Pool, so these asserts should not fail.
x = tensor.as_tensor_variable(x) x = tensor.as_tensor_variable(x)
gz = tensor.as_tensor_variable(gz) gz = tensor.as_tensor_variable(gz)
if stride is None:
stride = ws
ws = tensor.as_tensor_variable(ws)
stride = tensor.as_tensor_variable(stride)
pad = tensor.as_tensor_variable(pad)
assert isinstance(x, Variable) and x.ndim == 4 assert isinstance(x, Variable) and x.ndim == 4
assert isinstance(gz, Variable) and gz.ndim == 4 assert isinstance(gz, Variable) and gz.ndim == 4
# TODO CESAR assert
return Apply(self, [x, gz], [x.type()]) return Apply(self, [x, gz, ws, stride, pad], [x.type()])
def perform(self, node, inp, out): def perform(self, node, inp, out):
if self.mode == 'average_exc_pad' and self.padding != (0, 0): x, gz, ws, stride, pad = inp
raise NotImplementedError()
x, gz = inp
gx_stg, = out gx_stg, = out
z_shape = self.out_shape(x.shape, self.ds, self.ignore_border, self.st, if self.mode == 'average_exc_pad' and pad[0] != 0 and pad[1] != 0:
self.padding) raise NotImplementedError()
z_shape = self.out_shape(x.shape, ws, self.ignore_border, stride, pad)
if (gx_stg[0] is None) or (gx_stg[0].shape != z_shape): if (gx_stg[0] is None) or (gx_stg[0].shape != z_shape):
gx_stg[0] = numpy.empty(z_shape, dtype=x.dtype) gx_stg[0] = numpy.empty(z_shape, dtype=x.dtype)
zz = gx_stg[0] zz = gx_stg[0]
...@@ -857,17 +868,17 @@ class AveragePoolGrad(PoolGrad): ...@@ -857,17 +868,17 @@ class AveragePoolGrad(PoolGrad):
pr = zz.shape[-2] pr = zz.shape[-2]
# number of pooling output cols # number of pooling output cols
pc = zz.shape[-1] pc = zz.shape[-1]
ds0, ds1 = self.ds ws0, ws1 = ws
st0, st1 = self.st st0, st1 = stride
pad_h = self.padding[0] pad_h = pad[0]
pad_w = self.padding[1] pad_w = pad[1]
img_rows = x.shape[-2] + 2 * pad_h img_rows = x.shape[-2] + 2 * pad_h
img_cols = x.shape[-1] + 2 * pad_w img_cols = x.shape[-1] + 2 * pad_w
inc_pad = self.mode == 'average_inc_pad' inc_pad = self.mode == 'average_inc_pad'
sum_mode = self.mode == 'sum' sum_mode = self.mode == 'sum'
# pad the image # pad the image
if self.padding != (0, 0): if pad_h != 0 and pad_w != 0:
y = numpy.zeros( y = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols), (x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype) dtype=x.dtype)
...@@ -881,15 +892,14 @@ class AveragePoolGrad(PoolGrad): ...@@ -881,15 +892,14 @@ class AveragePoolGrad(PoolGrad):
if sum_mode or inc_pad: if sum_mode or inc_pad:
row_st = r * st0 row_st = r * st0
else: else:
row_st = builtins.max(r * st0, self.padding[0]) row_st = builtins.max(r * st0, pad_h)
row_end = builtins.min(row_st + ds0, img_rows) row_end = builtins.min(row_st + ws0, img_rows)
for c in xrange(pc): for c in xrange(pc):
if sum_mode or inc_pad: if sum_mode or inc_pad:
col_st = c * st1 col_st = c * st1
else: else:
col_st = builtins.max(c * st1, col_st = builtins.max(c * st1, pad_w)
self.padding[1]) col_end = builtins.min(col_st + ws1, img_cols)
col_end = builtins.min(col_st + ds1, img_cols)
if sum_mode: if sum_mode:
val = gz[n, k, r, c] val = gz[n, k, r, c]
else: else:
...@@ -901,39 +911,27 @@ class AveragePoolGrad(PoolGrad): ...@@ -901,39 +911,27 @@ class AveragePoolGrad(PoolGrad):
gx_stg[0] = gx gx_stg[0] = gx
def grad(self, inp, grads): def grad(self, inp, grads):
x, gz = inp x, gz, ws, stride, pad = inp
ggx, = grads ggx, = grads
return [theano.tensor.zeros_like(x), return ([theano.tensor.zeros_like(x),
Pool(self.ds, ignore_border=self.ignore_border, Pool(ignore_border=self.ignore_border, mode=self.mode)(ggx,
st=self.st, padding=self.padding, mode=self.mode)(ggx)] ws, stride, pad)] +
[DisconnectedType()() for i in inp[2:]])
def connection_pattern(self, node):
return [[1], [1], [0], [0], [0]]
class DownsampleFactorMaxGradGrad(OpenMPOp): class DownsampleFactorMaxGradGrad(OpenMPOp):
__props__ = ('ds', 'ignore_border', 'st', 'padding', 'mode') __props__ = ('ignore_border', 'mode')
def __init__(self, ds, ignore_border, st=None, padding=(0, 0), mode='max', openmp=None): def __init__(self, ignore_border, mode='max', openmp=None):
self.ds = tuple(ds)
if not all([isinstance(d, integer_types) for d in ds]):
raise ValueError(
"Pool downsample parameters must be ints."
" Got %s" % str(ds))
if st is None:
st = ds
assert isinstance(st, (tuple, list))
self.st = tuple(st)
self.ignore_border = ignore_border 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')
self.mode = mode self.mode = mode
super(DownsampleFactorMaxGradGrad, self).__init__(openmp=openmp) super(DownsampleFactorMaxGradGrad, self).__init__(openmp=openmp)
assert self.mode == 'max' assert self.mode == 'max'
def make_node(self, x, maxout, gz): def make_node(self, x, maxout, gz, ws, stride=None, pad=(0, 0)):
# make_node should only be called by the grad function of # make_node should only be called by the grad function of
# MaxPoolGrad, so these asserts should not fail. # MaxPoolGrad, so these asserts should not fail.
x = tensor.as_tensor_variable(x) x = tensor.as_tensor_variable(x)
...@@ -943,10 +941,34 @@ class DownsampleFactorMaxGradGrad(OpenMPOp): ...@@ -943,10 +941,34 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
assert maxout.ndim == 4 assert maxout.ndim == 4
assert gz.ndim == 4 assert gz.ndim == 4
return Apply(self, [x, maxout, gz], [x.type()]) # TODO CESAR: How can we check the theano variables?
if isinstance(ws, (tuple, list)):
if not all([isinstance(w, integer_types) for w in ws]):
raise ValueError(
"Pool downsample parameters must be ints."
" Got %s" % str(ws))
if stride is None:
stride = ws
if isinstance(pad, (tuple, list)):
pad = tuple(pad)
if pad != (0, 0) and not self.ignore_border:
raise NotImplementedError(
'padding works only with ignore_border=True')
# TODO CESAR: Again, how can we check against theano variables?
if pad[0] >= ws[0] or pad[1] >= ws[1]: #TODO CESAR this is wrong if ws is a theano variable
raise NotImplementedError(
'padding_h and padding_w must be smaller than strides')
ws = tensor.as_tensor_variable(ws)
stride = tensor.as_tensor_variable(stride)
pad = tensor.as_tensor_variable(pad)
assert ws.ndim == 1
assert stride.ndim == 1
assert pad.ndim == 1
return Apply(self, [x, maxout, gz, ws, stride, pad], [x.type()])
def perform(self, node, inp, out): def perform(self, node, inp, out):
x, maxout, ggx = inp x, maxout, ggx, ws, stride, pad = inp
z, = out z, = out
if len(x.shape) != 4: if len(x.shape) != 4:
raise NotImplementedError( raise NotImplementedError(
...@@ -958,14 +980,14 @@ class DownsampleFactorMaxGradGrad(OpenMPOp): ...@@ -958,14 +980,14 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
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 ws0, ws1 = ws
st0, st1 = self.st st0, st1 = stride
pd0, pd1 = self.padding pd0, pd1 = pad
img_rows = x.shape[-2] + 2 * pd0 img_rows = x.shape[-2] + 2 * pd0
img_cols = x.shape[-1] + 2 * pd1 img_cols = x.shape[-1] + 2 * pd1
# pad the image and its gradients # pad the image and its gradients
if self.padding != (0, 0): if pd0 == 0 and pd1 == 0:
y_padded = numpy.zeros( y_padded = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols), (x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype) + x.min() - 1 dtype=x.dtype) + x.min() - 1
...@@ -982,10 +1004,10 @@ class DownsampleFactorMaxGradGrad(OpenMPOp): ...@@ -982,10 +1004,10 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
for k in xrange(x.shape[1]): for k in xrange(x.shape[1]):
for r in xrange(pr): for r in xrange(pr):
row_st = r * st0 row_st = r * st0
row_end = builtins.min(row_st + ds0, img_rows) row_end = builtins.min(row_st + ws0, img_rows)
for c in xrange(pc): for c in xrange(pc):
col_st = c * st1 col_st = c * st1
col_end = builtins.min(col_st + ds1, img_cols) col_end = builtins.min(col_st + ws1, 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] == y_padded[n, k, row_ind, col_ind]): if (maxout[n, k, r, c] == y_padded[n, k, row_ind, col_ind]):
...@@ -1003,7 +1025,7 @@ class DownsampleFactorMaxGradGrad(OpenMPOp): ...@@ -1003,7 +1025,7 @@ class DownsampleFactorMaxGradGrad(OpenMPOp):
self.ds, ignore_border=self.ignore_border, self.ds, ignore_border=self.ignore_border,
st=self.st, padding=self.padding)(x, maxout, gz)] st=self.st, padding=self.padding)(x, maxout, gz)]
def c_code(self, node, name, inp, out, sub): def c_code_(self, node, name, inp, out, sub):
if self.mode != 'max': if self.mode != 'max':
raise theano.gof.utils.MethodNotDefined() raise theano.gof.utils.MethodNotDefined()
x, maxout, ggx = inp x, maxout, ggx = inp
......
...@@ -197,9 +197,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -197,9 +197,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
utt.assert_allclose(output_val, numpy_output_val) utt.assert_allclose(output_val, numpy_output_val)
# Pool op # Pool op
maxpool_op = Pool(maxpoolshp, maxpool_op = Pool(ignore_border=ignore_border,
ignore_border=ignore_border, mode=mode)(images, maxpoolshp)
mode=mode)(images)
output_shape = Pool.out_shape(imval.shape, maxpoolshp, output_shape = Pool.out_shape(imval.shape, maxpoolshp,
ignore_border=ignore_border) ignore_border=ignore_border)
...@@ -245,9 +244,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -245,9 +244,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
"outshape is %s, calculated shape is %s" "outshape is %s, calculated shape is %s"
% (outputshp, numpy_output_val.shape)) % (outputshp, numpy_output_val.shape))
maxpool_op = \ maxpool_op = \
Pool(maxpoolshp, Pool(ignore_border=ignore_border, mode=mode)(images,
ignore_border=ignore_border, maxpoolshp, stride)
st=stride, mode=mode)(images)
f = function([images], maxpool_op) f = function([images], maxpool_op)
output_val = f(imval) output_val = f(imval)
utt.assert_allclose(output_val, numpy_output_val) utt.assert_allclose(output_val, numpy_output_val)
...@@ -286,9 +284,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -286,9 +284,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
"outshape is %s, calculated shape is %s" "outshape is %s, calculated shape is %s"
% (outputshp, numpy_output_val.shape)) % (outputshp, numpy_output_val.shape))
maxpool_op = \ maxpool_op = \
Pool(maxpoolshp, Pool(ignore_border=ignore_border, mode=mode)(images,
ignore_border=ignore_border, maxpoolshp, stride)
st=stride, mode=mode)(images)
f = function([images], maxpool_op) f = function([images], maxpool_op)
output_val = f(imval) output_val = f(imval)
utt.assert_allclose(output_val, numpy_output_val) utt.assert_allclose(output_val, numpy_output_val)
...@@ -315,10 +312,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -315,10 +312,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
numpy_output_val = self.numpy_max_pool_2d_stride_padding( numpy_output_val = self.numpy_max_pool_2d_stride_padding(
imval, maxpoolsize, ignore_border, imval, maxpoolsize, ignore_border,
stridesize, paddingsize, mode) stridesize, paddingsize, mode)
maxpool_op = Pool( maxpool_op = Pool(ignore_border=ignore_border, mode=mode)(images,
maxpoolsize, maxpoolsize, stridesize, paddingsize)
ignore_border=ignore_border,
st=stridesize, padding=paddingsize, mode=mode)(images)
f = function([images], maxpool_op) f = function([images], maxpool_op)
output_val = f(imval) output_val = f(imval)
utt.assert_allclose(output_val, numpy_output_val) utt.assert_allclose(output_val, numpy_output_val)
...@@ -340,12 +335,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -340,12 +335,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
paddingsize = paddingsizes[i] paddingsize = paddingsizes[i]
def mp(input): def mp(input):
return Pool( return Pool(ignore_border=True, mode=mode)(input,
maxpoolsize, ignore_border=True, maxpoolsize, stridesize, paddingsize)
st=stridesize,
padding=paddingsize,
mode=mode,
)(input)
utt.verify_grad(mp, [imval], rng=rng) utt.verify_grad(mp, [imval], rng=rng)
def test_DownsampleFactorMax_grad(self): def test_DownsampleFactorMax_grad(self):
...@@ -361,9 +352,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -361,9 +352,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
'average_inc_pad', 'average_inc_pad',
'average_exc_pad']): 'average_exc_pad']):
def mp(input): def mp(input):
return Pool(maxpoolshp, return Pool(ignore_border=ignore_border, mode=mode)(input,
ignore_border=ignore_border, maxpoolshp)
mode=mode)(input)
utt.verify_grad(mp, [imval], rng=rng) utt.verify_grad(mp, [imval], rng=rng)
def test_DownsampleFactorMax_grad_st(self): def test_DownsampleFactorMax_grad_st(self):
...@@ -381,9 +371,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -381,9 +371,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
'average_exc_pad'], 'average_exc_pad'],
stridesizes): stridesizes):
def mp(input): def mp(input):
return Pool(maxpoolshp, return Pool(ignore_border=ignore_border, mode=mode)(input,
ignore_border=ignore_border, maxpoolshp, stride)
st=stride, mode=mode)(input)
utt.verify_grad(mp, [imval], rng=rng) utt.verify_grad(mp, [imval], rng=rng)
def test_DownsampleFactorMax_grad_st_extra(self): def test_DownsampleFactorMax_grad_st_extra(self):
...@@ -404,10 +393,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -404,10 +393,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
maxpoolshp = maxpoolshps[indx] maxpoolshp = maxpoolshps[indx]
for ignore_border in [True, False]: for ignore_border in [True, False]:
def mp(input): def mp(input):
return Pool(maxpoolshp, return Pool(ignore_border=ignore_border, mode=mode)(
ignore_border=ignore_border, input, maxpoolshp, stride)
st=stride,
mode=mode)(input)
utt.verify_grad(mp, [imval], rng=rng) utt.verify_grad(mp, [imval], rng=rng)
def test_DownsampleFactorMaxGrad_grad(self): def test_DownsampleFactorMaxGrad_grad(self):
...@@ -426,11 +413,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -426,11 +413,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val = rng.rand(*grad_shape) * 10.0 grad_val = rng.rand(*grad_shape) * 10.0
def mp(input, grad): def mp(input, grad):
out = Pool( out = Pool(ignore_border=ignore_border)(input, maxpoolshp)
maxpoolshp, ignore_border=ignore_border)(input) grad_op = MaxPoolGrad(ignore_border=ignore_border)
grad_op = MaxPoolGrad( return grad_op(input, out, grad, maxpoolshp)
maxpoolshp, ignore_border=ignore_border)
return grad_op(input, out, grad)
utt.verify_grad(mp, [imval, grad_val], rng=rng) utt.verify_grad(mp, [imval, grad_val], rng=rng)
...@@ -451,9 +436,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -451,9 +436,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val = rng.rand(*grad_shape) * 10.0 grad_val = rng.rand(*grad_shape) * 10.0
def mp(input, grad): def mp(input, grad):
grad_op = AveragePoolGrad( grad_op = AveragePoolGrad(ignore_border=ignore_border,
avgpoolshp, ignore_border=ignore_border, mode=mode) mode=mode)
return grad_op(input, grad) return grad_op(input, grad, avgpoolshp)
utt.verify_grad(mp, [imval, grad_val], rng=rng) utt.verify_grad(mp, [imval, grad_val], rng=rng)
...@@ -474,13 +459,10 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -474,13 +459,10 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val = rng.rand(*grad_shape) grad_val = rng.rand(*grad_shape)
def mp(input, grad): def mp(input, grad):
out = Pool( out = Pool(ignore_border=ignore_border)(input,
maxpoolshp, ignore_border=ignore_border, maxpoolshp, stride)
st=stride)(input) grad_op = MaxPoolGrad(ignore_border=ignore_border)
grad_op = MaxPoolGrad( return grad_op(input, out, grad, maxpoolshp, stride)
maxpoolshp, ignore_border=ignore_border,
st=stride)
return grad_op(input, out, grad)
utt.verify_grad(mp, [imval, grad_val], rng=rng) utt.verify_grad(mp, [imval, grad_val], rng=rng)
...@@ -503,9 +485,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -503,9 +485,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
def mp(input, grad): def mp(input, grad):
grad_op = AveragePoolGrad( grad_op = AveragePoolGrad(
avgpoolshp, ignore_border=ignore_border, ignore_border=ignore_border, mode=mode)
st=stride, mode=mode) return grad_op(input, grad, avgpoolshp, stride)
return grad_op(input, grad)
utt.verify_grad(mp, [imval, grad_val], rng=rng) utt.verify_grad(mp, [imval, grad_val], rng=rng)
...@@ -531,13 +512,10 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -531,13 +512,10 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val = rng.rand(*grad_shape) grad_val = rng.rand(*grad_shape)
def mp(input, grad): def mp(input, grad):
out = Pool( out = Pool(ignore_border=ignore_border)(input, maxpoolshp,
maxpoolshp, ignore_border=ignore_border, stride)
st=stride)(input) grad_op = MaxPoolGrad(ignore_border=ignore_border)
grad_op = MaxPoolGrad( return grad_op(input, out, grad, maxpoolshp, stride)
maxpoolshp, ignore_border=ignore_border,
st=stride)
return grad_op(input, out, grad)
# skip the grad verification when the output is empty # skip the grad verification when the output is empty
if numpy.prod(grad_shape) == 0: if numpy.prod(grad_shape) == 0:
...@@ -567,10 +545,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -567,10 +545,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val = rng.rand(*grad_shape) grad_val = rng.rand(*grad_shape)
def mp(input, grad): def mp(input, grad):
grad_op = AveragePoolGrad( grad_op = AveragePoolGrad(ignore_border=ignore_border,
avgpoolshp, ignore_border=ignore_border, mode=mode)
st=stride, mode=mode) return grad_op(input, grad, avgpoolshp, stride)
return grad_op(input, grad)
# skip the grad verification when the output is empty # skip the grad verification when the output is empty
if numpy.prod(grad_shape) == 0: if numpy.prod(grad_shape) == 0:
...@@ -598,14 +575,11 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -598,14 +575,11 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val = rng.rand(*grad_shape) * 10.0 grad_val = rng.rand(*grad_shape) * 10.0
def mp(input, grad): def mp(input, grad):
out = Pool( out = Pool(ignore_border=True)(input, maxpoolsize, stridesize,
maxpoolsize, ignore_border=True, paddingsize)
st=stridesize, grad_op = MaxPoolGrad(ignore_border=True)
padding=paddingsize, return grad_op(input, out, grad, maxpoolsize, stridesize,
)(input) paddingsize)
grad_op = MaxPoolGrad(maxpoolsize, ignore_border=True,
st=stridesize, padding=paddingsize)
return grad_op(input, out, grad)
utt.verify_grad(mp, [imval, grad_val], rng=rng) utt.verify_grad(mp, [imval, grad_val], rng=rng)
def test_AveragePoolPaddingStride_grad_grad(self): def test_AveragePoolPaddingStride_grad_grad(self):
...@@ -630,10 +604,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -630,10 +604,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
grad_val = rng.rand(*grad_shape) * 10.0 grad_val = rng.rand(*grad_shape) * 10.0
def mp(input, grad): def mp(input, grad):
grad_op = AveragePoolGrad(avgpoolsize, ignore_border=True, grad_op = AveragePoolGrad(ignore_border=True, mode=mode)
st=stridesize, padding=paddingsize, return grad_op(input, grad, avgpoolsize, stridesize, paddingsize)
mode=mode)
return grad_op(input, grad)
utt.verify_grad(mp, [imval, grad_val], rng=rng) utt.verify_grad(mp, [imval, grad_val], rng=rng)
def test_DownsampleFactorMax_hessian(self): def test_DownsampleFactorMax_hessian(self):
...@@ -813,19 +785,18 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -813,19 +785,18 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
continue continue
# checking shapes generated by Pool # checking shapes generated by Pool
self._compile_and_check([image], self._compile_and_check([image],
[Pool(maxpoolshp, [Pool(ignore_border=ignore_border)
ignore_border=ignore_border, (image, maxpoolshp, pad=padding)],
padding=padding)(image)],
[image_val], Pool) [image_val], Pool)
# checking shapes generated by MaxPoolGrad # checking shapes generated by MaxPoolGrad
maxout_val = rng.rand(*out_shapes[k][i][j]) maxout_val = rng.rand(*out_shapes[k][i][j])
gz_val = rng.rand(*out_shapes[k][i][j]) gz_val = rng.rand(*out_shapes[k][i][j])
self._compile_and_check([image, maxout, gz], self._compile_and_check([image, maxout, gz],
[MaxPoolGrad(maxpoolshp, [MaxPoolGrad(
ignore_border=ignore_border, ignore_border=ignore_border)
padding=padding) (image, maxout, gz, maxpoolshp,
(image, maxout, gz)], pad=padding)],
[image_val, maxout_val, gz_val], [image_val, maxout_val, gz_val],
MaxPoolGrad, MaxPoolGrad,
warn=False) warn=False)
...@@ -835,9 +806,7 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -835,9 +806,7 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
image_val = rng.rand(4, 6, 1, 1) image_val = rng.rand(4, 6, 1, 1)
self._compile_and_check( self._compile_and_check(
[image], [image],
[Pool((2, 2), [Pool(ignore_border=True)(image, (2, 2), pad=(0, 0))],
ignore_border=True,
padding=(0, 0))(image)],
[image_val], Pool) [image_val], Pool)
def test_DownsampleFactorMaxGrad(self): def test_DownsampleFactorMaxGrad(self):
...@@ -847,9 +816,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester): ...@@ -847,9 +816,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
for mode in ['max', 'sum', 'average_inc_pad', 'average_exc_pad']: for mode in ['max', 'sum', 'average_inc_pad', 'average_exc_pad']:
f = theano.function([im, maxout, grad], f = theano.function([im, maxout, grad],
DownsampleFactorMaxGrad(ds=(3, 3), DownsampleFactorMaxGrad(ignore_border=False,
ignore_border=False, mode=mode)(im, maxout,
mode=mode)(im, maxout, grad), grad, ds),
on_unused_input='ignore') on_unused_input='ignore')
if mode == 'max': if mode == 'max':
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论