From 679ba1060c2ae8fa05197f7ce63c93d0c84c5a97 Mon Sep 17 00:00:00 2001 From: Sina Honari Date: Wed, 19 Nov 2014 11:39:23 -0500 Subject: [PATCH] fixing the stride computation case and adding test cases for issue #2196 --- theano/tensor/signal/downsample.py | 48 +++++++--- theano/tensor/signal/tests/test_downsample.py | 95 ++++++++++++++++--- 2 files changed, 115 insertions(+), 28 deletions(-) diff --git a/theano/tensor/signal/downsample.py b/theano/tensor/signal/downsample.py index d6d0d2864f9..602a4d9ccfe 100644 --- a/theano/tensor/signal/downsample.py +++ b/theano/tensor/signal/downsample.py @@ -102,23 +102,43 @@ def out_shape(imgshape, ds, ignore_border=False, st=None): st = ds r, c = imgshape[-2:] - nr = (r - ds[0]) // st[0] + 1 - nc = (c - ds[1]) // st[1] + 1 - - rval = list(imgshape[:-2]) + [nr, nc] - + out_r = (r - ds[0]) // st[0] + 1 + out_c = (c - ds[1]) // st[1] + 1 + nr = 0 + nc = 0 + if isinstance(r, theano.Variable): + nr = tensor.switch(tensor.ge(r - ds[0], 0), out_r, 0) + elif r - ds[0] >= 0: + nr = out_r + if isinstance(c, theano.Variable): + nr = tensor.switch(tensor.ge(c - ds[1], 0), out_c, 0) + elif c - ds[1] >= 0: + nc = out_c + + out_re = 0 + out_ce = 0 if not ignore_border: + re = r - ((out_r - 1) * st[0] + ds[0]) + rr = r - out_r * st[0] + ce = c - ((out_c - 1) * st[1] + ds[1]) + cr = c - out_c * st[1] if isinstance(r, theano.Variable): - rr = r % st[0] - rval[-2] = tensor.switch(tensor.and_((rr % ds[0]), tensor.eq(rr // ds[0], 0)), rval[-2] + 1, rval[-2]) - elif (r % st[0]) % ds[0]: - rval[-2] += 1 + out_re = tensor.switch(tensor.gt(nr, 0), tensor.switch(tensor.gt(re, 0), tensor.switch(tensor.gt(rr, 0), 1, 0), 0), tensor.switch(tensor.gt(r, 0), 1, 0)) + elif nr > 0: + if re > 0 and rr > 0: + out_re = 1 + elif r > 0: + out_re = 1 if isinstance(c, theano.Variable): - cr = c % st[1] - crn = cr - ds[1] - rval[-1] = tensor.switch(tensor.lt(crn, 0), rval[-1] + 1, rval[-1]) - elif (c % st[1]) % ds[1]: - rval[-1] += 1 + out_ce = tensor.switch(tensor.gt(nc, 0), tensor.switch(tensor.gt(ce, 0), tensor.switch(tensor.gt(cr, 0), 1, 0), 0), tensor.switch(tensor.gt(c, 0), 1, 0)) + elif nc > 0: + if ce > 0 and cr > 0: + out_ce = 1 + elif c > 0: + out_ce = 1 + nr += out_re + nc += out_ce + rval = list(imgshape[:-2]) + [nr, nc] return rval def __init__(self, ds, ignore_border=False, st=None): diff --git a/theano/tensor/signal/tests/test_downsample.py b/theano/tensor/signal/tests/test_downsample.py index 8aa2dbb51fa..0a2b25eb4d7 100644 --- a/theano/tensor/signal/tests/test_downsample.py +++ b/theano/tensor/signal/tests/test_downsample.py @@ -55,20 +55,37 @@ def numpy_max_pool_2d_stride(input, ds, ignore_border=False, st=None): img_rows = input.shape[-2] img_cols = input.shape[-1] + out_r = 0 + out_c = 0 + if img_rows - ds[0] >= 0: + out_r = (img_rows - ds[0]) // st[0] + 1 + if img_cols - ds[1] >= 0: + out_c = (img_cols - ds[1]) // st[1] + 1 + if not ignore_border: - rr = (img_rows) % st[0] - cr = (img_cols) % st[1] - if rr > 0 and rr < ds[0]: - xi += 1 - if cr > 0 and cr < ds[1]: - yi += 1 + if out_r > 0: + if img_rows - ((out_r - 1) * st[0] + ds[0]) > 0 : + rr = img_rows - out_r * st[0] + if rr > 0: + out_r += 1 + else: + if img_rows > 0: + out_r += 1 + + if out_c > 0: + if img_cols - ((out_c - 1) * st[1] + ds[1]) > 0 : + cr = img_cols - out_c * st[1] + if cr > 0: + out_c +=1 + else: + if img_cols > 0: + out_c += 1 out_shp = list(input.shape[:-2]) - out_shp.append((img_rows - ds[0]) / st[0] + 1 + xi) - out_shp.append((img_cols - ds[1]) / st[1] + 1 + yi) - - output_val = numpy.zeros(out_shp) + out_shp.append(out_r) + out_shp.append(out_c) + output_val = numpy.zeros(out_shp) for k in numpy.ndindex(*input.shape[:-2]): for i in range(output_val.shape[-2]): ii_st = i * st[0] @@ -109,15 +126,22 @@ def test_DownsampleFactorMax(self): def test_DownsampleFactorMaxStride(self): rng = numpy.random.RandomState(utt.fetch_seed()) + maxpoolshps = ((1, 1), (3, 3), (5, 3)) + stridesizes = ((1, 1), (3, 3), (5, 7)) # generate random images - maxpoolshps = ((1, 1), (2, 2), (3, 3), (2, 3)) - stridesizes = ((1, 1), (2, 2), (3, 1), (2, 5), (5, 7)) - imval = rng.rand(4, 10, 64, 64) + imval = rng.rand(4, 10, 16, 16) + 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)) images = tensor.dtensor4() - + indx = 0 for maxpoolshp in maxpoolshps: for ignore_border in [True, False]: for stride in stridesizes: + outputshp = outputshps[indx] + indx += 1 print 'maxpoolshp =', maxpoolshp print 'ignore_border =', ignore_border print 'stride =', stride @@ -125,12 +149,55 @@ def test_DownsampleFactorMaxStride(self): #DownsampleFactorMax op numpy_output_val = self.numpy_max_pool_2d_stride(imval, maxpoolshp, ignore_border, stride) + print "outshape is %s " %(outputshp, ) + print "calculated shape is %s " %(numpy_output_val.shape,) + assert numpy_output_val.shape == outputshp maxpool_op = DownsampleFactorMax(maxpoolshp, ignore_border=ignore_border, st=stride)(images) f = function([images], maxpool_op) output_val = f(imval) + print "numpy_output_val shape is %s" %(numpy_output_val.shape,) assert (numpy.abs(output_val - numpy_output_val) < 1e-5).all() + def test_DownsampleFactorMaxStrideExtra(self): + rng = numpy.random.RandomState(utt.fetch_seed()) + maxpoolshps = ((5, 3), (5, 3), (5, 3), (5, 5), (3, 2), (7, 7), (9, 9)) + stridesizes = ((3, 2), (7, 5), (10, 6), (1, 1), (2, 3), (10, 10), (1, 1)) + imvsizs = ((16, 16), (16, 16), (16, 16), (8, 5), (8, 5), (8, 5), (8, 5)) + outputshps = ((4, 10, 4, 7), (4, 10, 5, 8), (4, 10, 2, 3), (4, 10, 3, 4), \ + (4, 10, 2, 3), (4, 10, 2, 3), (4, 10, 4, 1), (4, 10, 4, 1), \ + (4, 10, 3, 2), (4, 10, 4, 2), (4, 10, 1, 0), (4, 10, 1, 1), \ + (4, 10, 0, 0), (4, 10, 1, 1)) + images = tensor.dtensor4() + indx = 0 + for indx in numpy.arange(len(maxpoolshps)): + imvsize = imvsizs[indx] + imval = rng.rand(4, 10 , imvsize[0], imvsize[1]) + stride = stridesizes[indx] + maxpoolshp = maxpoolshps[indx] + for ignore_border in [True, False]: + indx_out = indx * 2 + if not ignore_border: + indx_out += 1 + outputshp = outputshps[indx_out] + print 'maxpoolshp =', maxpoolshp + print 'ignore_border =', ignore_border + print 'stride =', stride + + #DownsampleFactorMax op + numpy_output_val = self.numpy_max_pool_2d_stride(imval, maxpoolshp, + ignore_border, stride) + print "outshape is %s " %(outputshp, ) + print "calculated shape is %s " %(numpy_output_val.shape,) + assert numpy_output_val.shape == outputshp + maxpool_op = DownsampleFactorMax(maxpoolshp, + ignore_border=ignore_border, st=stride)(images) + f = function([images], maxpool_op) + output_val = f(imval) + print "numpy_output_val shape is %s" %(numpy_output_val.shape,) + print "output_val shape is %s " %(output_val.shape,) + assert (numpy.abs(output_val - numpy_output_val) < 1e-5).all() + def test_DownsampleFactorMax_grad(self): rng = numpy.random.RandomState(utt.fetch_seed()) maxpoolshps = ((1, 1), (3, 2), (2, 3))