pooling_ops_test.py revision 9bedadceab3e126684494e6e6a8103ccab9d90c7
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 16"""Functional tests for pooling operations.""" 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import print_function 20 21import numpy as np 22import tensorflow as tf 23 24from tensorflow.python.framework import test_util 25from tensorflow.python.ops import gen_nn_ops 26 27 28def NHWCToNCHW(input_tensor): 29 """Convert the input from NHWC format to NCHW. 30 31 Args: 32 input_tensor: a 4-D tensor, or a 4-element array representing the same. 33 34 Returns: 35 the converted tensor or a shape array 36 """ 37 if isinstance(input_tensor, tf.Tensor): 38 return tf.transpose(input_tensor, [0, 3, 1, 2]) 39 else: 40 return [input_tensor[0], input_tensor[3], input_tensor[1], input_tensor[2]] 41 42 43def NCHWToNHWC(input_tensor): 44 """Convert the input from NCHW format to NHWC. 45 46 Args: 47 input_tensor: a 4-D tensor, or a 4-element array representing the same. 48 49 Returns: 50 the converted tensor or a shape array 51 """ 52 if isinstance(input_tensor, tf.Tensor): 53 return tf.transpose(input_tensor, [0, 2, 3, 1]) 54 else: 55 return [input_tensor[0], input_tensor[2], input_tensor[3], input_tensor[1]] 56 57 58def GetTestConfigs(): 59 """Get all the valid tests configs to run. 60 61 Returns: 62 all the valid test configs as tuples of data_format and use_gpu. 63 """ 64 test_configs = [("NHWC", False), ("NHWC", True)] 65 if test_util.IsGoogleCudaEnabled(): 66 # "NCHW" format is not currently supported on CPU. 67 test_configs += [("NCHW", True)] 68 return test_configs 69 70 71def GetShrunkInceptionMaxPoolShapes(shrink=30): 72 """Iterator for some of the max pool ops in the Inception 2015 model. 73 74 Args: 75 shrink: Factor to shrink depth relative to Inception. 76 77 Yields: 78 Tuple (name, input_size, filter_size, out_size, strides, padding) 79 """ 80 names = ["maxpool2", "maxpool3", "maxpool4", "maxpool5"] 81 input_sizes = [[32, 71, 71, 192], 82 [32, 35, 35, 288], [32, 17, 17, 1248], [32, 8, 8, 2048]] 83 filter_sizes = [[1, 3, 3, 1], [1, 3, 3, 1], 84 [1, 3, 3, 1], [1, 3, 3, 1]] 85 output_sizes = [[32, 35, 35, 192], [32, 17, 17, 288], 86 [32, 8, 8, 1248], [32, 8, 8, 2048]] 87 strides = [[1, 2, 2, 1], [1, 2, 2, 1], [1, 2, 2, 1], 88 [1, 1, 1, 1]] 89 # Shrink each depth value 90 for i in input_sizes: 91 i[3] //= shrink 92 for o in output_sizes: 93 o[3] //= shrink 94 paddings = ["VALID", "VALID", "VALID", "SAME"] 95 for n, i, f, o, s, p in zip(names, input_sizes, filter_sizes, output_sizes, 96 strides, paddings): 97 yield n, i, f, o, s, p 98 99 100class PoolingTest(tf.test.TestCase): 101 102 def _VerifyOneType(self, pool_func, input_sizes, ksize, strides, padding, 103 data_format, data_type, expected, use_gpu): 104 """Verifies the output values of the pooling function. 105 106 Args: 107 pool_func: Function to be called, co.MaxPool, co.AvgPool, 108 or the Lua version. 109 input_sizes: Input tensor dimensions. 110 ksize: The kernel size dimensions 111 strides: The stride dimensions 112 padding: Padding type. 113 data_format: The data format we use to run the pooling operation. 114 data_type: The data type to use to run the pooling operation. 115 expected: An array containing the expected operation outputs. 116 use_gpu: Whether we are running on GPU. 117 """ 118 total_size = 1 119 for s in input_sizes: 120 total_size *= s 121 # Initializes the input tensor with array containing incrementing 122 # numbers from 1. 123 x = [f * 1.0 for f in range(1, total_size + 1)] 124 with self.test_session(use_gpu=use_gpu) as sess: 125 t = tf.constant(x, shape=input_sizes, dtype=data_type) 126 if data_format == "NCHW": 127 t = NHWCToNCHW(t) 128 ksize = NHWCToNCHW(ksize) 129 strides = NHWCToNCHW(strides) 130 t = pool_func(t, ksize=ksize, strides=strides, padding=padding, 131 data_format=data_format) 132 if data_format == "NCHW": 133 t = NCHWToNHWC(t) 134 actual = t.eval() 135 self.assertAllCloseAccordingToType(expected, actual.flatten()) 136 self.assertShapeEqual(actual, t) 137 138 def _VerifyOneTest(self, pool_func, input_sizes, ksize, strides, padding, 139 data_format, expected, use_gpu): 140 """Verifies the output values of the pooling function. 141 142 Args: 143 pool_func: Function to be called, co.MaxPool, co.AvgPool, 144 or the Lua version. 145 input_sizes: Input tensor dimensions. 146 ksize: The kernel size dimensions 147 strides: The stride dimensions 148 padding: Padding type. 149 data_format: The data format we use to run the pooling operation. 150 expected: An array containing the expected operation outputs. 151 use_gpu: Whether we are running on GPU. 152 """ 153 self._VerifyOneType(pool_func, input_sizes, ksize, strides, padding, 154 data_format, tf.float32, expected, use_gpu) 155 156 if not use_gpu or test_util.CudaSupportsHalfMatMulAndConv(): 157 self._VerifyOneType(pool_func, input_sizes, ksize, strides, padding, 158 data_format, tf.float16, expected, use_gpu) 159 160 def _VerifyValues(self, pool_func, input_sizes, ksize, strides, padding, 161 expected, use_gpu): 162 """Verifies the output values of the pooling function. 163 164 Args: 165 pool_func: Function to be called, co.MaxPool, co.AvgPool, 166 or the Lua version. 167 input_sizes: Input tensor dimensions. 168 ksize: The kernel size dimensions 169 strides: The stride dimensions 170 padding: Padding type. 171 expected: An array containing the expected operation outputs. 172 use_gpu: Whether we are running on GPU. 173 """ 174 for (data_format, use_gpu_2) in GetTestConfigs(): 175 if use_gpu_2 == use_gpu: 176 self._VerifyOneTest(pool_func, input_sizes, ksize, strides, padding, 177 data_format, expected, use_gpu) 178 179 def _testAvgPoolValidPadding(self, use_gpu): 180 expected_output = [7.0, 8.0, 9.0] 181 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 3, 3, 3], 182 ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], 183 padding="VALID", 184 expected=expected_output, use_gpu=use_gpu) 185 186 def _testAvgPoolSamePadding(self, use_gpu): 187 expected_output = [8.5, 9.5, 10.5, 14.5, 15.5, 16.5] 188 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 2, 4, 3], 189 ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], 190 padding="SAME", 191 expected=expected_output, use_gpu=use_gpu) 192 193 def _testAvgPoolSamePaddingNonSquareWindow(self, use_gpu): 194 # input is: 195 # [1.0, 2.0 196 # 3.0 4.0] 197 # 198 # Window of [x, x] should do: 199 # [avg(1.0, 2.0), avg(2.0, padded0), 200 # avg(3.0, 4.0), avg(4.0, padded0)] 201 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 2, 2, 1], 202 ksize=[1, 1, 2, 1], strides=[1, 1, 1, 1], 203 padding="SAME", 204 expected=[1.5, 2.0, 3.5, 4.0], use_gpu=use_gpu) 205 206 # Window of [x, 207 # x] should do: 208 # [avg(1.0, 3.0), avg(2.0, 4.0) 209 # avg(3.0, padded0), avg(4.0, padded0)] 210 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 2, 2, 1], 211 ksize=[1, 2, 1, 1], strides=[1, 1, 1, 1], 212 padding="SAME", 213 expected=[2.0, 3.0, 3.0, 4.0], use_gpu=use_gpu) 214 215 def _testAvgPoolSamePaddingNonSquareWindowMultiBatch(self, use_gpu): 216 self._VerifyValues(tf.nn.avg_pool, input_sizes=[2, 2, 2, 2], 217 ksize=[1, 1, 2, 1], strides=[1, 1, 1, 1], 218 padding="SAME", 219 expected=[2.0, 3.0, 3.0, 4.0, 220 6.0, 7.0, 7.0, 8.0, 221 10.0, 11.0, 11.0, 12.0, 222 14.0, 15.0, 15.0, 16.0], 223 use_gpu=use_gpu) 224 self._VerifyValues(tf.nn.avg_pool, input_sizes=[2, 2, 2, 2], 225 ksize=[1, 2, 1, 1], strides=[1, 1, 1, 1], 226 padding="SAME", 227 expected=[3.0, 4.0, 5.0, 6.0, 228 5.0, 6.0, 7.0, 8.0, 229 11.0, 12.0, 13.0, 14.0, 230 13.0, 14.0, 15.0, 16.0], 231 use_gpu=use_gpu) 232 233 def _testAvgPoolValidPaddingUnevenStride(self, use_gpu): 234 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 3, 3, 3], 235 ksize=[1, 2, 2, 1], strides=[1, 1, 2, 1], 236 padding="VALID", 237 expected=[7.0, 8.0, 9.0, 16.0, 17.0, 18.0], 238 use_gpu=use_gpu) 239 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 3, 3, 3], 240 ksize=[1, 2, 2, 1], strides=[1, 2, 1, 1], 241 padding="VALID", 242 expected=[7.0, 8.0, 9.0, 10.0, 11.0, 12.0], 243 use_gpu=use_gpu) 244 245 def _testAvgPoolSamePadding4(self, use_gpu): 246 expected_output = [11.0, 12.0, 13.0, 14.0, 19.0, 20.0, 21.0, 22.0, 43.0, 247 44.0, 45.0, 46.0, 51.0, 52.0, 53.0, 54.0] 248 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 4, 4, 4], 249 ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], 250 padding="SAME", 251 expected=expected_output, use_gpu=use_gpu) 252 253 def _testAvgPoolSamePaddingPacket4(self, use_gpu): 254 expected_output = [21.0, 22.0, 23.0, 24.0, 27.0, 28.0, 29.0, 30.0, 255 45.0, 46.0, 47.0, 48.0, 51.0, 52.0, 53.0, 54.0] 256 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 4, 4, 4], 257 ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], 258 padding="SAME", 259 expected=expected_output, use_gpu=use_gpu) 260 261 def _testAvgPoolSamePaddingPacket8(self, use_gpu): 262 expected_output = [73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0, 89.0, 263 90.0, 91.0, 92.0, 93.0, 94.0, 95.0, 96.0, 105.0, 106.0, 264 107.0, 108.0, 109.0, 110.0, 111.0, 112.0, 117.0, 118.0, 265 119.0, 120.0, 121.0, 122.0, 123.0, 124.0, 201.0, 202.0, 266 203.0, 204.0, 205.0, 206.0, 207.0, 208.0, 217.0, 218.0, 267 219.0, 220.0, 221.0, 222.0, 223.0, 224.0, 233.0, 234.0, 268 235.0, 236.0, 237.0, 238.0, 239.0, 240.0, 245.0, 246.0, 269 247.0, 248.0, 249.0, 250.0, 251.0, 252.0, 329.0, 330.0, 270 331.0, 332.0, 333.0, 334.0, 335.0, 336.0, 345.0, 346.0, 271 347.0, 348.0, 349.0, 350.0, 351.0, 352.0, 361.0, 362.0, 272 363.0, 364.0, 365.0, 366.0, 367.0, 368.0, 373.0, 374.0, 273 375.0, 376.0, 377.0, 378.0, 379.0, 380.0, 425.0, 426.0, 274 427.0, 428.0, 429.0, 430.0, 431.0, 432.0, 441.0, 442.0, 275 443.0, 444.0, 445.0, 446.0, 447.0, 448.0, 457.0, 458.0, 276 459.0, 460.0, 461.0, 462.0, 463.0, 464.0, 469.0, 470.0, 277 471.0, 472.0, 473.0, 474.0, 475.0, 476.0] 278 self._VerifyValues(tf.nn.avg_pool, input_sizes=[1, 8, 8, 8], 279 ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], 280 padding="SAME", 281 expected=expected_output, use_gpu=use_gpu) 282 283 def testAvgPooling(self): 284 for use_gpu in True, False: 285 self._testAvgPoolValidPadding(use_gpu) 286 self._testAvgPoolSamePadding(use_gpu) 287 self._testAvgPoolSamePaddingNonSquareWindow(use_gpu) 288 self._testAvgPoolSamePaddingNonSquareWindowMultiBatch(use_gpu) 289 self._testAvgPoolValidPaddingUnevenStride(use_gpu) 290 self._testAvgPoolSamePadding4(use_gpu) 291 self._testAvgPoolSamePaddingPacket4(use_gpu) 292 self._testAvgPoolSamePaddingPacket8(use_gpu) 293 294 def _testMaxPoolValidPadding(self, use_gpu): 295 expected_output = [13.0, 14.0, 15.0] 296 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 3, 3, 3], 297 ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], 298 padding="VALID", 299 expected=expected_output, use_gpu=use_gpu) 300 301 def _testMaxPoolSamePadding(self, use_gpu): 302 expected_output = [13.0, 14.0, 15.0, 16.0, 17.0, 18.0] 303 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 2, 3, 3], 304 ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], 305 padding="SAME", 306 expected=expected_output, use_gpu=use_gpu) 307 308 def _testMaxPoolSamePaddingNonSquareWindow(self, use_gpu): 309 # input is: 310 # [1.0, 2.0 311 # 3.0 4.0] 312 # 313 # Window of [x, x] should do: 314 # 315 # [max(1.0, 2.0), max(2.0, padded0), 316 # max(3.0, 4.0), max(4.0, padded0)] 317 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 2, 2, 1], 318 ksize=[1, 1, 2, 1], strides=[1, 1, 1, 1], 319 padding="SAME", 320 expected=[2.0, 2.0, 4.0, 4.0], use_gpu=use_gpu) 321 322 def _testMaxPoolValidPaddingUnevenStride(self, use_gpu): 323 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 4, 4, 1], 324 ksize=[1, 2, 2, 1], strides=[1, 1, 2, 1], 325 padding="VALID", 326 expected=[6.0, 8.0, 10.0, 12.0, 14.0, 16.0], 327 use_gpu=use_gpu) 328 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 4, 4, 1], 329 ksize=[1, 2, 2, 1], strides=[1, 2, 1, 1], 330 padding="VALID", 331 expected=[6.0, 7.0, 8.0, 14.0, 15.0, 16.0], 332 use_gpu=use_gpu) 333 334 def _testMaxPoolSamePaddingPacket4(self, use_gpu): 335 expected_output = [21.0, 22.0, 23.0, 24.0, 29.0, 30.0, 31.0, 32.0, 53.0, 336 54.0, 55.0, 56.0, 61.0, 62.0, 63.0, 64.0] 337 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 4, 4, 4], 338 ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], 339 padding="SAME", 340 expected=expected_output, use_gpu=use_gpu) 341 342 def _testMaxPoolSamePaddingPacket8(self, use_gpu): 343 expected_output = [145.0, 146.0, 147.0, 148.0, 149.0, 150.0, 151.0, 152.0, 344 161.0, 162.0, 163.0, 164.0, 165.0, 166.0, 167.0, 168.0, 345 177.0, 178.0, 179.0, 180.0, 181.0, 182.0, 183.0, 184.0, 346 185.0, 186.0, 187.0, 188.0, 189.0, 190.0, 191.0, 192.0, 347 273.0, 274.0, 275.0, 276.0, 277.0, 278.0, 279.0, 280.0, 348 289.0, 290.0, 291.0, 292.0, 293.0, 294.0, 295.0, 296.0, 349 305.0, 306.0, 307.0, 308.0, 309.0, 310.0, 311.0, 312.0, 350 313.0, 314.0, 315.0, 316.0, 317.0, 318.0, 319.0, 320.0, 351 401.0, 402.0, 403.0, 404.0, 405.0, 406.0, 407.0, 408.0, 352 417.0, 418.0, 419.0, 420.0, 421.0, 422.0, 423.0, 424.0, 353 433.0, 434.0, 435.0, 436.0, 437.0, 438.0, 439.0, 440.0, 354 441.0, 442.0, 443.0, 444.0, 445.0, 446.0, 447.0, 448.0, 355 465.0, 466.0, 467.0, 468.0, 469.0, 470.0, 471.0, 472.0, 356 481.0, 482.0, 483.0, 484.0, 485.0, 486.0, 487.0, 488.0, 357 497.0, 498.0, 499.0, 500.0, 501.0, 502.0, 503.0, 504.0, 358 505.0, 506.0, 507.0, 508.0, 509.0, 510.0, 511.0, 512.0] 359 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 8, 8, 8], 360 ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], 361 padding="SAME", 362 expected=expected_output, use_gpu=use_gpu) 363 364 def testMaxPooling(self): 365 for use_gpu in True, False: 366 self._testMaxPoolValidPadding(use_gpu) 367 self._testMaxPoolSamePadding(use_gpu) 368 self._testMaxPoolSamePaddingNonSquareWindow(use_gpu) 369 self._testMaxPoolValidPaddingUnevenStride(use_gpu) 370 self._testMaxPoolSamePaddingPacket4(use_gpu) 371 self._testMaxPoolSamePaddingPacket8(use_gpu) 372 373 # Tests for DepthwiseMaxPooling on CPU only. 374 def testDepthwiseMaxPool1x1DepthWindow1(self): 375 # input is: 376 # [1.0, ..., 10.0] along depth, 377 # 378 # We maxpool by depth in patches of 2. 379 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 1, 1, 10], 380 ksize=[1, 1, 1, 2], strides=[1, 1, 1, 2], 381 padding="SAME", 382 expected=[2.0, 4.0, 6.0, 8.0, 10.0], use_gpu=False) 383 384 def testDepthwiseMaxPool2x2DepthWindow3(self): 385 # input is: 386 # 387 # a 2x2x6 cube, and we depthwise max across 3 to produce a 2x2x2 388 # output. Each node has contiguous values, so the depthwise max 389 # should be multiples of 3.0. 390 self._VerifyValues(tf.nn.max_pool, input_sizes=[1, 2, 2, 6], 391 ksize=[1, 1, 1, 3], strides=[1, 1, 1, 3], 392 padding="SAME", 393 expected=[3.0, 6.0, 9.0, 12.0, 15.0, 18.0, 21.0, 24.0], 394 use_gpu=False) 395 396 def testKernelSmallerThanStrideValid(self): 397 for use_gpu in [True, False]: 398 self._VerifyValues(tf.nn.max_pool, 399 input_sizes=[1, 7, 7, 1], 400 ksize=[1, 2, 2, 1], 401 strides=[1, 3, 3, 1], 402 padding="VALID", 403 expected=[9, 12, 30, 33], 404 use_gpu=use_gpu) 405 406 self._VerifyValues(tf.nn.avg_pool, 407 input_sizes=[1, 7, 7, 1], 408 ksize=[1, 2, 2, 1], 409 strides=[1, 3, 3, 1], 410 padding="VALID", 411 expected=[5, 8, 26, 29], 412 use_gpu=use_gpu) 413 414 def testKernelSmallerThanStrideSame(self): 415 for use_gpu in [True, False]: 416 for pool_func in [tf.nn.max_pool, tf.nn.avg_pool]: 417 self._VerifyValues(pool_func, 418 input_sizes=[1, 3, 3, 1], 419 ksize=[1, 1, 1, 1], 420 strides=[1, 2, 2, 1], 421 padding="SAME", 422 expected=[1, 3, 7, 9], 423 use_gpu=use_gpu) 424 425 self._VerifyValues(pool_func, 426 input_sizes=[1, 4, 4, 1], 427 ksize=[1, 1, 1, 1], 428 strides=[1, 2, 2, 1], 429 padding="SAME", 430 expected=[1, 3, 9, 11], 431 use_gpu=use_gpu) 432 433 def _testDepthwiseMaxPoolInvalidConfig(self, in_size, ksize, strides, 434 error_msg, use_gpu=False): 435 t = tf.constant(1.0, shape=in_size) 436 with self.assertRaisesRegexp(ValueError, error_msg): 437 t = tf.nn.max_pool(t, ksize=ksize, strides=strides, padding="SAME") 438 439 def testDepthwiseMaxPoolInvalidConfigs(self): 440 self._testDepthwiseMaxPoolInvalidConfig( 441 [1, 2, 2, 4], [1, 2, 2, 2], 442 [1, 1, 1, 2], "exactly one of pooling across depth") 443 self._testDepthwiseMaxPoolInvalidConfig( 444 [1, 2, 2, 4], [1, 1, 1, 2], 445 [1, 1, 1, 1], "depth window to equal the depth stride") 446 self._testDepthwiseMaxPoolInvalidConfig( 447 [1, 2, 2, 4], [1, 1, 1, 3], 448 [1, 1, 1, 3], "evenly divide") 449 if tf.test.is_built_with_cuda(): 450 with self.test_session(use_gpu=True): 451 t = tf.constant(1.0, shape=[1, 2, 2, 4]) 452 with self.assertRaisesOpError("for CPU devices"): 453 tf.nn.max_pool(t, ksize=[1, 1, 1, 2], strides=[1, 1, 1, 2], 454 padding="SAME").eval() 455 456 # The following are tests that verify that the CPU and GPU implementations 457 # produce the same resuts. 458 def _CompareMaxPoolingFwd(self, input_shape, ksize, strides, padding): 459 for dtype in np.float32, np.float16: 460 tensor_input = np.random.rand(*input_shape).astype(dtype) 461 with self.test_session(use_gpu=True): 462 t = tf.constant(tensor_input, shape=input_shape) 463 out_op, _ = tf.nn.max_pool_with_argmax(t, ksize, strides, padding) 464 gpu_val = out_op.eval() 465 with self.test_session(use_gpu=False): 466 t = tf.constant(tensor_input, shape=input_shape) 467 out_op = tf.nn.max_pool(t, ksize, strides, padding) 468 cpu_val = out_op.eval() 469 self.assertAllCloseAccordingToType(cpu_val, gpu_val) 470 471 def _CompareMaxPoolingBk(self, input_shape, output_shape, ksize, strides, 472 padding): 473 for dtype in np.float32, np.float16: 474 # Generate numbers in a narrow range, so that there are many duplicates 475 # in the input. 476 tensor_input = np.random.random_integers(0, 3, input_shape).astype(dtype) 477 tensor_output = np.random.rand(*output_shape).astype(dtype) 478 with self.test_session(use_gpu=True): 479 t = tf.constant(tensor_input, shape=input_shape) 480 _, argmax_op = tf.nn.max_pool_with_argmax(t, ksize, strides, padding) 481 argmax = argmax_op.eval() 482 grad_in = tf.constant(tensor_output, shape=output_shape) 483 out_op = gen_nn_ops._max_pool_grad_with_argmax(t, grad_in, argmax, 484 ksize, strides, padding) 485 gpu_val = out_op.eval() 486 self.assertShapeEqual(gpu_val, out_op) 487 with self.test_session(use_gpu=False): 488 t = tf.constant(tensor_input, shape=input_shape) 489 out_op = tf.nn.max_pool(t, ksize, strides, padding) 490 orig_out = out_op.eval() 491 grad_in = tf.constant(tensor_output, shape=output_shape) 492 out_op = gen_nn_ops._max_pool_grad(t, orig_out, grad_in, ksize, strides, 493 padding) 494 cpu_val = out_op.eval() 495 self.assertShapeEqual(cpu_val, out_op) 496 if dtype == np.float16: 497 # The CPU version accumulates its gradient on fp16, so it's less 498 # accurate than the GPU version that does the accumulation on fp32 499 self.assertAllClose(cpu_val, gpu_val, rtol=0.01, atol=0.01) 500 else: 501 self.assertAllClose(cpu_val, gpu_val) 502 503 504 def testMaxPoolingWithArgmax(self): 505 # MaxPoolWithArgMax is implemented only on GPU. 506 if not tf.test.is_built_with_cuda(): 507 return 508 tensor_input = [1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0] 509 with self.test_session(use_gpu=True) as sess: 510 t = tf.constant(tensor_input, shape=[1, 3, 3, 1]) 511 out_op, argmax_op = tf.nn.max_pool_with_argmax(t, 512 ksize=[1, 2, 2, 1], 513 strides=[1, 1, 1, 1], 514 Targmax=tf.int64, 515 padding="VALID") 516 out, argmax = sess.run([out_op, argmax_op]) 517 self.assertShapeEqual(out, out_op) 518 self.assertShapeEqual(argmax, argmax_op) 519 self.assertAllClose(out.ravel(), [1.0, 1.0, 1.0, 1.0]) 520 self.assertAllEqual(argmax.ravel(), [0, 1, 3, 5]) 521 522 def testMaxPoolingGradWithArgmax(self): 523 # MaxPoolWithArgMax is implemented only on GPU. 524 if not tf.test.is_built_with_cuda(): 525 return 526 orig_input = [1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0] 527 tensor_input = [11.0, 12.0, 13.0, 14.0] 528 tensor_argmax = list(np.array([0, 1, 3, 5], dtype=np.int64)) 529 with self.test_session(use_gpu=True) as sess: 530 orig_in = tf.constant(orig_input, shape=[1, 3, 3, 1]) 531 t = tf.constant(tensor_input, shape=[1, 2, 2, 1]) 532 argmax = tf.constant(tensor_argmax, shape=[1, 2, 2, 1], 533 dtype=tf.int64) 534 out_op = gen_nn_ops._max_pool_grad_with_argmax(orig_in, t, argmax, 535 ksize=[1, 2, 2, 1], 536 strides=[1, 1, 1, 1], 537 padding="VALID") 538 out = out_op.eval().flatten() 539 self.assertAllClose(out, [11.0, 12.0, 0.0, 13.0, 0.0, 540 14.0, 0.0, 0.0, 0.0]) 541 542 def _ConstructAndTestGradient(self, pool_func, input_sizes, output_sizes, 543 window_rows, window_cols, row_stride, 544 col_stride, padding, data_format, use_gpu, 545 x_init_value=None): 546 """Verifies the gradients of the avg pooling function. 547 548 Args: 549 pool_func: Function to be called, co.MaxPool, co.AvgPool, 550 or the Lua version. 551 input_sizes: Input tensor dimensions. 552 output_sizes: Output tensor dimensions. 553 window_rows: kernel size in row dim 554 window_cols: kernel size in col dim 555 row_stride: Row Stride. 556 col_stride: Col Stride. 557 padding: Padding type. 558 data_format: Data format. 559 use_gpu: whether we are running on GPU 560 x_init_value: Values to be passed to the gradient checker. 561 """ 562 assert input_sizes[0] == output_sizes[0] 563 assert input_sizes[3] == output_sizes[3] 564 total_size = 1 565 for s in input_sizes: 566 total_size *= s 567 # Initializes the input tensor with array containing incrementing 568 # numbers from 1. 569 x = [f * 1.0 for f in range(1, total_size + 1)] 570 with self.test_session(use_gpu=use_gpu): 571 input_tensor = tf.constant(x, shape=input_sizes, name="input") 572 if pool_func == tf.nn.avg_pool: 573 func_name = "avg_pool" 574 err_margin = 1e-4 575 else: 576 if x_init_value is None: 577 x_init_value = np.asfarray( 578 np.arange(1, total_size + 1), 579 dtype=np.float32).reshape(input_sizes) 580 func_name = "max_pool" 581 err_margin = 1e-3 582 if data_format == "NCHW": 583 ksize = [1, 1, window_rows, window_rows] 584 strides = [1, 1, row_stride, col_stride] 585 t = NHWCToNCHW(input_tensor) 586 else: 587 ksize = [1, window_rows, window_rows, 1] 588 strides = [1, row_stride, col_stride, 1] 589 t = input_tensor 590 t = pool_func(t, ksize=ksize, strides=strides, padding=padding, 591 data_format=data_format, name=func_name) 592 if data_format == "NCHW": 593 t = NCHWToNHWC(t) 594 595 err = tf.test.compute_gradient_error(input_tensor, 596 input_sizes, 597 t, 598 output_sizes, 599 x_init_value=x_init_value, 600 delta=1e-2) 601 print("%s gradient error = " % func_name, err) 602 self.assertLess(err, err_margin) 603 604 def _testMaxPoolGradValidPadding1_1(self, data_format, use_gpu): 605 self._ConstructAndTestGradient( 606 tf.nn.max_pool, input_sizes=[1, 3, 3, 1], 607 output_sizes=[1, 3, 3, 1], window_rows=1, window_cols=1, row_stride=1, 608 col_stride=1, padding="VALID", data_format=data_format, use_gpu=use_gpu) 609 610 def _testMaxPoolGradValidPadding2_1_6(self, data_format, use_gpu): 611 self._ConstructAndTestGradient( 612 tf.nn.max_pool, input_sizes=[2, 6, 6, 3], 613 output_sizes=[2, 5, 5, 3], window_rows=2, window_cols=2, row_stride=1, 614 col_stride=1, padding="VALID", data_format=data_format, use_gpu=use_gpu) 615 616 def _testMaxPoolGradValidPadding2_1_7(self, data_format, use_gpu): 617 self._ConstructAndTestGradient( 618 tf.nn.max_pool, input_sizes=[2, 7, 7, 3], 619 output_sizes=[2, 6, 6, 3], window_rows=2, window_cols=2, row_stride=1, 620 col_stride=1, padding="VALID", data_format=data_format, use_gpu=use_gpu) 621 622 def _testMaxPoolGradValidPadding2_2(self, data_format, use_gpu): 623 self._ConstructAndTestGradient( 624 tf.nn.max_pool, input_sizes=[2, 2, 2, 3], 625 output_sizes=[2, 1, 1, 3], window_rows=2, window_cols=2, row_stride=2, 626 col_stride=2, padding="VALID", data_format=data_format, use_gpu=use_gpu) 627 628 def _testMaxPoolGradSamePadding1_1(self, data_format, use_gpu): 629 self._ConstructAndTestGradient( 630 tf.nn.max_pool, input_sizes=[2, 2, 4, 3], 631 output_sizes=[2, 2, 4, 3], window_rows=1, window_cols=1, row_stride=1, 632 col_stride=1, padding="SAME", data_format=data_format, use_gpu=use_gpu) 633 634 def _testMaxPoolGradSamePadding2_1(self, data_format, use_gpu): 635 self._ConstructAndTestGradient( 636 tf.nn.max_pool, input_sizes=[2, 2, 4, 3], 637 output_sizes=[2, 2, 4, 3], window_rows=2, window_cols=2, row_stride=1, 638 col_stride=1, padding="SAME", data_format=data_format, use_gpu=use_gpu) 639 640 def _testMaxPoolGradSamePadding2_2(self, data_format, use_gpu): 641 self._ConstructAndTestGradient( 642 tf.nn.max_pool, input_sizes=[2, 2, 4, 3], 643 output_sizes=[2, 1, 2, 3], window_rows=2, window_cols=2, row_stride=2, 644 col_stride=2, padding="SAME", data_format=data_format, use_gpu=use_gpu) 645 646 def _testMaxPoolGradSamePadding3_1(self, data_format, use_gpu): 647 self._ConstructAndTestGradient( 648 tf.nn.max_pool, input_sizes=[1, 7, 7, 1], 649 output_sizes=[1, 7, 7, 1], window_rows=3, window_cols=3, row_stride=1, 650 col_stride=1, padding="SAME", data_format=data_format, use_gpu=use_gpu) 651 652 def testMaxPoolGrad(self): 653 for (data_format, use_gpu) in GetTestConfigs(): 654 self._testMaxPoolGradValidPadding1_1(data_format, use_gpu) 655 self._testMaxPoolGradValidPadding2_1_6(data_format, use_gpu) 656 self._testMaxPoolGradValidPadding2_1_7(data_format, use_gpu) 657 self._testMaxPoolGradValidPadding2_2(data_format, use_gpu) 658 self._testMaxPoolGradSamePadding1_1(data_format, use_gpu) 659 self._testMaxPoolGradSamePadding2_1(data_format, use_gpu) 660 self._testMaxPoolGradSamePadding2_2(data_format, use_gpu) 661 self._testMaxPoolGradSamePadding3_1(data_format, use_gpu) 662 663 def _MaxPoolGrad(self, orig_input, orig_output, grad, window_rows, 664 window_cols, row_stride, col_stride, padding): 665 """Max Pooling Gradient. 666 667 Args: 668 orig_input: A float Tensor. The original input tensor. 669 orig_output: A float Tensor. The original output tensor. 670 grad: A float Tensor. 671 The 4D (batch x rows x cols x depth) output backprop. 672 window_rows: integer. Kernel size along rows dimension. 673 window_cols: integer. Kernel size along cols dimension. 674 row_stride: integer. Stride along rows dimension 675 col_stride: integer. Stride along cols dimension 676 padding: PoolingOpDef.Padding. Padding type. 677 678 Returns: 679 A Tensor. 680 """ 681 return gen_nn_ops._max_pool_grad( 682 orig_input, orig_output, grad, 683 [1, window_rows, window_cols, 1], [1, row_stride, col_stride, 1], 684 padding) 685 686 def _testMaxPoolGradDirect(self, input_data, output_backprop, 687 expected_input_backprop, input_sizes, output_sizes, 688 window_rows, window_cols, row_stride, col_stride, 689 padding, use_gpu): 690 with self.test_session(use_gpu=use_gpu) as sess: 691 input_tensor = tf.constant(input_data, shape=input_sizes) 692 output_tensor = tf.nn.max_pool( 693 input_tensor, [1, window_rows, window_cols, 1], 694 [1, row_stride, col_stride, 1], padding) 695 output_backprop_tensor = tf.constant(output_backprop, 696 shape=output_sizes) 697 698 input_backprop_tensor = self._MaxPoolGrad( 699 input_tensor, output_tensor, output_backprop_tensor, 700 window_rows, window_cols, row_stride, col_stride, padding) 701 702 actual_input_backprop = input_backprop_tensor.eval() 703 self.assertShapeEqual(actual_input_backprop, input_backprop_tensor) 704 actual_input_backprop = actual_input_backprop.flatten() 705 actual_input_backprop = self._GetNdArray(actual_input_backprop) 706 707 actual_output = output_tensor.eval().flatten() 708 actual_output = self._GetNdArray(actual_output) 709 710 self.assertAllClose(expected_input_backprop, actual_input_backprop, 711 rtol=1e-6, atol=1e-6) 712 713 def _testMaxPoolGradDirect1_1(self): 714 input_data = [ 715 1.0, 1.0, 1.0, 1.0, 716 1.0, 1.0, 1.0, 1.0, 717 1.0, 1.0, 1.0, 1.0, 718 1.0, 1.0, 1.0, 1.0] 719 output_backprop = [ 720 11.0, 12.0, 13.0, 721 15.0, 16.0, 17.0, 722 19.0, 20.0, 21.0] 723 expected_input_backprop = [ 724 11.0, 12.0, 13.0, 0.0, 725 15.0, 16.0, 17.0, 0.0, 726 19.0, 20.0, 21.0, 0.0, 727 0.0, 0.0, 0.0, 0.0] 728 729 for use_gpu in True, False: 730 self._testMaxPoolGradDirect( 731 input_data, output_backprop, expected_input_backprop, 732 input_sizes=[1, 4, 4, 1], output_sizes=[1, 3, 3, 1], 733 window_rows=2, window_cols=2, row_stride=1, col_stride=1, 734 padding="VALID", use_gpu=use_gpu) 735 736 def _testMaxPoolGradDirect1_2(self): 737 input_data = [ 738 1.0, 0.0, 1.0, 0.0, 739 0.0, 1.0, 0.0, 1.0, 740 1.0, 0.0, 1.0, 0.0, 741 0.0, 1.0, 0.0, 1.0] 742 output_backprop = [ 743 11.0, 12.0, 13.0, 744 15.0, 16.0, 17.0, 745 19.0, 20.0, 21.0] 746 expected_input_backprop = [ 747 11.0, 0.0, 25.0, 0.0, 748 0.0, 31.0, 0.0, 17.0, 749 19.0, 0.0, 41.0, 0.0, 750 0.0, 0.0, 0.0, 0.0] 751 752 for use_gpu in True, False: 753 self._testMaxPoolGradDirect( 754 input_data, output_backprop, expected_input_backprop, 755 input_sizes=[1, 4, 4, 1], output_sizes=[1, 3, 3, 1], 756 window_rows=2, window_cols=2, row_stride=1, col_stride=1, 757 padding="VALID", use_gpu=use_gpu) 758 759 def _testMaxPoolGradDirect1_3(self): 760 input_data = [ 761 1.0, 0.0, 1.0, 0.0, 762 0.0, 1.0, 0.0, 1.0, 763 1.0, 0.0, 1.0, 0.0, 764 0.0, 1.0, 0.0, 1.0,] 765 output_backprop = [ 766 11.0, 12.0, 13.0, 14.0, 767 15.0, 16.0, 17.0, 18.0, 768 19.0, 20.0, 21.0, 22.0, 769 23.0, 24.0, 25.0, 26.0] 770 expected_input_backprop = [ 771 54, 0.0, 62, 0.0, 772 0.0, 60, 0.0, 22.0, 773 47, 0.0, 51, 0.0, 774 0.0, 0.0, 0.0, 0.0,] 775 776 for use_gpu in True, False: 777 self._testMaxPoolGradDirect( 778 input_data, output_backprop, expected_input_backprop, 779 input_sizes=[1, 4, 4, 1], output_sizes=[1, 4, 4, 1], 780 window_rows=3, window_cols=3, row_stride=1, col_stride=1, 781 padding="SAME", use_gpu=use_gpu) 782 783 def _testMaxPoolGradDirectWithNans2_1(self): 784 input_data = [float("nan")] * 16 785 output_backprop = [ 786 11.0, 12.0, 13.0, 787 15.0, 16.0, 17.0, 788 19.0, 20.0, 21.0] 789 # Test the CPU implementation, which propagates diffs in case of NaN 790 expected_input_backprop_tf_cpu = [ 791 11.0, 12.0, 13.0, 0.0, 792 15.0, 16.0, 17.0, 0.0, 793 19.0, 20.0, 21.0, 0.0, 794 0.0, 0.0, 0.0, 0.0] 795 self._testMaxPoolGradDirect( 796 input_data, output_backprop, expected_input_backprop_tf_cpu, 797 input_sizes=[1, 4, 4, 1], output_sizes=[1, 3, 3, 1], 798 window_rows=2, window_cols=2, row_stride=1, col_stride=1, 799 padding="VALID", use_gpu=False) 800 801 if not tf.test.is_built_with_cuda(): 802 return 803 804 # Test the GPU implementation that uses cudnn for now. 805 # It does not propagate the diff in cases of NaNs 806 expected_input_backprop_cudnn = [ 807 0.0, 0.0, 0.0, 0.0, 808 0.0, 0.0, 0.0, 0.0, 809 0.0, 0.0, 0.0, 0.0, 810 0.0, 0.0, 0.0, 0.0] 811 self._testMaxPoolGradDirect( 812 input_data, output_backprop, expected_input_backprop_cudnn, 813 input_sizes=[1, 4, 4, 1], output_sizes=[1, 3, 3, 1], 814 window_rows=2, window_cols=2, row_stride=1, col_stride=1, 815 padding="VALID", use_gpu=True) 816 817 def _testMaxPoolGradDirectWithNans2_2(self): 818 input_data = [float("nan")] * 16 819 output_backprop = [ 820 float("nan"), 12.0, 13.0, 821 15.0, float("nan"), 17.0, 822 19.0, 20.0, float("nan")] 823 # Test the CPU implementation, which propagates diffs in case of NaN 824 expected_input_backprop_tf_cpu = [ 825 float("nan"), 12.0, 13.0, 0.0, 826 15.0, float("nan"), 17.0, 0.0, 827 19.0, 20.0, float("nan"), 0.0, 828 0.0, 0.0, 0.0, 0.0] 829 self._testMaxPoolGradDirect( 830 input_data, output_backprop, expected_input_backprop_tf_cpu, 831 input_sizes=[1, 4, 4, 1], output_sizes=[1, 3, 3, 1], 832 window_rows=2, window_cols=2, row_stride=1, col_stride=1, 833 padding="VALID", use_gpu=False) 834 835 if not tf.test.is_built_with_cuda(): 836 return 837 838 # Test the GPU implementation that uses cudnn for now. 839 # It does not propagate the diff in cases of NaNs 840 expected_input_backprop_cudnn = [ 841 0.0, 0.0, 0.0, 0.0, 842 0.0, 0.0, 0.0, 0.0, 843 0.0, 0.0, 0.0, 0.0, 844 0.0, 0.0, 0.0, 0.0] 845 self._testMaxPoolGradDirect( 846 input_data, output_backprop, expected_input_backprop_cudnn, 847 input_sizes=[1, 4, 4, 1], output_sizes=[1, 3, 3, 1], 848 window_rows=2, window_cols=2, row_stride=1, col_stride=1, 849 padding="VALID", use_gpu=True) 850 851 def testMaxPoolGradDirect(self): 852 self._testMaxPoolGradDirect1_1() 853 self._testMaxPoolGradDirect1_2() 854 self._testMaxPoolGradDirect1_3() 855 self._testMaxPoolGradDirectWithNans2_1() 856 self._testMaxPoolGradDirectWithNans2_2() 857 858 def testAvgPoolGrad(self): 859 for (data_format, use_gpu) in GetTestConfigs(): 860 self._testAvgPoolGradValidPadding1_1(data_format, use_gpu) 861 self._testAvgPoolGradValidPadding2_1(data_format, use_gpu) 862 self._testAvgPoolGradValidPadding2_2(data_format, use_gpu) 863 self._testAvgPoolGradSamePadding1_1(data_format, use_gpu) 864 self._testAvgPoolGradSamePadding2_1(data_format, use_gpu) 865 self._testAvgPoolGradSamePadding2_2(data_format, use_gpu) 866 self._testAvgPoolGradSamePadding3_1(data_format, use_gpu) 867 868 def _testAvgPoolGradValidPadding1_1(self, data_format, use_gpu): 869 self._ConstructAndTestGradient( 870 tf.nn.avg_pool, input_sizes=[2, 3, 3, 3], 871 output_sizes=[2, 3, 3, 3], window_rows=1, window_cols=1, row_stride=1, 872 col_stride=1, padding="VALID", data_format=data_format, use_gpu=use_gpu) 873 874 def _testAvgPoolGradValidPadding2_1(self, data_format, use_gpu): 875 self._ConstructAndTestGradient( 876 tf.nn.avg_pool, input_sizes=[2, 3, 3, 3], 877 output_sizes=[2, 2, 2, 3], window_rows=2, window_cols=2, row_stride=1, 878 col_stride=1, padding="VALID", data_format=data_format, use_gpu=use_gpu) 879 880 def _testAvgPoolGradValidPadding2_2(self, data_format, use_gpu): 881 self._ConstructAndTestGradient( 882 tf.nn.avg_pool, input_sizes=[2, 2, 2, 3], 883 output_sizes=[2, 1, 1, 3], window_rows=2, window_cols=2, row_stride=2, 884 col_stride=2, padding="VALID", data_format=data_format, use_gpu=use_gpu) 885 886 def _testAvgPoolGradSamePadding1_1(self, data_format, use_gpu): 887 self._ConstructAndTestGradient( 888 tf.nn.avg_pool, input_sizes=[2, 2, 4, 3], 889 output_sizes=[2, 2, 4, 3], window_rows=1, window_cols=1, row_stride=1, 890 col_stride=1, padding="SAME", data_format=data_format, use_gpu=use_gpu) 891 892 def _testAvgPoolGradSamePadding2_1(self, data_format, use_gpu): 893 self._ConstructAndTestGradient( 894 tf.nn.avg_pool, input_sizes=[2, 2, 4, 3], 895 output_sizes=[2, 2, 4, 3], window_rows=2, window_cols=2, row_stride=1, 896 col_stride=1, padding="SAME", data_format=data_format, use_gpu=use_gpu) 897 898 def _testAvgPoolGradSamePadding2_2(self, data_format, use_gpu): 899 self._ConstructAndTestGradient( 900 tf.nn.avg_pool, input_sizes=[2, 2, 4, 3], 901 output_sizes=[2, 1, 2, 3], window_rows=2, window_cols=2, row_stride=2, 902 col_stride=2, padding="SAME", data_format=data_format, use_gpu=use_gpu) 903 904 def _testAvgPoolGradSamePadding3_1(self, data_format, use_gpu): 905 self._ConstructAndTestGradient( 906 tf.nn.avg_pool, input_sizes=[1, 7, 7, 1], 907 output_sizes=[1, 7, 7, 1], window_rows=3, window_cols=3, row_stride=1, 908 col_stride=1, padding="SAME", data_format=data_format, use_gpu=use_gpu) 909 910 def testShapeFunctionEdgeCases(self): 911 # All shapes unknown. 912 for pool_func in [tf.nn.max_pool, tf.nn.avg_pool]: 913 p = pool_func(tf.placeholder(tf.float32), 914 ksize=[1, 1, 1, 1], strides=[1, 1, 1, 1], 915 padding="SAME") 916 self.assertEqual([None, None, None, None], p.get_shape().as_list()) 917 p, am = tf.nn.max_pool_with_argmax( 918 tf.placeholder(tf.float32), 919 ksize=[1, 1, 1, 1], strides=[1, 1, 1, 1], 920 padding="SAME") 921 self.assertEqual([None, None, None, None], p.get_shape().as_list()) 922 self.assertEqual([None, None, None, None], am.get_shape().as_list()) 923 924 # Incorrect input shape. 925 for pool_func in [tf.nn.max_pool, tf.nn.avg_pool, 926 tf.nn.max_pool_with_argmax]: 927 with self.assertRaises(ValueError): 928 pool_func(tf.placeholder(tf.float32, shape=[1, 3]), 929 ksize=[1, 1, 1, 1], strides=[1, 1, 1, 1], padding="SAME") 930 931 # Illegal strides. 932 for pool_func in [tf.nn.max_pool, tf.nn.avg_pool, 933 tf.nn.max_pool_with_argmax]: 934 with self.assertRaisesRegexp(ValueError, "strides in the batch"): 935 pool_func(tf.placeholder(tf.float32), 936 ksize=[1, 1, 1, 1], strides=[2, 1, 1, 1], padding="SAME") 937 with self.assertRaisesRegexp(ValueError, "strides in the batch and depth"): 938 tf.nn.avg_pool(tf.placeholder(tf.float32), 939 ksize=[1, 1, 1, 1], strides=[1, 1, 1, 2], padding="SAME") 940 941 # Filter larger than input. 942 for pool_func in [tf.nn.max_pool, tf.nn.avg_pool, 943 tf.nn.max_pool_with_argmax]: 944 with self.assertRaisesRegexp(ValueError, 945 "Filter must not be larger than the input"): 946 pool_func(tf.placeholder(tf.float32, 947 shape=[32, 20, 20, 3]), 948 ksize=[1, 20, 21, 1], strides=[1, 1, 1, 1], padding="SAME") 949 with self.assertRaisesRegexp(ValueError, 950 "Filter must not be larger than the input"): 951 pool_func(tf.placeholder(tf.float32, 952 shape=[32, 20, 20, 3]), 953 ksize=[1, 21, 20, 1], strides=[1, 1, 1, 1], padding="SAME") 954 955 956def GetMaxPoolFwdTest(input_size, filter_size, strides, padding): 957 def Test(self): 958 # MaxPoolWithArgMax is implemented only on GPU. 959 if not tf.test.is_built_with_cuda(): 960 return 961 self._CompareMaxPoolingFwd(input_size, filter_size, strides, padding) 962 return Test 963 964 965def GetMaxPoolGradTest(input_size, filter_size, output_size, strides, padding): 966 def Test(self): 967 # MaxPoolWithArgMax is implemented only on GPU. 968 if not tf.test.is_built_with_cuda(): 969 return 970 self._CompareMaxPoolingBk(input_size, output_size, 971 filter_size, strides, padding) 972 return Test 973 974 975if __name__ == "__main__": 976 for (name_, input_size_, filter_size_, output_size_, stride_, 977 padding_) in GetShrunkInceptionMaxPoolShapes(): 978 setattr(PoolingTest, "testMaxPoolFwd_" + name_, 979 GetMaxPoolFwdTest(input_size_, filter_size_, stride_, padding_)) 980 setattr(PoolingTest, "testMaxPoolGrad_" + name_, 981 GetMaxPoolGradTest(input_size_, filter_size_, output_size_, 982 stride_, padding_)) 983 tf.test.main() 984