Home | History | Annotate | Download | only in kernel_tests
      1 # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 # ==============================================================================
     15 """Functional tests for pooling operations."""
     16 
     17 from __future__ import absolute_import
     18 from __future__ import division
     19 from __future__ import print_function
     20 
     21 import os
     22 import numpy as np
     23 
     24 from tensorflow.python.framework import constant_op
     25 from tensorflow.python.framework import dtypes
     26 from tensorflow.python.framework import errors_impl
     27 from tensorflow.python.framework import test_util
     28 from tensorflow.python.ops import array_ops
     29 from tensorflow.python.ops import gen_array_ops
     30 from tensorflow.python.ops import gen_nn_ops
     31 from tensorflow.python.ops import gradient_checker
     32 from tensorflow.python.ops import gradients_impl
     33 from tensorflow.python.ops import nn_ops
     34 import tensorflow.python.ops.nn_grad  # pylint: disable=unused-import
     35 from tensorflow.python.platform import test
     36 from tensorflow.python.platform import tf_logging
     37 
     38 
     39 def GetTestConfigs(include_nchw_vect_c=False):
     40   """Get all the valid tests configs to run.
     41 
     42   Args:
     43     include_nchw_vect_c: Whether to include NCHW_VECT_C in the test configs.
     44 
     45   Returns:
     46     all the valid test configs as tuples of data_format and use_gpu.
     47   """
     48   test_configs = [("NHWC", False), ("NHWC", True)]
     49   if not test.is_gpu_available(cuda_only=True):
     50     tf_logging.info("NCHW and NCHW_VECT_C tests skipped because not run with "
     51                     "--config=cuda or no GPUs available.")
     52     return test_configs
     53   # "NCHW" format is currently supported exclusively on CUDA GPUs.
     54   test_configs += [("NCHW", True)]
     55   if include_nchw_vect_c:
     56     if test.is_gpu_available(
     57         cuda_only=True, min_cuda_compute_capability=(6, 1)):
     58       test_configs += [("NCHW_VECT_C", True)]
     59     else:
     60       tf_logging.info("NCHW_VECT_C test skipped because no GPUs with "
     61                       "compute capability >= 6.1 are available.")
     62 
     63   return test_configs
     64 
     65 
     66 def GetShrunkInceptionMaxPoolShapes(shrink=30):
     67   """Iterator for some of the max pool ops in the Inception 2015 model.
     68 
     69   Args:
     70     shrink: Factor to shrink depth relative to Inception.
     71 
     72   Yields:
     73     Tuple (name, input_size, filter_size, out_size, strides, padding)
     74   """
     75   names = ["maxpool2", "maxpool3", "maxpool4", "maxpool5"]
     76   input_sizes = [[32, 71, 71, 192], [32, 35, 35, 288], [32, 17, 17, 1248],
     77                  [32, 8, 8, 2048]]
     78   filter_sizes = [[1, 3, 3, 1], [1, 3, 3, 1], [1, 3, 3, 1], [1, 3, 3, 1]]
     79   output_sizes = [[32, 35, 35, 192], [32, 17, 17, 288], [32, 8, 8, 1248],
     80                   [32, 8, 8, 2048]]
     81   strides = [[1, 2, 2, 1], [1, 2, 2, 1], [1, 2, 2, 1], [1, 1, 1, 1]]
     82   # Shrink each depth value
     83   for i in input_sizes:
     84     i[3] //= shrink
     85   for o in output_sizes:
     86     o[3] //= shrink
     87   paddings = ["VALID", "VALID", "VALID", "SAME"]
     88   for n, i, f, o, s, p in zip(names, input_sizes, filter_sizes, output_sizes,
     89                               strides, paddings):
     90     yield n, i, f, o, s, p
     91 
     92 
     93 class PoolingTest(test.TestCase):
     94 
     95   def _VerifyOneType(self, pool_func, input_sizes, ksize, strides, padding,
     96                      data_format, data_type, expected, use_gpu, v2):
     97     """Verifies the output values of the pooling function.
     98 
     99     Args:
    100       pool_func: Function to be called, co.MaxPool, co.AvgPool,
    101         or the Lua version.
    102       input_sizes: Input tensor dimensions.
    103       ksize: The kernel size dimensions
    104       strides: The stride dimensions
    105       padding: Padding type.
    106       data_format: The data format we use to run the pooling operation.
    107       data_type: The data type to use to run the pooling operation.
    108       expected: An array containing the expected operation outputs.
    109       use_gpu: Whether we are running on GPU.
    110     """
    111     total_size = 1
    112     for s in input_sizes:
    113       total_size *= s
    114     if v2 and data_format != "NHWC":
    115       tf_logging.info("v2 not supported for %s", data_format)
    116       return
    117     if data_format == "NCHW_VECT_C":
    118       if data_type != dtypes.float32:
    119         tf_logging.info("quantization to qint8 not implemented for %r",
    120                         data_type)
    121         return
    122       if input_sizes[-1] % 4 != 0:
    123         tf_logging.info("Skipping test for depth %d", input_sizes[-1])
    124         return
    125     tf_logging.info("Running %s test. %r %r %d %r %r %r", data_format, v2,
    126                     input_sizes, total_size, pool_func, ksize, strides)
    127     # Initializes the input tensor with array containing incrementing
    128     # numbers from 1, wrapping round to -127 after 127 to support int8.
    129     x = [((f + 128) % 255) - 127 for f in range(total_size)]
    130     with self.test_session(use_gpu=use_gpu):
    131       t = constant_op.constant(x, shape=input_sizes, dtype=data_type)
    132       if data_format in ("NCHW", "NCHW_VECT_C"):
    133         if data_format == "NCHW_VECT_C":
    134           t = test_util.NHWCToNCHW_VECT_C(t)
    135           t, _, _ = gen_array_ops.quantize_v2(t, -128.0, 127.0, dtypes.qint8)
    136         else:
    137           t = test_util.NHWCToNCHW(t)
    138         ksize = test_util.NHWCToNCHW(ksize)
    139         strides = test_util.NHWCToNCHW(strides)
    140       ksize_placeholder = array_ops.placeholder(dtypes.int32, shape=[4])
    141       strides_placeholder = array_ops.placeholder(dtypes.int32, shape=[4])
    142       if v2:
    143         t = pool_func(
    144             t,
    145             ksize=ksize_placeholder,
    146             strides=strides_placeholder,
    147             padding=padding,
    148             data_format=data_format)
    149       else:
    150         t = pool_func(
    151             t,
    152             ksize=ksize,
    153             strides=strides,
    154             padding=padding,
    155             data_format=data_format)
    156       if data_format == "NCHW_VECT_C":
    157         t = gen_array_ops.dequantize(t, -128, 127)
    158         t = test_util.NCHW_VECT_CToNHWC(t)
    159       elif data_format == "NCHW":
    160         t = test_util.NCHWToNHWC(t)
    161       if v2:
    162         actual = t.eval(feed_dict={
    163             ksize_placeholder: ksize,
    164             strides_placeholder: strides
    165         })
    166       else:
    167         actual = t.eval()
    168         self.assertShapeEqual(actual, t)
    169       self.assertAllCloseAccordingToType(expected, actual.flatten())
    170 
    171   def _VerifyOneTest(self, pool_func, input_sizes, ksize, strides, padding,
    172                      data_format, expected, use_gpu, v2):
    173     """Verifies the output values of the pooling function.
    174 
    175     Args:
    176       pool_func: Function to be called, co.MaxPool, co.AvgPool,
    177         or the Lua version.
    178       input_sizes: Input tensor dimensions.
    179       ksize: The kernel size dimensions
    180       strides: The stride dimensions
    181       padding: Padding type.
    182       data_format: The data format we use to run the pooling operation.
    183       expected: An array containing the expected operation outputs.
    184       use_gpu: Whether we are running on GPU.
    185     """
    186     if data_format == "NCHW_VECT_C":
    187       avg_pool_func = nn_ops.avg_pool
    188       tf_logging.info("pool_func=%s", pool_func)
    189       if pool_func == avg_pool_func:
    190         tf_logging.info("NCHW_VECT_C not yet implemented for avg_pool")
    191         return
    192 
    193     self._VerifyOneType(pool_func, input_sizes, ksize, strides, padding,
    194                         data_format, dtypes.float32, expected, use_gpu, v2)
    195 
    196     if not use_gpu or test_util.CudaSupportsHalfMatMulAndConv():
    197       self._VerifyOneType(pool_func, input_sizes, ksize, strides, padding,
    198                           data_format, dtypes.float16, expected, use_gpu, v2)
    199 
    200   def _VerifyValues(self,
    201                     pool_func,
    202                     input_sizes,
    203                     ksize,
    204                     strides,
    205                     padding,
    206                     expected,
    207                     use_gpu,
    208                     v2=False):
    209     """Verifies the output values of the pooling function.
    210 
    211     Args:
    212       pool_func: Function to be called, co.MaxPool, co.AvgPool,
    213         or the Lua version.
    214       input_sizes: Input tensor dimensions.
    215       ksize: The kernel size dimensions
    216       strides: The stride dimensions
    217       padding: Padding type.
    218       expected: An array containing the expected operation outputs.
    219       use_gpu: Whether we are running on GPU.
    220     """
    221     for (data_format, use_gpu_2) in GetTestConfigs(True):
    222       if use_gpu_2 == use_gpu:
    223         self._VerifyOneTest(pool_func, input_sizes, ksize, strides, padding,
    224                             data_format, expected, use_gpu, v2)
    225 
    226   def _testAvgPoolValidPadding(self, use_gpu):
    227     expected_output = [7.0, 8.0, 9.0]
    228     self._VerifyValues(
    229         nn_ops.avg_pool,
    230         input_sizes=[1, 3, 3, 3],
    231         ksize=[1, 2, 2, 1],
    232         strides=[1, 2, 2, 1],
    233         padding="VALID",
    234         expected=expected_output,
    235         use_gpu=use_gpu)
    236 
    237   def _testAvgPoolSamePadding(self, use_gpu):
    238     expected_output = [8.5, 9.5, 10.5, 14.5, 15.5, 16.5]
    239     self._VerifyValues(
    240         nn_ops.avg_pool,
    241         input_sizes=[1, 2, 4, 3],
    242         ksize=[1, 2, 2, 1],
    243         strides=[1, 2, 2, 1],
    244         padding="SAME",
    245         expected=expected_output,
    246         use_gpu=use_gpu)
    247 
    248   def _testAvgPoolSamePaddingNonSquareWindow(self, use_gpu):
    249     # input is:
    250     # [1.0, 2.0
    251     #  3.0  4.0]
    252     #
    253     # Window of [x, x] should do:
    254     #  [avg(1.0, 2.0), avg(2.0, padded0),
    255     #   avg(3.0, 4.0), avg(4.0, padded0)]
    256     self._VerifyValues(
    257         nn_ops.avg_pool,
    258         input_sizes=[1, 2, 2, 1],
    259         ksize=[1, 1, 2, 1],
    260         strides=[1, 1, 1, 1],
    261         padding="SAME",
    262         expected=[1.5, 2.0, 3.5, 4.0],
    263         use_gpu=use_gpu)
    264 
    265     # Window of [x,
    266     #            x] should do:
    267     #  [avg(1.0, 3.0), avg(2.0, 4.0)
    268     #   avg(3.0, padded0), avg(4.0, padded0)]
    269     self._VerifyValues(
    270         nn_ops.avg_pool,
    271         input_sizes=[1, 2, 2, 1],
    272         ksize=[1, 2, 1, 1],
    273         strides=[1, 1, 1, 1],
    274         padding="SAME",
    275         expected=[2.0, 3.0, 3.0, 4.0],
    276         use_gpu=use_gpu)
    277 
    278   def _testAvgPoolSamePaddingNonSquareWindowMultiBatch(self, use_gpu):
    279     self._VerifyValues(
    280         nn_ops.avg_pool,
    281         input_sizes=[2, 2, 2, 2],
    282         ksize=[1, 1, 2, 1],
    283         strides=[1, 1, 1, 1],
    284         padding="SAME",
    285         expected=[
    286             2.0, 3.0, 3.0, 4.0, 6.0, 7.0, 7.0, 8.0, 10.0, 11.0, 11.0, 12.0,
    287             14.0, 15.0, 15.0, 16.0
    288         ],
    289         use_gpu=use_gpu)
    290     self._VerifyValues(
    291         nn_ops.avg_pool,
    292         input_sizes=[2, 2, 2, 2],
    293         ksize=[1, 2, 1, 1],
    294         strides=[1, 1, 1, 1],
    295         padding="SAME",
    296         expected=[
    297             3.0, 4.0, 5.0, 6.0, 5.0, 6.0, 7.0, 8.0, 11.0, 12.0, 13.0, 14.0,
    298             13.0, 14.0, 15.0, 16.0
    299         ],
    300         use_gpu=use_gpu)
    301 
    302   def _testAvgPoolValidPaddingUnevenStride(self, use_gpu):
    303     self._VerifyValues(
    304         nn_ops.avg_pool,
    305         input_sizes=[1, 3, 3, 3],
    306         ksize=[1, 2, 2, 1],
    307         strides=[1, 1, 2, 1],
    308         padding="VALID",
    309         expected=[7.0, 8.0, 9.0, 16.0, 17.0, 18.0],
    310         use_gpu=use_gpu)
    311     self._VerifyValues(
    312         nn_ops.avg_pool,
    313         input_sizes=[1, 3, 3, 3],
    314         ksize=[1, 2, 2, 1],
    315         strides=[1, 2, 1, 1],
    316         padding="VALID",
    317         expected=[7.0, 8.0, 9.0, 10.0, 11.0, 12.0],
    318         use_gpu=use_gpu)
    319 
    320   def _testAvgPoolSamePadding4(self, use_gpu):
    321     expected_output = [
    322         11.0, 12.0, 13.0, 14.0, 19.0, 20.0, 21.0, 22.0, 43.0, 44.0, 45.0, 46.0,
    323         51.0, 52.0, 53.0, 54.0
    324     ]
    325     self._VerifyValues(
    326         nn_ops.avg_pool,
    327         input_sizes=[1, 4, 4, 4],
    328         ksize=[1, 2, 2, 1],
    329         strides=[1, 2, 2, 1],
    330         padding="SAME",
    331         expected=expected_output,
    332         use_gpu=use_gpu)
    333 
    334   def _testAvgPoolSamePaddingPacket4(self, use_gpu):
    335     expected_output = [
    336         21.0, 22.0, 23.0, 24.0, 27.0, 28.0, 29.0, 30.0, 45.0, 46.0, 47.0, 48.0,
    337         51.0, 52.0, 53.0, 54.0
    338     ]
    339     self._VerifyValues(
    340         nn_ops.avg_pool,
    341         input_sizes=[1, 4, 4, 4],
    342         ksize=[1, 3, 3, 1],
    343         strides=[1, 2, 2, 1],
    344         padding="SAME",
    345         expected=expected_output,
    346         use_gpu=use_gpu)
    347 
    348   def _testAvgPoolSamePaddingPacket8(self, use_gpu):
    349     expected_output = [
    350         -12.0, -11.0, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, 4.0, 5.0, 6.0, 7.0,
    351         8.0, 9.0, 10.0, 11.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0,
    352         32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, -3.5, -54.0, -53.0, -52.0,
    353         -51.0, -50.0, -49.0, -48.0, -47.0, -38.0, -37.0, -36.0, -35.0, -34.0,
    354         -33.0, -32.0, -31.0, -22.0, -21.0, -20.0, -19.0, -18.0, -17.0, -16.0,
    355         -15.0, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -11.0, -10.0,
    356         -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0,
    357         12.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 33.0, 34.0, 35.0,
    358         36.0, 37.0, 38.0, -3.5, -2.5, -85.0, -84.0, -83.0, -82.0, -81.0, -80.0,
    359         -79.0, -78.0, -69.0, -68.0, -67.0, -66.0, -65.0, -64.0, -63.0, -62.0,
    360         -53.0, -52.0, -51.0, -50.0, -49.0, -48.0, -47.0, -46.0, -41.0, -40.0,
    361         -39.0, -38.0, -37.0, -36.0, -35.0, -34.0
    362     ]
    363 
    364     self._VerifyValues(
    365         nn_ops.avg_pool,
    366         input_sizes=[1, 8, 8, 8],
    367         ksize=[1, 3, 3, 1],
    368         strides=[1, 2, 2, 1],
    369         padding="SAME",
    370         expected=expected_output,
    371         use_gpu=use_gpu)
    372 
    373   def _testAvgPoolEmptyInput(self, use_gpu):
    374     self._VerifyValues(
    375         nn_ops.avg_pool,
    376         input_sizes=[0, 8, 8, 8],
    377         ksize=[1, 3, 3, 1],
    378         strides=[1, 2, 2, 1],
    379         padding="SAME",
    380         expected=[],
    381         use_gpu=use_gpu)
    382 
    383   def testAvgPooling(self):
    384     for use_gpu in True, False:
    385       self._testAvgPoolValidPadding(use_gpu)
    386       self._testAvgPoolSamePadding(use_gpu)
    387       self._testAvgPoolSamePaddingNonSquareWindow(use_gpu)
    388       self._testAvgPoolSamePaddingNonSquareWindowMultiBatch(use_gpu)
    389       self._testAvgPoolValidPaddingUnevenStride(use_gpu)
    390       self._testAvgPoolSamePadding4(use_gpu)
    391       self._testAvgPoolSamePaddingPacket4(use_gpu)
    392       self._testAvgPoolSamePaddingPacket8(use_gpu)
    393       self._testAvgPoolEmptyInput(use_gpu)
    394 
    395   def _testMaxPoolValidPadding(self, use_gpu):
    396     expected_output = [13.0, 14.0, 15.0]
    397     self._VerifyValues(
    398         nn_ops.max_pool,
    399         input_sizes=[1, 3, 3, 3],
    400         ksize=[1, 2, 2, 1],
    401         strides=[1, 2, 2, 1],
    402         padding="VALID",
    403         expected=expected_output,
    404         use_gpu=use_gpu)
    405 
    406     for v2 in [True, False]:
    407       self._VerifyValues(
    408           gen_nn_ops._max_pool_v2,
    409           input_sizes=[1, 3, 3, 3],
    410           ksize=[1, 2, 2, 1],
    411           strides=[1, 2, 2, 1],
    412           padding="VALID",
    413           expected=expected_output,
    414           use_gpu=use_gpu,
    415           v2=v2)
    416 
    417   def _testMaxPoolSamePadding(self, use_gpu):
    418     expected_output = [13.0, 14.0, 15.0, 16.0, 17.0, 18.0]
    419     self._VerifyValues(
    420         nn_ops.max_pool,
    421         input_sizes=[1, 2, 3, 3],
    422         ksize=[1, 2, 2, 1],
    423         strides=[1, 2, 2, 1],
    424         padding="SAME",
    425         expected=expected_output,
    426         use_gpu=use_gpu)
    427 
    428     for v2 in [True, False]:
    429       self._VerifyValues(
    430           gen_nn_ops._max_pool_v2,
    431           input_sizes=[1, 2, 3, 3],
    432           ksize=[1, 2, 2, 1],
    433           strides=[1, 2, 2, 1],
    434           padding="SAME",
    435           expected=expected_output,
    436           use_gpu=use_gpu,
    437           v2=v2)
    438 
    439   def _testMaxPoolSamePaddingNonSquareWindow(self, use_gpu):
    440     # input is:
    441     # [1.0, 2.0
    442     #  3.0  4.0]
    443     #
    444     # Window of [x, x] should do:
    445     #
    446     #  [max(1.0, 2.0), max(2.0, padded0),
    447     #   max(3.0, 4.0), max(4.0, padded0)]
    448     self._VerifyValues(
    449         nn_ops.max_pool,
    450         input_sizes=[1, 2, 2, 1],
    451         ksize=[1, 1, 2, 1],
    452         strides=[1, 1, 1, 1],
    453         padding="SAME",
    454         expected=[2.0, 2.0, 4.0, 4.0],
    455         use_gpu=use_gpu)
    456 
    457     for v2 in [True, False]:
    458       self._VerifyValues(
    459           gen_nn_ops._max_pool_v2,
    460           input_sizes=[1, 2, 2, 1],
    461           ksize=[1, 1, 2, 1],
    462           strides=[1, 1, 1, 1],
    463           padding="SAME",
    464           expected=[2.0, 2.0, 4.0, 4.0],
    465           use_gpu=use_gpu,
    466           v2=v2)
    467 
    468   def _testMaxPoolValidPaddingUnevenStride(self, use_gpu):
    469     self._VerifyValues(
    470         nn_ops.max_pool,
    471         input_sizes=[1, 4, 4, 1],
    472         ksize=[1, 2, 2, 1],
    473         strides=[1, 1, 2, 1],
    474         padding="VALID",
    475         expected=[6.0, 8.0, 10.0, 12.0, 14.0, 16.0],
    476         use_gpu=use_gpu)
    477     self._VerifyValues(
    478         nn_ops.max_pool,
    479         input_sizes=[1, 4, 4, 1],
    480         ksize=[1, 2, 2, 1],
    481         strides=[1, 2, 1, 1],
    482         padding="VALID",
    483         expected=[6.0, 7.0, 8.0, 14.0, 15.0, 16.0],
    484         use_gpu=use_gpu)
    485 
    486     for v2 in [True, False]:
    487       self._VerifyValues(
    488           gen_nn_ops._max_pool_v2,
    489           input_sizes=[1, 4, 4, 1],
    490           ksize=[1, 2, 2, 1],
    491           strides=[1, 1, 2, 1],
    492           padding="VALID",
    493           expected=[6.0, 8.0, 10.0, 12.0, 14.0, 16.0],
    494           use_gpu=use_gpu,
    495           v2=v2)
    496       self._VerifyValues(
    497           gen_nn_ops._max_pool_v2,
    498           input_sizes=[1, 4, 4, 1],
    499           ksize=[1, 2, 2, 1],
    500           strides=[1, 2, 1, 1],
    501           padding="VALID",
    502           expected=[6.0, 7.0, 8.0, 14.0, 15.0, 16.0],
    503           use_gpu=use_gpu,
    504           v2=v2)
    505 
    506   def _testMaxPoolSamePaddingPacket4(self, use_gpu):
    507     expected_output = [
    508         21.0, 22.0, 23.0, 24.0, 29.0, 30.0, 31.0, 32.0, 53.0, 54.0, 55.0, 56.0,
    509         61.0, 62.0, 63.0, 64.0
    510     ]
    511     self._VerifyValues(
    512         nn_ops.max_pool,
    513         input_sizes=[1, 4, 4, 4],
    514         ksize=[1, 2, 2, 1],
    515         strides=[1, 2, 2, 1],
    516         padding="SAME",
    517         expected=expected_output,
    518         use_gpu=use_gpu)
    519 
    520     for v2 in [True, False]:
    521       self._VerifyValues(
    522           gen_nn_ops._max_pool_v2,
    523           input_sizes=[1, 4, 4, 4],
    524           ksize=[1, 2, 2, 1],
    525           strides=[1, 2, 2, 1],
    526           padding="SAME",
    527           expected=expected_output,
    528           use_gpu=use_gpu,
    529           v2=v2)
    530 
    531   def _testMaxPoolSamePaddingPacket8(self, use_gpu):
    532     expected_output = [
    533         81.0, 82.0, 83.0, 84.0, 85.0, 86.0, 87.0, 88.0, 97.0, 98.0, 99.0, 100.0,
    534         101.0, 102.0, 103.0, 104.0, 113.0, 114.0, 115.0, 116.0, 117.0, 118.0,
    535         119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 125.0, 126.0, 127.0, 120.0,
    536         18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 34.0, 35.0, 36.0, 37.0,
    537         38.0, 39.0, 40.0, 41.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0,
    538         58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 82.0, 83.0, 84.0, 85.0,
    539         86.0, 87.0, 88.0, 89.0, 98.0, 99.0, 100.0, 101.0, 102.0, 103.0, 104.0,
    540         105.0, 114.0, 115.0, 116.0, 117.0, 118.0, 119.0, 120.0, 121.0, 122.0,
    541         123.0, 124.0, 125.0, 126.0, 127.0, 120.0, 121.0, -45.0, -44.0, -43.0,
    542         -42.0, -41.0, -40.0, -39.0, -38.0, -29.0, -28.0, -27.0, -26.0, -25.0,
    543         -24.0, -23.0, -22.0, -13.0, -12.0, -11.0, -10.0, -9.0, -8.0, -7.0, -6.0,
    544         -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0
    545     ]
    546     self._VerifyValues(
    547         nn_ops.max_pool,
    548         input_sizes=[1, 8, 8, 8],
    549         ksize=[1, 3, 3, 1],
    550         strides=[1, 2, 2, 1],
    551         padding="SAME",
    552         expected=expected_output,
    553         use_gpu=use_gpu)
    554 
    555     for v2 in [True, False]:
    556       self._VerifyValues(
    557           gen_nn_ops._max_pool_v2,
    558           input_sizes=[1, 8, 8, 8],
    559           ksize=[1, 3, 3, 1],
    560           strides=[1, 2, 2, 1],
    561           padding="SAME",
    562           expected=expected_output,
    563           use_gpu=use_gpu,
    564           v2=v2)
    565 
    566   def _testMaxPoolEmptyInput(self, use_gpu):
    567     self._VerifyValues(
    568         gen_nn_ops._max_pool_v2,
    569         input_sizes=[0, 8, 8, 8],
    570         ksize=[1, 3, 3, 1],
    571         strides=[1, 2, 2, 1],
    572         padding="SAME",
    573         expected=[],
    574         use_gpu=use_gpu)
    575 
    576   def testMaxPooling(self):
    577     for use_gpu in True, False:
    578       self._testMaxPoolValidPadding(use_gpu)
    579       self._testMaxPoolSamePadding(use_gpu)
    580       self._testMaxPoolSamePaddingNonSquareWindow(use_gpu)
    581       self._testMaxPoolValidPaddingUnevenStride(use_gpu)
    582       self._testMaxPoolSamePaddingPacket4(use_gpu)
    583       self._testMaxPoolSamePaddingPacket8(use_gpu)
    584       self._testMaxPoolEmptyInput(use_gpu)
    585 
    586   # Tests for DepthwiseMaxPooling on CPU only.
    587   def testDepthwiseMaxPool1x1DepthWindow1(self):
    588     # input is:
    589     # [1.0, ..., 10.0] along depth,
    590     #
    591     # We maxpool by depth in patches of 2.
    592     self._VerifyValues(
    593         nn_ops.max_pool,
    594         input_sizes=[1, 1, 1, 10],
    595         ksize=[1, 1, 1, 2],
    596         strides=[1, 1, 1, 2],
    597         padding="SAME",
    598         expected=[2.0, 4.0, 6.0, 8.0, 10.0],
    599         use_gpu=False)
    600 
    601     for v2 in [True, False]:
    602       self._VerifyValues(
    603           gen_nn_ops._max_pool_v2,
    604           input_sizes=[1, 1, 1, 10],
    605           ksize=[1, 1, 1, 2],
    606           strides=[1, 1, 1, 2],
    607           padding="SAME",
    608           expected=[2.0, 4.0, 6.0, 8.0, 10.0],
    609           use_gpu=False,
    610           v2=v2)
    611 
    612   def testDepthwiseMaxPool2x2DepthWindow3(self):
    613     # input is:
    614     #
    615     # a 2x2x6 cube, and we depthwise max across 3 to produce a 2x2x2
    616     # output.  Each node has contiguous values, so the depthwise max
    617     # should be multiples of 3.0.
    618     self._VerifyValues(
    619         nn_ops.max_pool,
    620         input_sizes=[1, 2, 2, 6],
    621         ksize=[1, 1, 1, 3],
    622         strides=[1, 1, 1, 3],
    623         padding="SAME",
    624         expected=[3.0, 6.0, 9.0, 12.0, 15.0, 18.0, 21.0, 24.0],
    625         use_gpu=False)
    626 
    627     for v2 in [True, False]:
    628       self._VerifyValues(
    629           gen_nn_ops._max_pool_v2,
    630           input_sizes=[1, 2, 2, 6],
    631           ksize=[1, 1, 1, 3],
    632           strides=[1, 1, 1, 3],
    633           padding="SAME",
    634           expected=[3.0, 6.0, 9.0, 12.0, 15.0, 18.0, 21.0, 24.0],
    635           use_gpu=False,
    636           v2=v2)
    637 
    638   def testKernelSmallerThanStrideValid(self):
    639     for use_gpu in [True, False]:
    640       self._VerifyValues(
    641           nn_ops.max_pool,
    642           input_sizes=[1, 7, 7, 1],
    643           ksize=[1, 2, 2, 1],
    644           strides=[1, 3, 3, 1],
    645           padding="VALID",
    646           expected=[9, 12, 30, 33],
    647           use_gpu=use_gpu)
    648 
    649       for v2 in [True, False]:
    650         self._VerifyValues(
    651             gen_nn_ops._max_pool_v2,
    652             input_sizes=[1, 7, 7, 1],
    653             ksize=[1, 2, 2, 1],
    654             strides=[1, 3, 3, 1],
    655             padding="VALID",
    656             expected=[9, 12, 30, 33],
    657             use_gpu=use_gpu,
    658             v2=v2)
    659 
    660       self._VerifyValues(
    661           nn_ops.avg_pool,
    662           input_sizes=[1, 7, 7, 1],
    663           ksize=[1, 2, 2, 1],
    664           strides=[1, 3, 3, 1],
    665           padding="VALID",
    666           expected=[5, 8, 26, 29],
    667           use_gpu=use_gpu)
    668 
    669   def testKernelSmallerThanStrideSame(self):
    670     for use_gpu in [True, False]:
    671       for pool_func in [nn_ops.max_pool, nn_ops.avg_pool]:
    672         self._VerifyValues(
    673             pool_func,
    674             input_sizes=[1, 3, 3, 1],
    675             ksize=[1, 1, 1, 1],
    676             strides=[1, 2, 2, 1],
    677             padding="SAME",
    678             expected=[1, 3, 7, 9],
    679             use_gpu=use_gpu)
    680 
    681         self._VerifyValues(
    682             pool_func,
    683             input_sizes=[1, 4, 4, 1],
    684             ksize=[1, 1, 1, 1],
    685             strides=[1, 2, 2, 1],
    686             padding="SAME",
    687             expected=[1, 3, 9, 11],
    688             use_gpu=use_gpu)
    689 
    690       for v2 in [True, False]:
    691         self._VerifyValues(
    692             gen_nn_ops._max_pool_v2,
    693             input_sizes=[1, 3, 3, 1],
    694             ksize=[1, 1, 1, 1],
    695             strides=[1, 2, 2, 1],
    696             padding="SAME",
    697             expected=[1, 3, 7, 9],
    698             use_gpu=use_gpu,
    699             v2=v2)
    700 
    701         self._VerifyValues(
    702             gen_nn_ops._max_pool_v2,
    703             input_sizes=[1, 4, 4, 1],
    704             ksize=[1, 1, 1, 1],
    705             strides=[1, 2, 2, 1],
    706             padding="SAME",
    707             expected=[1, 3, 9, 11],
    708             use_gpu=use_gpu,
    709             v2=v2)
    710 
    711   def _testDepthwiseMaxPoolInvalidConfig(self,
    712                                          in_size,
    713                                          ksize,
    714                                          strides,
    715                                          error_msg,
    716                                          use_gpu=False):
    717     with self.test_session(use_gpu=use_gpu):
    718       t = constant_op.constant(1.0, shape=in_size)
    719       with self.assertRaisesRegexp(errors_impl.UnimplementedError, error_msg):
    720         t = nn_ops.max_pool(
    721             t, ksize=ksize, strides=strides, padding="SAME").eval()
    722 
    723   def testDepthwiseMaxPoolInvalidConfigs(self):
    724     self._testDepthwiseMaxPoolInvalidConfig(
    725         [1, 2, 2, 4], [1, 2, 2, 2], [1, 1, 1, 2],
    726         "exactly one of pooling across depth")
    727     self._testDepthwiseMaxPoolInvalidConfig(
    728         [1, 2, 2, 4], [1, 1, 1, 2], [1, 1, 1, 1],
    729         "depth window to equal the depth stride")
    730     self._testDepthwiseMaxPoolInvalidConfig([1, 2, 2, 4], [1, 1, 1, 3],
    731                                             [1, 1, 1, 3], "evenly divide")
    732     if test.is_gpu_available():
    733       with self.test_session(use_gpu=True):
    734         t = constant_op.constant(1.0, shape=[1, 2, 2, 4])
    735         with self.assertRaisesOpError("for CPU devices"):
    736           nn_ops.max_pool(
    737               t, ksize=[1, 1, 1, 2], strides=[1, 1, 1, 2],
    738               padding="SAME").eval()
    739 
    740   # The following are tests that verify that the CPU and GPU implementations
    741   # produce the same results.
    742   def _CompareMaxPoolingFwd(self, input_shape, ksize, strides, padding):
    743     for dtype in np.float64, np.float32, np.float16:
    744       tensor_input = np.random.rand(*input_shape).astype(dtype)
    745       with self.test_session(use_gpu=True):
    746         t = constant_op.constant(tensor_input, shape=input_shape)
    747         out_op, _ = nn_ops.max_pool_with_argmax(t, ksize, strides, padding)
    748         gpu_val = out_op.eval()
    749       with self.test_session(use_gpu=False):
    750         t = constant_op.constant(tensor_input, shape=input_shape)
    751         out_op = nn_ops.max_pool(t, ksize, strides, padding)
    752         cpu_val = out_op.eval()
    753       self.assertAllCloseAccordingToType(cpu_val, gpu_val)
    754 
    755   def _CompareMaxPoolingBk(self, input_shape, output_shape, ksize, strides,
    756                            padding):
    757     for dtype in np.float64, np.float32, np.float16:
    758       # Generate numbers in a narrow range, so that there are many duplicates
    759       # in the input.
    760       tensor_input = np.random.random_integers(0, 3, input_shape).astype(dtype)
    761       tensor_output = np.random.rand(*output_shape).astype(dtype)
    762       with self.test_session(use_gpu=True):
    763         t = constant_op.constant(tensor_input, shape=input_shape)
    764         _, argmax_op = nn_ops.max_pool_with_argmax(t, ksize, strides, padding)
    765         argmax = argmax_op.eval()
    766         grad_in = constant_op.constant(tensor_output, shape=output_shape)
    767         out_op = gen_nn_ops._max_pool_grad_with_argmax(t, grad_in, argmax,
    768                                                        ksize, strides, padding)
    769         gpu_val = out_op.eval()
    770         self.assertShapeEqual(gpu_val, out_op)
    771       with self.test_session(use_gpu=False):
    772         t = constant_op.constant(tensor_input, shape=input_shape)
    773         out_op = nn_ops.max_pool(t, ksize, strides, padding)
    774         orig_out = out_op.eval()
    775         grad_in = constant_op.constant(tensor_output, shape=output_shape)
    776         out_op = gen_nn_ops._max_pool_grad(t, orig_out, grad_in, ksize, strides,
    777                                            padding)
    778         cpu_val = out_op.eval()
    779         self.assertShapeEqual(cpu_val, out_op)
    780       # The CPU version accumulates its gradient on fp16, so it's less
    781       # accurate than the GPU version that does the accumulation on fp32
    782       self.assertAllCloseAccordingToType(
    783           cpu_val, gpu_val, half_rtol=0.01, half_atol=0.01)
    784 
    785   def _CompareMaxPoolingGradBk(self, input_shape, output_shape, ksize, strides,
    786                                padding):
    787     for dtype in np.float64, np.float32, np.float16:
    788       # Generate numbers in a narrow range, so that there are many duplicates
    789       # in the input.
    790       tensor_input = np.random.random_integers(0, 3, input_shape).astype(dtype)
    791       with self.test_session(use_gpu=True):
    792         t = constant_op.constant(tensor_input, shape=input_shape)
    793         _, argmax_op = nn_ops.max_pool_with_argmax(t, ksize, strides, padding)
    794         argmax = argmax_op.eval()
    795         grad_in = constant_op.constant(tensor_input, shape=input_shape)
    796         out_op = gen_nn_ops._max_pool_grad_grad_with_argmax(
    797             t, grad_in, argmax, ksize, strides, padding)
    798         gpu_val = out_op.eval()
    799         self.assertShapeEqual(gpu_val, out_op)
    800       with self.test_session(use_gpu=False):
    801         t = constant_op.constant(tensor_input, shape=input_shape)
    802         out_op = nn_ops.max_pool(t, ksize, strides, padding)
    803         orig_out = out_op.eval()
    804         grad_in = constant_op.constant(tensor_input, shape=input_shape)
    805         out_op = gen_nn_ops._max_pool_grad_grad(t, orig_out, grad_in, ksize,
    806                                                 strides, padding)
    807         cpu_val = out_op.eval()
    808         self.assertShapeEqual(cpu_val, out_op)
    809       # The CPU version accumulates its gradient on fp16, so it's less
    810       # accurate than the GPU version that does the accumulation on fp32
    811       self.assertAllCloseAccordingToType(
    812           cpu_val, gpu_val, half_rtol=0.01, half_atol=0.01)
    813 
    814   def testMaxPoolingWithArgmax(self):
    815     # MaxPoolWithArgMax is implemented only on CUDA.
    816     if not test.is_gpu_available(cuda_only=True):
    817       return
    818     tensor_input = [1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0]
    819     with self.test_session(use_gpu=True) as sess:
    820       t = constant_op.constant(tensor_input, shape=[1, 3, 3, 1])
    821       out_op, argmax_op = nn_ops.max_pool_with_argmax(
    822           t,
    823           ksize=[1, 2, 2, 1],
    824           strides=[1, 1, 1, 1],
    825           Targmax=dtypes.int64,
    826           padding="VALID")
    827       out, argmax = sess.run([out_op, argmax_op])
    828       self.assertShapeEqual(out, out_op)
    829       self.assertShapeEqual(argmax, argmax_op)
    830       self.assertAllClose(out.ravel(), [1.0, 1.0, 1.0, 1.0])
    831       self.assertAllEqual(argmax.ravel(), [0, 1, 3, 5])
    832 
    833   def testMaxPoolingGradWithArgmax(self):
    834     # MaxPoolWithArgMax is implemented only on CUDA.
    835     if not test.is_gpu_available(cuda_only=True):
    836       return
    837     orig_input = [1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0]
    838     tensor_input = [11.0, 12.0, 13.0, 14.0]
    839     tensor_argmax = list(np.array([0, 1, 3, 5], dtype=np.int64))
    840     with self.test_session(use_gpu=True):
    841       orig_in = constant_op.constant(orig_input, shape=[1, 3, 3, 1])
    842       t = constant_op.constant(tensor_input, shape=[1, 2, 2, 1])
    843       argmax = constant_op.constant(
    844           tensor_argmax, shape=[1, 2, 2, 1], dtype=dtypes.int64)
    845       out_op = gen_nn_ops._max_pool_grad_with_argmax(
    846           orig_in,
    847           t,
    848           argmax,
    849           ksize=[1, 2, 2, 1],
    850           strides=[1, 1, 1, 1],
    851           padding="VALID")
    852       out = out_op.eval().flatten()
    853       self.assertAllClose(out,
    854                           [11.0, 12.0, 0.0, 13.0, 0.0, 14.0, 0.0, 0.0, 0.0])
    855 
    856   def testMaxPoolingGradGradWithArgmax(self):
    857     # MaxPoolWithArgMax is implemented only on CUDA.
    858     if not test.is_gpu_available(cuda_only=True):
    859       return
    860     orig_input = [1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0]
    861     tensor_input = [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0]
    862     tensor_argmax = list(np.array([0, 1, 3, 5], dtype=np.int64))
    863     with self.test_session(use_gpu=True):
    864       orig_in = constant_op.constant(orig_input, shape=[1, 3, 3, 1])
    865       t = constant_op.constant(tensor_input, shape=[1, 3, 3, 1])
    866       argmax = constant_op.constant(
    867           tensor_argmax, shape=[1, 2, 2, 1], dtype=dtypes.int64)
    868       out_op = gen_nn_ops._max_pool_grad_grad_with_argmax(
    869           orig_in,
    870           t,
    871           argmax,
    872           ksize=[1, 2, 2, 1],
    873           strides=[1, 1, 1, 1],
    874           padding="VALID")
    875       out = out_op.eval().flatten()
    876       self.assertAllClose(out, [11.0, 12.0, 14.0, 16.0])
    877 
    878   def _ConstructAndTestGradient(self,
    879                                 pool_func,
    880                                 input_sizes,
    881                                 output_sizes,
    882                                 window_rows,
    883                                 window_cols,
    884                                 row_stride,
    885                                 col_stride,
    886                                 padding,
    887                                 data_format,
    888                                 use_gpu,
    889                                 x_init_value=None):
    890     """Verifies the gradients of the avg pooling function.
    891 
    892     Args:
    893       pool_func: Function to be called, co.MaxPool, co.AvgPool,
    894         or the Lua version.
    895       input_sizes: Input tensor dimensions.
    896       output_sizes: Output tensor dimensions.
    897       window_rows: kernel size in row dim
    898       window_cols: kernel size in col dim
    899       row_stride: Row Stride.
    900       col_stride: Col Stride.
    901       padding: Padding type.
    902       data_format: Data format.
    903       use_gpu: whether we are running on GPU
    904       x_init_value: Values to be passed to the gradient checker.
    905     """
    906     assert input_sizes[0] == output_sizes[0]
    907     assert input_sizes[3] == output_sizes[3]
    908     total_size = 1
    909     for s in input_sizes:
    910       total_size *= s
    911     # Initializes the input tensor with array containing incrementing
    912     # numbers from 1.
    913     x = [f * 1.0 for f in range(1, total_size + 1)]
    914     with self.test_session(use_gpu=use_gpu):
    915       input_tensor = constant_op.constant(x, shape=input_sizes, name="input")
    916       if pool_func == nn_ops.avg_pool:
    917         func_name = "avg_pool"
    918         err_tolerance = 1e-4
    919       else:
    920         if x_init_value is None:
    921           x_init_value = np.asfarray(
    922               np.arange(1, total_size + 1),
    923               dtype=np.float32).reshape(input_sizes)
    924         func_name = "max_pool"
    925         err_tolerance = 1e-3
    926       if data_format == "NCHW":
    927         ksize = [1, 1, window_rows, window_rows]
    928         strides = [1, 1, row_stride, col_stride]
    929         t = test_util.NHWCToNCHW(input_tensor)
    930       else:
    931         ksize = [1, window_rows, window_rows, 1]
    932         strides = [1, row_stride, col_stride, 1]
    933         t = input_tensor
    934       t = pool_func(
    935           t,
    936           ksize=ksize,
    937           strides=strides,
    938           padding=padding,
    939           data_format=data_format,
    940           name=func_name)
    941       if data_format == "NCHW":
    942         t = test_util.NCHWToNHWC(t)
    943 
    944       err = gradient_checker.compute_gradient_error(
    945           input_tensor,
    946           input_sizes,
    947           t,
    948           output_sizes,
    949           x_init_value=x_init_value,
    950           delta=1e-2)
    951     print("%s gradient error = " % func_name, err)
    952     self.assertLess(err, err_tolerance)
    953 
    954   def _ConstructAndTestSecondGradient(self,
    955                                       pool_func,
    956                                       input_sizes,
    957                                       output_sizes,
    958                                       window_rows,
    959                                       window_cols,
    960                                       row_stride,
    961                                       col_stride,
    962                                       padding,
    963                                       data_format,
    964                                       use_gpu,
    965                                       x_init_value=None):
    966     """Verifies the second-order gradients of the pooling function.
    967 
    968     Args:
    969       pool_func: Function to be called, co.MaxPool, co.AvgPool,
    970         or the Lua version.
    971       input_sizes: Input tensor dimensions.
    972       output_sizes: Output tensor dimensions.
    973       window_rows: kernel size in row dim
    974       window_cols: kernel size in col dim
    975       row_stride: Row Stride.
    976       col_stride: Col Stride.
    977       padding: Padding type.
    978       data_format: Data format.
    979       use_gpu: whether we are running on GPU
    980       x_init_value: Values to be passed to the gradient checker.
    981     """
    982     assert input_sizes[0] == output_sizes[0]
    983     assert input_sizes[3] == output_sizes[3]
    984     total_size = 1
    985     for s in input_sizes:
    986       total_size *= s
    987     # Initializes the input tensor with array containing incrementing
    988     # numbers from 1.
    989     x = [f * 1.0 for f in range(1, total_size + 1)]
    990     with self.test_session(use_gpu=use_gpu):
    991       input_tensor = constant_op.constant(x, shape=input_sizes, name="input")
    992       if pool_func == nn_ops.avg_pool:
    993         func_name = "avg_pool"
    994         err_tolerance = 1e-3
    995       else:
    996         if x_init_value is None:
    997           x_init_value = np.asfarray(
    998               np.arange(1, total_size + 1),
    999               dtype=np.float32).reshape(input_sizes)
   1000         func_name = "max_pool"
   1001         err_tolerance = 1e-2
   1002       if data_format == "NCHW":
   1003         ksize = [1, 1, window_rows, window_rows]
   1004         strides = [1, 1, row_stride, col_stride]
   1005         t = test_util.NHWCToNCHW(input_tensor)
   1006       else:
   1007         ksize = [1, window_rows, window_rows, 1]
   1008         strides = [1, row_stride, col_stride, 1]
   1009         t = input_tensor
   1010       t = pool_func(
   1011           t,
   1012           ksize=ksize,
   1013           strides=strides,
   1014           padding=padding,
   1015           data_format=data_format,
   1016           name=func_name)
   1017       if data_format == "NCHW":
   1018         t = test_util.NHWCToNCHW(t)
   1019 
   1020       t_g = gradients_impl.gradients(t**2, input_tensor)[0]
   1021       err = gradient_checker.compute_gradient_error(
   1022           input_tensor,
   1023           input_sizes,
   1024           t_g,
   1025           input_sizes,
   1026           x_init_value=x_init_value,
   1027           delta=1e-2)
   1028     print("%s second-order gradient error = " % func_name, err)
   1029     self.assertLess(err, err_tolerance)
   1030 
   1031   def _testMaxPoolGradValidPadding1_1(self, data_format, use_gpu):
   1032     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1033       self._ConstructAndTestGradient(
   1034           pool_func,
   1035           input_sizes=[1, 3, 3, 1],
   1036           output_sizes=[1, 3, 3, 1],
   1037           window_rows=1,
   1038           window_cols=1,
   1039           row_stride=1,
   1040           col_stride=1,
   1041           padding="VALID",
   1042           data_format=data_format,
   1043           use_gpu=use_gpu)
   1044 
   1045   def _testMaxPoolGradValidPadding2_1_6(self, data_format, use_gpu):
   1046     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1047       self._ConstructAndTestGradient(
   1048           pool_func,
   1049           input_sizes=[2, 6, 6, 3],
   1050           output_sizes=[2, 5, 5, 3],
   1051           window_rows=2,
   1052           window_cols=2,
   1053           row_stride=1,
   1054           col_stride=1,
   1055           padding="VALID",
   1056           data_format=data_format,
   1057           use_gpu=use_gpu)
   1058 
   1059   def _testMaxPoolGradValidPadding2_1_7(self, data_format, use_gpu):
   1060     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1061       self._ConstructAndTestGradient(
   1062           pool_func,
   1063           input_sizes=[2, 7, 7, 3],
   1064           output_sizes=[2, 6, 6, 3],
   1065           window_rows=2,
   1066           window_cols=2,
   1067           row_stride=1,
   1068           col_stride=1,
   1069           padding="VALID",
   1070           data_format=data_format,
   1071           use_gpu=use_gpu)
   1072 
   1073   def _testMaxPoolGradValidPadding1_2(self, data_format, use_gpu):
   1074     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1075       self._ConstructAndTestGradient(
   1076           pool_func,
   1077           input_sizes=[1, 3, 3, 1],
   1078           output_sizes=[1, 2, 2, 1],
   1079           window_rows=1,
   1080           window_cols=1,
   1081           row_stride=2,
   1082           col_stride=2,
   1083           padding="VALID",
   1084           data_format=data_format,
   1085           use_gpu=use_gpu)
   1086 
   1087   def _testMaxPoolGradValidPadding2_2(self, data_format, use_gpu):
   1088     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1089       self._ConstructAndTestGradient(
   1090           pool_func,
   1091           input_sizes=[2, 2, 2, 3],
   1092           output_sizes=[2, 1, 1, 3],
   1093           window_rows=2,
   1094           window_cols=2,
   1095           row_stride=2,
   1096           col_stride=2,
   1097           padding="VALID",
   1098           data_format=data_format,
   1099           use_gpu=use_gpu)
   1100 
   1101   def _testMaxPoolGradSamePadding1_1(self, data_format, use_gpu):
   1102     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1103       self._ConstructAndTestGradient(
   1104           pool_func,
   1105           input_sizes=[2, 2, 4, 3],
   1106           output_sizes=[2, 2, 4, 3],
   1107           window_rows=1,
   1108           window_cols=1,
   1109           row_stride=1,
   1110           col_stride=1,
   1111           padding="SAME",
   1112           data_format=data_format,
   1113           use_gpu=use_gpu)
   1114 
   1115   def _testMaxPoolGradSamePadding1_2(self, data_format, use_gpu):
   1116     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1117       self._ConstructAndTestGradient(
   1118           pool_func,
   1119           input_sizes=[2, 2, 4, 3],
   1120           output_sizes=[2, 1, 2, 3],
   1121           window_rows=1,
   1122           window_cols=1,
   1123           row_stride=2,
   1124           col_stride=2,
   1125           padding="SAME",
   1126           data_format=data_format,
   1127           use_gpu=use_gpu)
   1128 
   1129   def _testMaxPoolGradSamePadding2_1(self, data_format, use_gpu):
   1130     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1131       self._ConstructAndTestGradient(
   1132           pool_func,
   1133           input_sizes=[2, 2, 4, 3],
   1134           output_sizes=[2, 2, 4, 3],
   1135           window_rows=2,
   1136           window_cols=2,
   1137           row_stride=1,
   1138           col_stride=1,
   1139           padding="SAME",
   1140           data_format=data_format,
   1141           use_gpu=use_gpu)
   1142 
   1143   def _testMaxPoolGradSamePadding2_2(self, data_format, use_gpu):
   1144     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1145       self._ConstructAndTestGradient(
   1146           pool_func,
   1147           input_sizes=[2, 2, 4, 3],
   1148           output_sizes=[2, 1, 2, 3],
   1149           window_rows=2,
   1150           window_cols=2,
   1151           row_stride=2,
   1152           col_stride=2,
   1153           padding="SAME",
   1154           data_format=data_format,
   1155           use_gpu=use_gpu)
   1156 
   1157   def _testMaxPoolGradSamePadding3_1(self, data_format, use_gpu):
   1158     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1159       self._ConstructAndTestGradient(
   1160           pool_func,
   1161           input_sizes=[1, 7, 7, 1],
   1162           output_sizes=[1, 7, 7, 1],
   1163           window_rows=3,
   1164           window_cols=3,
   1165           row_stride=1,
   1166           col_stride=1,
   1167           padding="SAME",
   1168           data_format=data_format,
   1169           use_gpu=use_gpu)
   1170 
   1171   def testMaxPoolGrad(self):
   1172     for (data_format, use_gpu) in GetTestConfigs():
   1173       self._testMaxPoolGradValidPadding1_1(data_format, use_gpu)
   1174       self._testMaxPoolGradValidPadding1_2(data_format, use_gpu)
   1175       self._testMaxPoolGradValidPadding2_1_6(data_format, use_gpu)
   1176       self._testMaxPoolGradValidPadding2_1_7(data_format, use_gpu)
   1177       self._testMaxPoolGradValidPadding2_2(data_format, use_gpu)
   1178       self._testMaxPoolGradSamePadding1_1(data_format, use_gpu)
   1179       self._testMaxPoolGradSamePadding1_2(data_format, use_gpu)
   1180       self._testMaxPoolGradSamePadding2_1(data_format, use_gpu)
   1181       self._testMaxPoolGradSamePadding2_2(data_format, use_gpu)
   1182       self._testMaxPoolGradSamePadding3_1(data_format, use_gpu)
   1183 
   1184   def _MaxPoolGrad(self, orig_input, orig_output, grad, window_rows,
   1185                    window_cols, row_stride, col_stride, padding, v2):
   1186     """Max Pooling Gradient.
   1187 
   1188     Args:
   1189       orig_input: A float Tensor. The original input tensor.
   1190       orig_output: A float Tensor. The original output tensor.
   1191       grad: A float Tensor.
   1192         The 4D (batch x rows x cols x depth) output backprop.
   1193       window_rows: integer. Kernel size along rows dimension.
   1194       window_cols: integer. Kernel size along cols dimension.
   1195       row_stride: integer. Stride along rows dimension
   1196       col_stride: integer. Stride along cols dimension
   1197       padding: PoolingOpDef.Padding.  Padding type.
   1198 
   1199     Returns:
   1200       A Tensor.
   1201     """
   1202     pool_func = gen_nn_ops.max_pool_grad_v2 if v2 else gen_nn_ops._max_pool_grad
   1203     return pool_func(orig_input, orig_output, grad,
   1204                      [1, window_rows, window_cols, 1],
   1205                      [1, row_stride, col_stride, 1], padding)
   1206 
   1207   def _testMaxPoolGradDirect(self, input_data, output_backprop,
   1208                              expected_input_backprop, input_sizes, output_sizes,
   1209                              window_rows, window_cols, row_stride, col_stride,
   1210                              padding, use_gpu, v2):
   1211     pool_func = gen_nn_ops._max_pool_v2 if v2 else nn_ops.max_pool
   1212     with self.test_session(use_gpu=use_gpu):
   1213       input_tensor = constant_op.constant(input_data, shape=input_sizes)
   1214       output_tensor = pool_func(input_tensor, [1, window_rows, window_cols, 1],
   1215                                 [1, row_stride, col_stride, 1], padding)
   1216       output_backprop_tensor = constant_op.constant(
   1217           output_backprop, shape=output_sizes)
   1218 
   1219       input_backprop_tensor = self._MaxPoolGrad(
   1220           input_tensor, output_tensor, output_backprop_tensor, window_rows,
   1221           window_cols, row_stride, col_stride, padding, v2)
   1222 
   1223       actual_input_backprop = input_backprop_tensor.eval()
   1224       self.assertShapeEqual(actual_input_backprop, input_backprop_tensor)
   1225       actual_input_backprop = actual_input_backprop.flatten()
   1226       actual_input_backprop = self._GetNdArray(actual_input_backprop)
   1227 
   1228       actual_output = output_tensor.eval().flatten()
   1229       actual_output = self._GetNdArray(actual_output)
   1230 
   1231       self.assertAllClose(
   1232           expected_input_backprop, actual_input_backprop, rtol=1e-6, atol=1e-6)
   1233 
   1234   def _testMaxPoolGradDirect1_1(self):
   1235     input_data = [
   1236         1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
   1237         1.0, 1.0
   1238     ]
   1239     output_backprop = [11.0, 12.0, 13.0, 15.0, 16.0, 17.0, 19.0, 20.0, 21.0]
   1240     expected_input_backprop = [
   1241         11.0, 12.0, 13.0, 0.0, 15.0, 16.0, 17.0, 0.0, 19.0, 20.0, 21.0, 0.0,
   1242         0.0, 0.0, 0.0, 0.0
   1243     ]
   1244 
   1245     for use_gpu in True, False:
   1246       for v2 in [True, False]:
   1247         self._testMaxPoolGradDirect(
   1248             input_data,
   1249             output_backprop,
   1250             expected_input_backprop,
   1251             input_sizes=[1, 4, 4, 1],
   1252             output_sizes=[1, 3, 3, 1],
   1253             window_rows=2,
   1254             window_cols=2,
   1255             row_stride=1,
   1256             col_stride=1,
   1257             padding="VALID",
   1258             use_gpu=use_gpu,
   1259             v2=v2)
   1260 
   1261   def _testMaxPoolGradDirect1_2(self):
   1262     input_data = [
   1263         1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0,
   1264         0.0, 1.0
   1265     ]
   1266     output_backprop = [11.0, 12.0, 13.0, 15.0, 16.0, 17.0, 19.0, 20.0, 21.0]
   1267     expected_input_backprop = [
   1268         11.0, 0.0, 25.0, 0.0, 0.0, 31.0, 0.0, 17.0, 19.0, 0.0, 41.0, 0.0, 0.0,
   1269         0.0, 0.0, 0.0
   1270     ]
   1271 
   1272     for use_gpu in True, False:
   1273       for v2 in [True, False]:
   1274         self._testMaxPoolGradDirect(
   1275             input_data,
   1276             output_backprop,
   1277             expected_input_backprop,
   1278             input_sizes=[1, 4, 4, 1],
   1279             output_sizes=[1, 3, 3, 1],
   1280             window_rows=2,
   1281             window_cols=2,
   1282             row_stride=1,
   1283             col_stride=1,
   1284             padding="VALID",
   1285             use_gpu=use_gpu,
   1286             v2=v2)
   1287 
   1288   def _testMaxPoolGradDirect1_3(self):
   1289     input_data = [
   1290         1.0,
   1291         0.0,
   1292         1.0,
   1293         0.0,
   1294         0.0,
   1295         1.0,
   1296         0.0,
   1297         1.0,
   1298         1.0,
   1299         0.0,
   1300         1.0,
   1301         0.0,
   1302         0.0,
   1303         1.0,
   1304         0.0,
   1305         1.0,
   1306     ]
   1307     output_backprop = [
   1308         11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0,
   1309         23.0, 24.0, 25.0, 26.0
   1310     ]
   1311     expected_input_backprop = [
   1312         54,
   1313         0.0,
   1314         62,
   1315         0.0,
   1316         0.0,
   1317         60,
   1318         0.0,
   1319         22.0,
   1320         47,
   1321         0.0,
   1322         51,
   1323         0.0,
   1324         0.0,
   1325         0.0,
   1326         0.0,
   1327         0.0,
   1328     ]
   1329 
   1330     for use_gpu in True, False:
   1331       for v2 in [True, False]:
   1332         self._testMaxPoolGradDirect(
   1333             input_data,
   1334             output_backprop,
   1335             expected_input_backprop,
   1336             input_sizes=[1, 4, 4, 1],
   1337             output_sizes=[1, 4, 4, 1],
   1338             window_rows=3,
   1339             window_cols=3,
   1340             row_stride=1,
   1341             col_stride=1,
   1342             padding="SAME",
   1343             use_gpu=use_gpu,
   1344             v2=v2)
   1345 
   1346   def _testMaxPoolGradDirectWithNans2_1(self):
   1347     input_data = [float("nan")] * 16
   1348     output_backprop = [11.0, 12.0, 13.0, 15.0, 16.0, 17.0, 19.0, 20.0, 21.0]
   1349     # Test the CPU implementation, which propagates diffs in case of NaN
   1350     expected_input_backprop_tf_cpu = [
   1351         11.0, 12.0, 13.0, 0.0, 15.0, 16.0, 17.0, 0.0, 19.0, 20.0, 21.0, 0.0,
   1352         0.0, 0.0, 0.0, 0.0
   1353     ]
   1354     for v2 in [True, False]:
   1355       self._testMaxPoolGradDirect(
   1356           input_data,
   1357           output_backprop,
   1358           expected_input_backprop_tf_cpu,
   1359           input_sizes=[1, 4, 4, 1],
   1360           output_sizes=[1, 3, 3, 1],
   1361           window_rows=2,
   1362           window_cols=2,
   1363           row_stride=1,
   1364           col_stride=1,
   1365           padding="VALID",
   1366           use_gpu=False,
   1367           v2=v2)
   1368 
   1369     if not test.is_gpu_available():
   1370       return
   1371 
   1372     # Test the GPU implementation that uses cudnn for now.
   1373     saved_nanprop = os.environ.get("TF_ENABLE_MAXPOOL_NANPROP")
   1374     # Do not propagate the diff in cases of NaNs
   1375     os.environ["TF_ENABLE_MAXPOOL_NANPROP"] = "0"
   1376     expected_input_backprop_cudnn = [
   1377         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
   1378         0.0, 0.0
   1379     ]
   1380 
   1381     for v2 in [True, False]:
   1382       self._testMaxPoolGradDirect(
   1383           input_data,
   1384           output_backprop,
   1385           expected_input_backprop_cudnn,
   1386           input_sizes=[1, 4, 4, 1],
   1387           output_sizes=[1, 3, 3, 1],
   1388           window_rows=2,
   1389           window_cols=2,
   1390           row_stride=1,
   1391           col_stride=1,
   1392           padding="VALID",
   1393           use_gpu=True,
   1394           v2=v2)
   1395 
   1396     # Propagate the diff in cases of NaNs
   1397     os.environ["TF_ENABLE_MAXPOOL_NANPROP"] = "1"
   1398     expected_input_backprop_cudnn = expected_input_backprop_tf_cpu
   1399 
   1400     for v2 in [True, False]:
   1401       self._testMaxPoolGradDirect(
   1402           input_data,
   1403           output_backprop,
   1404           expected_input_backprop_cudnn,
   1405           input_sizes=[1, 4, 4, 1],
   1406           output_sizes=[1, 3, 3, 1],
   1407           window_rows=2,
   1408           window_cols=2,
   1409           row_stride=1,
   1410           col_stride=1,
   1411           padding="VALID",
   1412           use_gpu=True,
   1413           v2=v2)
   1414 
   1415     if saved_nanprop:
   1416       os.environ["TF_ENABLE_MAXPOOL_NANPROP"] = saved_nanprop
   1417     else:
   1418       del os.environ["TF_ENABLE_MAXPOOL_NANPROP"]
   1419 
   1420   def _testMaxPoolGradDirectWithNans2_2(self):
   1421     input_data = [float("nan")] * 16
   1422     output_backprop = [
   1423         float("nan"), 12.0, 13.0, 15.0,
   1424         float("nan"), 17.0, 19.0, 20.0,
   1425         float("nan")
   1426     ]
   1427     # Test the CPU implementation, which propagates diffs in case of NaN
   1428     expected_input_backprop_tf_cpu = [
   1429         float("nan"), 12.0, 13.0, 0.0, 15.0,
   1430         float("nan"), 17.0, 0.0, 19.0, 20.0,
   1431         float("nan"), 0.0, 0.0, 0.0, 0.0, 0.0
   1432     ]
   1433     for v2 in [True, False]:
   1434       self._testMaxPoolGradDirect(
   1435           input_data,
   1436           output_backprop,
   1437           expected_input_backprop_tf_cpu,
   1438           input_sizes=[1, 4, 4, 1],
   1439           output_sizes=[1, 3, 3, 1],
   1440           window_rows=2,
   1441           window_cols=2,
   1442           row_stride=1,
   1443           col_stride=1,
   1444           padding="VALID",
   1445           use_gpu=False,
   1446           v2=v2)
   1447 
   1448     if not test.is_gpu_available():
   1449       return
   1450 
   1451     # Test the GPU implementation that uses cudnn for now.
   1452     saved_nanprop = os.environ.get("TF_ENABLE_MAXPOOL_NANPROP")
   1453     # Do not propagate the diff in cases of NaNs
   1454     os.environ["TF_ENABLE_MAXPOOL_NANPROP"] = "0"
   1455     expected_input_backprop_cudnn = [
   1456         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
   1457         0.0, 0.0
   1458     ]
   1459 
   1460     for v2 in [True, False]:
   1461       self._testMaxPoolGradDirect(
   1462           input_data,
   1463           output_backprop,
   1464           expected_input_backprop_cudnn,
   1465           input_sizes=[1, 4, 4, 1],
   1466           output_sizes=[1, 3, 3, 1],
   1467           window_rows=2,
   1468           window_cols=2,
   1469           row_stride=1,
   1470           col_stride=1,
   1471           padding="VALID",
   1472           use_gpu=True,
   1473           v2=v2)
   1474 
   1475     # Propagate the diff in cases of NaNs
   1476     os.environ["TF_ENABLE_MAXPOOL_NANPROP"] = "1"
   1477     expected_input_backprop_cudnn = expected_input_backprop_tf_cpu
   1478 
   1479     for v2 in [True, False]:
   1480       self._testMaxPoolGradDirect(
   1481           input_data,
   1482           output_backprop,
   1483           expected_input_backprop_cudnn,
   1484           input_sizes=[1, 4, 4, 1],
   1485           output_sizes=[1, 3, 3, 1],
   1486           window_rows=2,
   1487           window_cols=2,
   1488           row_stride=1,
   1489           col_stride=1,
   1490           padding="VALID",
   1491           use_gpu=True,
   1492           v2=v2)
   1493 
   1494     if saved_nanprop:
   1495       os.environ["TF_ENABLE_MAXPOOL_NANPROP"] = saved_nanprop
   1496     else:
   1497       del os.environ["TF_ENABLE_MAXPOOL_NANPROP"]
   1498 
   1499   def testMaxPoolGradDirect(self):
   1500     self._testMaxPoolGradDirect1_1()
   1501     self._testMaxPoolGradDirect1_2()
   1502     self._testMaxPoolGradDirect1_3()
   1503     self._testMaxPoolGradDirectWithNans2_1()
   1504     self._testMaxPoolGradDirectWithNans2_2()
   1505 
   1506   def _testMaxPoolGradGradValidPadding1_1(self, data_format, use_gpu):
   1507     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1508       self._ConstructAndTestSecondGradient(
   1509           pool_func,
   1510           input_sizes=[1, 3, 3, 1],
   1511           output_sizes=[1, 3, 3, 1],
   1512           window_rows=1,
   1513           window_cols=1,
   1514           row_stride=1,
   1515           col_stride=1,
   1516           padding="VALID",
   1517           data_format=data_format,
   1518           use_gpu=use_gpu)
   1519 
   1520   def _testMaxPoolGradGradValidPadding2_1_6(self, data_format, use_gpu):
   1521     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1522       self._ConstructAndTestSecondGradient(
   1523           pool_func,
   1524           input_sizes=[2, 6, 6, 3],
   1525           output_sizes=[2, 5, 5, 3],
   1526           window_rows=2,
   1527           window_cols=2,
   1528           row_stride=1,
   1529           col_stride=1,
   1530           padding="VALID",
   1531           data_format=data_format,
   1532           use_gpu=use_gpu)
   1533 
   1534   def _testMaxPoolGradGradValidPadding2_1_7(self, data_format, use_gpu):
   1535     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1536       self._ConstructAndTestSecondGradient(
   1537           pool_func,
   1538           input_sizes=[2, 7, 7, 3],
   1539           output_sizes=[2, 6, 6, 3],
   1540           window_rows=2,
   1541           window_cols=2,
   1542           row_stride=1,
   1543           col_stride=1,
   1544           padding="VALID",
   1545           data_format=data_format,
   1546           use_gpu=use_gpu)
   1547 
   1548   def _testMaxPoolGradGradValidPadding2_2(self, data_format, use_gpu):
   1549     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1550       self._ConstructAndTestSecondGradient(
   1551           pool_func,
   1552           input_sizes=[2, 2, 2, 3],
   1553           output_sizes=[2, 1, 1, 3],
   1554           window_rows=2,
   1555           window_cols=2,
   1556           row_stride=2,
   1557           col_stride=2,
   1558           padding="VALID",
   1559           data_format=data_format,
   1560           use_gpu=use_gpu)
   1561 
   1562   def _testMaxPoolGradGradSamePadding1_1(self, data_format, use_gpu):
   1563     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1564       self._ConstructAndTestSecondGradient(
   1565           pool_func,
   1566           input_sizes=[2, 2, 4, 3],
   1567           output_sizes=[2, 2, 4, 3],
   1568           window_rows=1,
   1569           window_cols=1,
   1570           row_stride=1,
   1571           col_stride=1,
   1572           padding="SAME",
   1573           data_format=data_format,
   1574           use_gpu=use_gpu)
   1575 
   1576   def _testMaxPoolGradGradSamePadding2_1(self, data_format, use_gpu):
   1577     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1578       self._ConstructAndTestSecondGradient(
   1579           pool_func,
   1580           input_sizes=[2, 2, 4, 3],
   1581           output_sizes=[2, 2, 4, 3],
   1582           window_rows=2,
   1583           window_cols=2,
   1584           row_stride=1,
   1585           col_stride=1,
   1586           padding="SAME",
   1587           data_format=data_format,
   1588           use_gpu=use_gpu)
   1589 
   1590   def _testMaxPoolGradGradSamePadding2_2(self, data_format, use_gpu):
   1591     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1592       self._ConstructAndTestSecondGradient(
   1593           pool_func,
   1594           input_sizes=[2, 2, 4, 3],
   1595           output_sizes=[2, 1, 2, 3],
   1596           window_rows=2,
   1597           window_cols=2,
   1598           row_stride=2,
   1599           col_stride=2,
   1600           padding="SAME",
   1601           data_format=data_format,
   1602           use_gpu=use_gpu)
   1603 
   1604   def _testMaxPoolGradGradSamePadding3_1(self, data_format, use_gpu):
   1605     for pool_func in [gen_nn_ops._max_pool_v2, nn_ops.max_pool]:
   1606       self._ConstructAndTestSecondGradient(
   1607           pool_func,
   1608           input_sizes=[1, 7, 7, 1],
   1609           output_sizes=[1, 7, 7, 1],
   1610           window_rows=3,
   1611           window_cols=3,
   1612           row_stride=1,
   1613           col_stride=1,
   1614           padding="SAME",
   1615           data_format=data_format,
   1616           use_gpu=use_gpu)
   1617 
   1618   def testMaxPoolGradGrad(self):
   1619     for (data_format, use_gpu) in GetTestConfigs():
   1620       self._testMaxPoolGradGradValidPadding1_1(data_format, use_gpu)
   1621       self._testMaxPoolGradGradValidPadding2_1_6(data_format, use_gpu)
   1622       self._testMaxPoolGradGradValidPadding2_1_7(data_format, use_gpu)
   1623       self._testMaxPoolGradGradValidPadding2_2(data_format, use_gpu)
   1624       self._testMaxPoolGradGradSamePadding1_1(data_format, use_gpu)
   1625       self._testMaxPoolGradGradSamePadding2_1(data_format, use_gpu)
   1626       self._testMaxPoolGradGradSamePadding2_2(data_format, use_gpu)
   1627       self._testMaxPoolGradGradSamePadding3_1(data_format, use_gpu)
   1628 
   1629   def _MaxPoolGradGrad(self, orig_input, orig_output, grad, window_rows,
   1630                        window_cols, row_stride, col_stride, padding):
   1631     """Max Pooling Second-Order Gradient.
   1632 
   1633     Args:
   1634       orig_input: A float Tensor. The original input tensor.
   1635       orig_output: A float Tensor. The original output tensor.
   1636       grad: A float Tensor.
   1637         The 4D (batch x out_rows x out_cols x depth) output backprop.
   1638       window_rows: integer. Kernel size along rows dimension.
   1639       window_cols: integer. Kernel size along cols dimension.
   1640       row_stride: integer. Stride along rows dimension
   1641       col_stride: integer. Stride along cols dimension
   1642       padding: PoolingOpDef.Padding.  Padding type.
   1643 
   1644     Returns:
   1645       A Tensor.
   1646     """
   1647     return gen_nn_ops._max_pool_grad_grad(
   1648         orig_input, orig_output, grad, [1, window_rows, window_cols, 1],
   1649         [1, row_stride, col_stride, 1], padding)
   1650 
   1651   def testAvgPoolGrad(self):
   1652     for (data_format, use_gpu) in GetTestConfigs():
   1653       self._testAvgPoolGradValidPadding1_1(data_format, use_gpu)
   1654       self._testAvgPoolGradValidPadding1_2(data_format, use_gpu)
   1655       self._testAvgPoolGradValidPadding2_1(data_format, use_gpu)
   1656       self._testAvgPoolGradValidPadding2_2(data_format, use_gpu)
   1657       self._testAvgPoolGradSamePadding1_1(data_format, use_gpu)
   1658       self._testAvgPoolGradSamePadding1_2(data_format, use_gpu)
   1659       self._testAvgPoolGradSamePadding2_1(data_format, use_gpu)
   1660       self._testAvgPoolGradSamePadding2_2(data_format, use_gpu)
   1661       self._testAvgPoolGradSamePadding3_1(data_format, use_gpu)
   1662 
   1663   def _testAvgPoolGradValidPadding1_1(self, data_format, use_gpu):
   1664     self._ConstructAndTestGradient(
   1665         nn_ops.avg_pool,
   1666         input_sizes=[2, 3, 3, 3],
   1667         output_sizes=[2, 3, 3, 3],
   1668         window_rows=1,
   1669         window_cols=1,
   1670         row_stride=1,
   1671         col_stride=1,
   1672         padding="VALID",
   1673         data_format=data_format,
   1674         use_gpu=use_gpu)
   1675 
   1676   def _testAvgPoolGradValidPadding1_2(self, data_format, use_gpu):
   1677     self._ConstructAndTestGradient(
   1678         nn_ops.avg_pool,
   1679         input_sizes=[2, 3, 3, 3],
   1680         output_sizes=[2, 2, 2, 3],
   1681         window_rows=1,
   1682         window_cols=1,
   1683         row_stride=2,
   1684         col_stride=2,
   1685         padding="VALID",
   1686         data_format=data_format,
   1687         use_gpu=use_gpu)
   1688 
   1689   def _testAvgPoolGradValidPadding2_1(self, data_format, use_gpu):
   1690     self._ConstructAndTestGradient(
   1691         nn_ops.avg_pool,
   1692         input_sizes=[2, 3, 3, 3],
   1693         output_sizes=[2, 2, 2, 3],
   1694         window_rows=2,
   1695         window_cols=2,
   1696         row_stride=1,
   1697         col_stride=1,
   1698         padding="VALID",
   1699         data_format=data_format,
   1700         use_gpu=use_gpu)
   1701 
   1702   def _testAvgPoolGradValidPadding2_2(self, data_format, use_gpu):
   1703     self._ConstructAndTestGradient(
   1704         nn_ops.avg_pool,
   1705         input_sizes=[2, 2, 2, 3],
   1706         output_sizes=[2, 1, 1, 3],
   1707         window_rows=2,
   1708         window_cols=2,
   1709         row_stride=2,
   1710         col_stride=2,
   1711         padding="VALID",
   1712         data_format=data_format,
   1713         use_gpu=use_gpu)
   1714 
   1715   def _testAvgPoolGradSamePadding1_1(self, data_format, use_gpu):
   1716     self._ConstructAndTestGradient(
   1717         nn_ops.avg_pool,
   1718         input_sizes=[2, 2, 4, 3],
   1719         output_sizes=[2, 2, 4, 3],
   1720         window_rows=1,
   1721         window_cols=1,
   1722         row_stride=1,
   1723         col_stride=1,
   1724         padding="SAME",
   1725         data_format=data_format,
   1726         use_gpu=use_gpu)
   1727 
   1728   def _testAvgPoolGradSamePadding1_2(self, data_format, use_gpu):
   1729     self._ConstructAndTestGradient(
   1730         nn_ops.avg_pool,
   1731         input_sizes=[2, 2, 4, 3],
   1732         output_sizes=[2, 1, 2, 3],
   1733         window_rows=1,
   1734         window_cols=1,
   1735         row_stride=2,
   1736         col_stride=2,
   1737         padding="SAME",
   1738         data_format=data_format,
   1739         use_gpu=use_gpu)
   1740 
   1741   def _testAvgPoolGradSamePadding2_1(self, data_format, use_gpu):
   1742     self._ConstructAndTestGradient(
   1743         nn_ops.avg_pool,
   1744         input_sizes=[2, 2, 4, 3],
   1745         output_sizes=[2, 2, 4, 3],
   1746         window_rows=2,
   1747         window_cols=2,
   1748         row_stride=1,
   1749         col_stride=1,
   1750         padding="SAME",
   1751         data_format=data_format,
   1752         use_gpu=use_gpu)
   1753 
   1754   def _testAvgPoolGradSamePadding2_2(self, data_format, use_gpu):
   1755     self._ConstructAndTestGradient(
   1756         nn_ops.avg_pool,
   1757         input_sizes=[2, 2, 4, 3],
   1758         output_sizes=[2, 1, 2, 3],
   1759         window_rows=2,
   1760         window_cols=2,
   1761         row_stride=2,
   1762         col_stride=2,
   1763         padding="SAME",
   1764         data_format=data_format,
   1765         use_gpu=use_gpu)
   1766 
   1767   def _testAvgPoolGradSamePadding3_1(self, data_format, use_gpu):
   1768     self._ConstructAndTestGradient(
   1769         nn_ops.avg_pool,
   1770         input_sizes=[1, 7, 7, 1],
   1771         output_sizes=[1, 7, 7, 1],
   1772         window_rows=3,
   1773         window_cols=3,
   1774         row_stride=1,
   1775         col_stride=1,
   1776         padding="SAME",
   1777         data_format=data_format,
   1778         use_gpu=use_gpu)
   1779 
   1780   def testShapeFunctionEdgeCases(self):
   1781     # All shapes unknown.
   1782     for pool_func in [nn_ops.max_pool, nn_ops.avg_pool]:
   1783       p = pool_func(
   1784           array_ops.placeholder(dtypes.float32),
   1785           ksize=[1, 1, 1, 1],
   1786           strides=[1, 1, 1, 1],
   1787           padding="SAME")
   1788       self.assertEqual([None, None, None, None], p.get_shape().as_list())
   1789     p, am = nn_ops.max_pool_with_argmax(
   1790         array_ops.placeholder(dtypes.float32),
   1791         ksize=[1, 1, 1, 1],
   1792         strides=[1, 1, 1, 1],
   1793         padding="SAME")
   1794     self.assertEqual([None, None, None, None], p.get_shape().as_list())
   1795     self.assertEqual([None, None, None, None], am.get_shape().as_list())
   1796 
   1797     # Incorrect input shape.
   1798     for pool_func in [
   1799         nn_ops.max_pool, nn_ops.avg_pool, nn_ops.max_pool_with_argmax
   1800     ]:
   1801       with self.assertRaises(ValueError):
   1802         pool_func(
   1803             array_ops.placeholder(dtypes.float32, shape=[1, 3]),
   1804             ksize=[1, 1, 1, 1],
   1805             strides=[1, 1, 1, 1],
   1806             padding="SAME")
   1807 
   1808   def testOpEdgeCases(self):
   1809     with self.test_session(use_gpu=test.is_gpu_available()) as sess:
   1810       pool_funcs = [nn_ops.max_pool, nn_ops.avg_pool]
   1811       if test.is_gpu_available():
   1812         pool_funcs.append(nn_ops.max_pool_with_argmax)
   1813       for pool_func in pool_funcs:
   1814         if pool_func != nn_ops.max_pool:
   1815           # Illegal strides.
   1816           with self.assertRaisesRegexp(
   1817               errors_impl.UnimplementedError,
   1818               "Pooling is not yet supported on the batch"):
   1819             sess.run(
   1820                 pool_func(
   1821                     array_ops.placeholder(dtypes.float32),
   1822                     ksize=[1, 1, 1, 1],
   1823                     strides=[2, 1, 1, 1],
   1824                     padding="SAME"))
   1825 
   1826         # Filter too large.
   1827         with self.assertRaisesRegexp(ValueError, "Negative dimension size"):
   1828           sess.run(
   1829               pool_func(
   1830                   array_ops.placeholder(dtypes.float32, shape=[32, 20, 20, 3]),
   1831                   ksize=[1, 20, 21, 1],
   1832                   strides=[1, 1, 1, 1],
   1833                   padding="VALID"))
   1834         with self.assertRaisesRegexp(ValueError, "Negative dimension size"):
   1835           pool_func(
   1836               array_ops.placeholder(dtypes.float32, shape=[32, 20, 20, 3]),
   1837               ksize=[1, 21, 20, 1],
   1838               strides=[1, 1, 1, 1],
   1839               padding="VALID")
   1840 
   1841 
   1842 def GetMaxPoolFwdTest(input_size, filter_size, strides, padding):
   1843 
   1844   def Test(self):
   1845     # MaxPoolWithArgMax is implemented only on CUDA.
   1846     if not test.is_gpu_available(cuda_only=True):
   1847       return
   1848     self._CompareMaxPoolingFwd(input_size, filter_size, strides, padding)
   1849 
   1850   return Test
   1851 
   1852 
   1853 def GetMaxPoolGradTest(input_size, filter_size, output_size, strides, padding):
   1854 
   1855   def Test(self):
   1856     # MaxPoolWithArgMax is implemented only on CUDA.
   1857     if not test.is_gpu_available(cuda_only=True):
   1858       return
   1859     self._CompareMaxPoolingBk(input_size, output_size, filter_size, strides,
   1860                               padding)
   1861 
   1862   return Test
   1863 
   1864 
   1865 def GetMaxPoolGradGradTest(input_size, filter_size, output_size, strides,
   1866                            padding):
   1867 
   1868   def Test(self):
   1869     # MaxPoolWithArgMax is implemented only on CUDA.
   1870     if not test.is_gpu_available(cuda_only=True):
   1871       return
   1872     self._CompareMaxPoolingGradBk(input_size, output_size, filter_size, strides,
   1873                                   padding)
   1874 
   1875   return Test
   1876 
   1877 
   1878 if __name__ == "__main__":
   1879   for (name_, input_size_, filter_size_, output_size_, stride_,
   1880        padding_) in GetShrunkInceptionMaxPoolShapes():
   1881     setattr(PoolingTest, "testMaxPoolFwd_" + name_,
   1882             GetMaxPoolFwdTest(input_size_, filter_size_, stride_, padding_))
   1883     setattr(PoolingTest, "testMaxPoolGrad_" + name_,
   1884             GetMaxPoolGradTest(input_size_, filter_size_, output_size_, stride_,
   1885                                padding_))
   1886     setattr(PoolingTest, "testMaxPoolGradGrad_" + name_,
   1887             GetMaxPoolGradGradTest(input_size_, filter_size_, output_size_,
   1888                                    stride_, padding_))
   1889   test.main()
   1890