提交 d383d9c9 authored 作者: Frederic's avatar Frederic

finish average pool python code on the CPU.

上级 512c2c16
......@@ -720,7 +720,8 @@ class GpuDnnPoolDesc(GpuOp):
:param ws: windows size
:param stride: (dx, dy)
:param mode: 'max' or 'average'
:param mode: 'max', 'average_inc_pad' or 'average_exc_pad'
The old deprecated name 'average' correspond to 'average_inc_pad'
:param pad: (padX, padY) padding information.
padX is the size of the left and right borders,
padY is the size of the top and bottom borders.
......@@ -743,7 +744,9 @@ class GpuDnnPoolDesc(GpuOp):
return False
def __init__(self, ws=(1, 1), stride=(1, 1), mode='max', pad=(0, 0)):
assert mode in ('max', 'average')
if mode == 'average':
mode = 'average_inc_pad'
assert mode in ('max', 'average_inc_pad', 'average_exc_pad')
self.mode = mode
assert len(ws) == 2
self.ws = ws
......@@ -771,8 +774,12 @@ class GpuDnnPoolDesc(GpuOp):
if self.mode == 'max':
mode_flag = 'CUDNN_POOLING_MAX'
elif self.mode == "average":
elif self.mode == "average_inc_pad":
mode_flag = 'CUDNN_POOLING_AVERAGE_COUNT_INCLUDE_PADDING'
elif self.mode == "average_exc_pad":
mode_flag = 'CUDNN_POOLING_AVERAGE_COUNT_EXCLUDE_PADDING'
if version() == -1:
raise Exception("cudnn v1 do not support average_exc_pad")
else:
raise NotImplementedError("Unsupported pooling model.")
......@@ -1193,7 +1200,8 @@ def dnn_pool(img, ws, stride=(1, 1), mode='max', pad=(0, 0)):
:param img: images to do the pooling over
:param ws: subsampling window size
:param stride: subsampling stride (default: (1, 1))
:param mode: one of 'max', 'average' (default: 'max')
:param mode: one of 'max', 'average_inc_pad' or 'average_exc_pad
(default: 'max')
:param pad: (padX, padY) padding information.
padX is the size of the left and right borders,
padY is the size of the top and bottom borders.
......
......@@ -88,12 +88,12 @@ def test_pooling():
raise SkipTest(cuda.dnn.dnn_available.msg)
x = T.ftensor4()
for func, pad in product((T.max, T.mean),
for mode, pad in product(('max', 'average_inc_pad', 'average_exc_pad'),
((0, 0), (1, 0), (1, 0), (2, 3), (3, 2))):
if func is T.max:
mode = 'max'
if mode == 'max':
func = T.max
else:
mode = 'average'
func = T.mean
if pad != (0, 0) and cuda.dnn.version() == -1:
continue
......@@ -164,7 +164,7 @@ def test_pooling():
x, ws=(ws, ws),
stride=(stride, stride),
pad=pad,
mode='max' if func is T.max else "average")
mode=mode)
return dnn_op
theano.tests.unittest_tools.verify_grad(
fn, [data],
......@@ -427,7 +427,7 @@ class TestDnnInferShapes(utt.InferShapeTester):
for params in product(
[(1, 1), (2, 2), (3, 3)],
[(1, 1), (2, 2), (3, 3)],
['max', 'average']
['max', 'average_inc_pad', 'average_exc_pad']
):
desc = dnn.GpuDnnPoolDesc(
ws=params[0],
......@@ -463,7 +463,7 @@ class TestDnnInferShapes(utt.InferShapeTester):
for params in product(
[(1, 1), (2, 2), (3, 3)],
[(1, 1), (2, 2), (3, 3)],
['max', 'average']
['max', 'average_inc_pad']
):
desc = dnn.GpuDnnPoolDesc(
ws=params[0],
......
......@@ -63,7 +63,9 @@ def max_pool_2d(input, ds, ignore_border=False, st=None, padding=(0, 0),
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
:param mode: 'max' or 'average', the operation executed on each window.
:param mode: 'max', 'average_inc_pad' or 'average_exc_pad',
the operation executed on each window. The max always exclude the
padding in the computation of the max. For average, you have the choise.
:type mode: string
"""
if input.ndim < 2:
......@@ -185,8 +187,7 @@ class DownsampleFactorMax(Op):
def __init__(self, ds, ignore_border=False, st=None, padding=(0, 0),
mode='max'):
"""
:param ds: downsample factor over rows and column.
""":param ds: downsample factor over rows and column.
ds indicates the pool region size.
:type ds: list or tuple of two ints
......@@ -206,7 +207,9 @@ class DownsampleFactorMax(Op):
and pad_w is the size of the left and right margins.
:type padding: tuple of two ints
:param mode: 'max' or 'average'
:param mode: 'max', 'average_inc_pad', 'average_exc_pad'.
('average_inc_pad' exclude the padding from the count,
'average_exc_pad' include it)
"""
self.ds = tuple(ds)
......@@ -226,10 +229,10 @@ class DownsampleFactorMax(Op):
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']:
if mode not in ['max', 'average_inc_pad', 'average_exc_pad']:
raise ValueError(
"DownsampleFactorMax mode parameter only support 'max' and"
" 'average'. Got %s" % mode)
"DownsampleFactorMax mode parameter only support 'max',"
" 'average_inc_pad' and 'average_exc_pad'. Got %s" % mode)
self.mode = mode
def __str__(self):
......@@ -245,8 +248,6 @@ class DownsampleFactorMax(Op):
return gof.Apply(self, [x], [x.type()])
def perform(self, node, inp, out):
if self.mode != 'max' and self.padding != (0, 0):
raise NotImplementedError()
x, = inp
z, = out
if len(x.shape) != 4:
......@@ -267,18 +268,18 @@ class DownsampleFactorMax(Op):
pad_w = self.padding[1]
img_rows = x.shape[-2] + 2 * pad_h
img_cols = x.shape[-1] + 2 * pad_w
inc_pad = self.mode == 'average_inc_pad'
# pad the image
if self.padding != (0, 0):
fill = x.min()-1.
y = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype) + fill
dtype=x.dtype)
y[:, :, pad_h:(img_rows-pad_h), pad_w:(img_cols-pad_w)] = x
else:
y = x
func = numpy.max
if self.mode == 'average':
if self.mode != 'max':
func = numpy.average
# max pooling
for n in xrange(x.shape[0]):
......@@ -286,9 +287,16 @@ class DownsampleFactorMax(Op):
for r in xrange(pr):
row_st = r * st0
row_end = __builtin__.min(row_st + ds0, img_rows)
if not inc_pad:
row_st = __builtin__.max(row_st, self.padding[0])
row_end = __builtin__.min(row_end, x.shape[-2] + pad_h)
for c in xrange(pc):
col_st = c * st1
col_end = __builtin__.min(col_st + ds1, img_cols)
if not inc_pad:
col_st = __builtin__.max(col_st, self.padding[1])
col_end = __builtin__.min(col_end,
x.shape[-1] + pad_w)
zz[n, k, r, c] = func(y[
n, k, row_st:row_end, col_st:col_end])
......@@ -472,10 +480,10 @@ class DownsampleFactorMaxGrad(Op):
st = ds
self.st = tuple(st)
self.padding = tuple(padding)
if mode not in ['max', 'average']:
if mode not in ['max', 'average_inc_pad', 'average_exc_pad']:
raise ValueError(
"DownsampleFactorMax mode parameter only support 'max' and"
" 'average'. Got %s" % mode)
"DownsampleFactorMax mode parameter only support 'max',"
" 'average_inc_pad' and 'average_exc_pad'. Got %s" % mode)
self.mode = mode
def __str__(self):
......@@ -510,12 +518,13 @@ class DownsampleFactorMaxGrad(Op):
pad_w = self.padding[1]
img_rows = x.shape[-2] + 2 * pad_h
img_cols = x.shape[-1] + 2 * pad_w
inc_pad = self.mode == 'average_inc_pad'
# pad the image
if self.padding != (0, 0):
fill = x.min()-1
y = numpy.zeros(
(x.shape[0], x.shape[1], img_rows, img_cols),
dtype=x.dtype) + fill
dtype=x.dtype)
y[:, :, pad_h:(img_rows-pad_h), pad_w:(img_cols-pad_w)] = x
else:
y = x
......@@ -524,29 +533,34 @@ class DownsampleFactorMaxGrad(Op):
for n in xrange(x.shape[0]):
for k in xrange(x.shape[1]):
for r in xrange(pr):
row_st = r * st0
row_st = __builtin__.max(r * st0, self.padding[0])
row_end = __builtin__.min(row_st + ds0, img_rows)
for c in xrange(pc):
col_st = c * st1
col_st = __builtin__.max(c * st1, self.padding[1])
col_end = __builtin__.min(col_st + ds1, img_cols)
for row_ind in xrange(row_st, row_end):
for col_ind in xrange(col_st, col_end):
if (maxout[n, k, r, c] == y[n, k, row_ind, col_ind]):
gx[n, k, row_ind, col_ind] += gz[n, k, r, c]
elif self.mode == 'average':
else:
for n in xrange(x.shape[0]):
for k in xrange(x.shape[1]):
for r in xrange(pr):
row_st = r * st0
if inc_pad:
row_st = r * st0
else:
row_st = __builtin__.max(r * st0, self.padding[0])
row_end = __builtin__.min(row_st + ds0, img_rows)
for c in xrange(pc):
col_st = c * st1
if inc_pad:
col_st = c * st1
else:
col_st = __builtin__.max(c * st1,
self.padding[1])
col_end = __builtin__.min(col_st + ds1, img_cols)
val = gz[n, k, r, c] / ((row_end - row_st) *
(col_end - col_st))
gx[n, k, row_st:row_end, col_st:col_end] += val
else:
raise ValueError('mode %s not know' % self.mode)
# unpad the image
gx = gx[:, :, pad_h:(img_rows-pad_h), pad_w:(img_cols-pad_w)]
gx_stg[0] = gx
......
......@@ -33,7 +33,7 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
out_shp.append(input.shape[-1] / ds[1] + yi)
output_val = numpy.zeros(out_shp)
func = numpy.max
if mode == 'average':
if mode != 'max':
func = numpy.average
for k in numpy.ndindex(*input.shape[:-2]):
......@@ -47,7 +47,7 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
@staticmethod
def numpy_max_pool_2d_stride_padding(
x, ds, ignore_border=True, st=None, padding=(0, 0)):
x, ds, ignore_border=True, st=None, padding=(0, 0), mode='max'):
pad_h = padding[0]
pad_w = padding[1]
h = x.shape[-2]
......@@ -56,14 +56,12 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
assert ds[1] > pad_w
def pad_img(x):
fill = x.min()-1
t = numpy.ones((x.shape[0], x.shape[1], 1, 1))
ud_bar = (numpy.zeros((pad_h, w)) + fill)[
numpy.newaxis, numpy.newaxis, :, :] * t
lr_bar = (numpy.zeros((pad_h * 2 + h, pad_w)) + fill)[
numpy.newaxis, numpy.newaxis, :, :] * t
y = numpy.concatenate([ud_bar, x, ud_bar], axis=2)
y = numpy.concatenate([lr_bar, y, lr_bar], axis=3)
y = numpy.zeros(
(x.shape[0], x.shape[1],
x.shape[2]+pad_h*2, x.shape[3]+pad_w*2),
dtype=x.dtype)
y[:, :, pad_h:(x.shape[2]+pad_h), pad_w:(x.shape[3]+pad_w)] = x
return y
img_rows = h + 2 * pad_h
img_cols = w + 2 * pad_w
......@@ -77,15 +75,26 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
output_val = numpy.zeros(out_shp)
tt = []
y = pad_img(x)
func = numpy.max
if mode != 'max':
func = numpy.average
inc_pad = mode == 'average_inc_pad'
for k in numpy.ndindex(*x.shape[:-2]):
for i in range(output_val.shape[-2]):
ii_st = i * st[0]
ii_end = __builtin__.min(ii_st + ds[0], img_rows)
if not inc_pad:
ii_st = __builtin__.max(ii_st, pad_h)
ii_end = __builtin__.min(ii_end, h + pad_h)
for j in range(output_val.shape[-1]):
jj_st = j * st[1]
jj_end = __builtin__.min(jj_st + ds[1], img_cols)
if not inc_pad:
jj_st = __builtin__.max(jj_st, pad_w)
jj_end = __builtin__.min(jj_end, w + pad_w)
patch = y[k][ii_st:ii_end, jj_st:jj_end]
output_val[k][i, j] = numpy.max(patch)
output_val[k][i, j] = func(patch)
return output_val
@staticmethod
......@@ -136,7 +145,7 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
out_shp.append(out_c)
func = numpy.max
if mode == 'average':
if mode != 'max':
func = numpy.average
output_val = numpy.zeros(out_shp)
......@@ -159,7 +168,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
images = tensor.dtensor4()
for maxpoolshp, ignore_border, mode in product(maxpoolshps,
[True, False],
['max', 'average']):
['max',
'average_inc_pad',
'average_exc_pad']):
# print 'maxpoolshp =', maxpoolshp
# print 'ignore_border =', ignore_border
......@@ -193,15 +204,13 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
(4, 10, 14, 14), (4, 10, 6, 6), (4, 10, 4, 3),
(4, 10, 12, 14), (4, 10, 4, 5), (4, 10, 3, 2),
(4, 10, 12, 14), (4, 10, 5, 6), (4, 10, 4, 3))
outputshps += ((4, 10, 16, 16), (4, 10, 6, 6), (4, 10, 4, 3),
(4, 10, 16, 16), (4, 10, 6, 6), (4, 10, 4, 3),
(4, 10, 14, 14), (4, 10, 5, 5), (4, 10, 3, 2),
(4, 10, 14, 14), (4, 10, 6, 6), (4, 10, 4, 3),
(4, 10, 12, 14), (4, 10, 4, 5), (4, 10, 3, 2),
(4, 10, 12, 14), (4, 10, 5, 6), (4, 10, 4, 3))
# The same for each mode
outputshps = outputshps + outputshps + outputshps
images = tensor.dtensor4()
indx = 0
for mode, maxpoolshp, ignore_border in product(['max', 'average'],
for mode, maxpoolshp, ignore_border in product(['max',
'average_inc_pad',
'average_exc_pad'],
maxpoolshps,
[True, False]):
for stride in stridesizes:
......@@ -242,7 +251,8 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
stride = stridesizes[indx]
maxpoolshp = maxpoolshps[indx]
for ignore_border, mode in product([True, False],
['max', 'average']):
['max', 'average_inc_pad',
'average_exc_pad']):
indx_out = indx * 2
if not ignore_border:
indx_out += 1
......@@ -270,20 +280,24 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
paddingsizes = [(2, 2), (1, 2), (2, 1), (0, 0), (1, 1)]
imgsizes = [(5, 5), (5, 5), (5, 6), (6, 5), (5, 5)]
m = 4 # minibatch
c = 10 # channel size
c = 2 # channel size
images = tensor.dtensor4()
for indx in numpy.arange(len(maxpoolsizes)):
for indx, mode in product(numpy.arange(len(maxpoolsizes)),
['max', 'average_inc_pad',
'average_exc_pad']):
imgsize = imgsizes[indx]
imval = rng.rand(m, c, imgsize[0], imgsize[1])
imval = rng.rand(m, c, imgsize[0], imgsize[1]) - 0.5
stridesize = stridesizes[indx]
maxpoolsize = maxpoolsizes[indx]
paddingsize = paddingsizes[indx]
numpy_output_val = self.numpy_max_pool_2d_stride_padding(
imval, maxpoolsize, ignore_border, stridesize, paddingsize)
imval, maxpoolsize, ignore_border,
stridesize, paddingsize, mode)
maxpool_op = DownsampleFactorMax(
maxpoolsize,
ignore_border=ignore_border,
st=stridesize, padding=paddingsize)(images)
st=stridesize, padding=paddingsize, mode=mode)(images)
f = function([images], maxpool_op)
output_val = f(imval)
utt.assert_allclose(output_val, numpy_output_val)
......@@ -300,7 +314,7 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
maxpoolsize = maxpoolsizes[i]
stridesize = stridesizes[i]
paddingsize = paddingsizes[i]
def mp(input):
return DownsampleFactorMax(
maxpoolsize, ignore_border=True,
......@@ -472,7 +486,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
for maxpoolshp, ignore_border, mode in product(maxpoolshps,
[True, False],
['max', 'average']):
['max',
'average_inc_pad',
'average_exc_pad']):
# print 'maxpoolshp =', maxpoolshp
# print 'ignore_border =', ignore_border
numpy_output_val = self.numpy_max_pool_2d(imval, maxpoolshp,
......@@ -521,7 +537,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
for maxpoolshp, ignore_border, mode in product(maxpoolshps,
[True, False],
['max', 'average']):
['max',
'average_inc_pad',
'average_exc_pad']):
# print 'maxpoolshp =', maxpoolshp
# print 'ignore_border =', ignore_border
numpy_output_val = self.numpy_max_pool_2d(imval, maxpoolshp,
......@@ -556,7 +574,9 @@ class TestDownsampleFactorMax(utt.InferShapeTester):
for maxpoolshp, ignore_border, mode in product(maxpoolshps,
[True, False],
['max', 'average']):
['max',
'average_inc_pad',
'average_exc_pad']):
# print 'maxpoolshp =', maxpoolshp
# print 'ignore_border =', ignore_border
numpy_output_val = self.numpy_max_pool_2d(imval, maxpoolshp,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论