Skip to content

Commit

Permalink
Fix SAME padding calc when stride>ksize (#1991)
Browse files Browse the repository at this point in the history
Adds a failing test case for conv2d ksize=1, stride=2, padding=same,
input=4x4

Adds tests convering that case for pooling ops too.

There's one test case I found that fails in a different way that
I left commented out with R=C=8, K=2, S=4. The error is:
F tensorflow/stream_executor/cuda/cuda_dnn.cc:483] could not set cudnn convolution descriptor: CUDNN_STATUS_BAD_PARAM
  • Loading branch information
ry authored and Vijay Vasudevan committed Apr 19, 2016
1 parent 0a37c9f commit cf7ce8a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 21 deletions.
10 changes: 4 additions & 6 deletions tensorflow/core/kernels/ops_util.cc
Expand Up @@ -54,16 +54,14 @@ Status Get2dOutputSizeVerbose(const int in_height, const int in_width,
*new_width = ceil(in_width / static_cast<float>(col_stride)); *new_width = ceil(in_width / static_cast<float>(col_stride));
// Calculate padding for top/bottom/left/right, spilling any excess // Calculate padding for top/bottom/left/right, spilling any excess
// padding to bottom and right. // padding to bottom and right.
const int pad_needed_height = const int pad_needed_height = std::max(0,
(*new_height - 1) * row_stride + filter_height - in_height; (*new_height - 1) * row_stride + filter_height - in_height);
*pad_top = pad_needed_height / 2; *pad_top = pad_needed_height / 2;
CHECK_GE(pad_needed_height, 0);
*pad_bottom = pad_needed_height - *pad_top; *pad_bottom = pad_needed_height - *pad_top;


const int pad_needed_width = const int pad_needed_width = std::max(0,
(*new_width - 1) * col_stride + filter_width - in_width; (*new_width - 1) * col_stride + filter_width - in_width);
*pad_left = pad_needed_width / 2; *pad_left = pad_needed_width / 2;
CHECK_GE(pad_needed_width, 0);
*pad_right = pad_needed_width - *pad_left; *pad_right = pad_needed_width - *pad_left;
break; break;
} }
Expand Down
19 changes: 17 additions & 2 deletions tensorflow/python/kernel_tests/conv_ops_test.py
Expand Up @@ -327,11 +327,26 @@ def testConv2DKernelSmallerThanStrideValid(self):
expected=expected_output) expected=expected_output)


def testConv2DKernelSmallerThanStrideSame(self): def testConv2DKernelSmallerThanStrideSame(self):
expected_output = [1, 3, 7, 9]
self._VerifyValues(tensor_in_sizes=[1, 3, 3, 1], self._VerifyValues(tensor_in_sizes=[1, 3, 3, 1],
filter_in_sizes=[1, 1, 1, 1], filter_in_sizes=[1, 1, 1, 1],
strides=[2, 2], padding="SAME", strides=[2, 2], padding="SAME",
expected=expected_output) expected=[1, 3, 7, 9])

self._VerifyValues(tensor_in_sizes=[1, 4, 4, 1],
filter_in_sizes=[1, 1, 1, 1],
strides=[2, 2], padding="SAME",
expected=[1, 3, 9, 11])

self._VerifyValues(tensor_in_sizes=[1, 4, 4, 1],
filter_in_sizes=[2, 2, 1, 1],
strides=[3, 3], padding="SAME",
expected=[44, 28, 41, 16])

# TODO this currently fails.
#self._VerifyValues(tensor_in_sizes=[1, 8, 8, 1],
# filter_in_sizes=[2, 2, 1, 1],
# strides=[4, 4], padding="SAME",
# expected=[72, 112, 392, 432])


# Testing for backprops # Testing for backprops
def _RunAndVerifyBackpropInput(self, input_sizes, filter_sizes, output_sizes, def _RunAndVerifyBackpropInput(self, input_sizes, filter_sizes, output_sizes,
Expand Down
29 changes: 16 additions & 13 deletions tensorflow/python/kernel_tests/pooling_ops_test.py
Expand Up @@ -370,32 +370,35 @@ def testDepthwiseMaxPool2x2DepthWindow3(self):
expected=[3.0, 6.0, 9.0, 12.0, 15.0, 18.0, 21.0, 24.0], expected=[3.0, 6.0, 9.0, 12.0, 15.0, 18.0, 21.0, 24.0],
use_gpu=False) use_gpu=False)


def testKernelSmallerThanStride(self): def testKernelSmallerThanStrideValid(self):
for use_gpu in [True, False]: for use_gpu in [True, False]:
self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 3, 3, 1],
ksize=[1, 1, 1, 1], strides=[1, 2, 2, 1],
padding="SAME",
expected=[1, 3, 7, 9],
use_gpu=use_gpu)

self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 7, 7, 1], self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 7, 7, 1],
ksize=[1, 2, 2, 1], strides=[1, 3, 3, 1], ksize=[1, 2, 2, 1], strides=[1, 3, 3, 1],
padding="VALID", padding="VALID",
expected=[9, 12, 30, 33], expected=[9, 12, 30, 33],
use_gpu=use_gpu) use_gpu=use_gpu)


self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 3, 3, 1],
ksize=[1, 1, 1, 1], strides=[1, 2, 2, 1],
padding="SAME",
expected=[1, 3, 7, 9],
use_gpu=use_gpu)

self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 7, 7, 1], self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 7, 7, 1],
ksize=[1, 2, 2, 1], strides=[1, 3, 3, 1], ksize=[1, 2, 2, 1], strides=[1, 3, 3, 1],
padding="VALID", padding="VALID",
expected=[5, 8, 26, 29], expected=[5, 8, 26, 29],
use_gpu=use_gpu) use_gpu=use_gpu)


def testKernelSmallerThanStrideSame(self):
for use_gpu in [True, False]:
for pool_func in [tf.nn.max_pool, tf.nn.avg_pool]:
self._VerifyValues(pool_func, input_sizes=[1, 3, 3, 1],
ksize=[1, 1, 1, 1], strides=[1, 2, 2, 1],
padding="SAME",
expected=[1, 3, 7, 9],
use_gpu=use_gpu)

self._VerifyValues(pool_func, input_sizes=[1, 4, 4, 1],
ksize=[1, 1, 1, 1], strides=[1, 2, 2, 1],
padding="SAME",
expected=[1, 3, 9, 11],
use_gpu=use_gpu)



def _testDepthwiseMaxPoolInvalidConfig(self, in_size, ksize, strides, def _testDepthwiseMaxPoolInvalidConfig(self, in_size, ksize, strides,
error_msg, use_gpu=False): error_msg, use_gpu=False):
Expand Down

0 comments on commit cf7ce8a

Please sign in to comment.