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 """Tests for local response normalization."""
     16 
     17 from __future__ import absolute_import
     18 from __future__ import division
     19 from __future__ import print_function
     20 
     21 import copy
     22 
     23 import numpy as np
     24 
     25 from tensorflow.python.framework import constant_op
     26 from tensorflow.python.framework import dtypes
     27 from tensorflow.python.ops import array_ops
     28 from tensorflow.python.ops import gradient_checker
     29 from tensorflow.python.ops import gradients_impl
     30 from tensorflow.python.ops import nn
     31 import tensorflow.python.ops.nn_grad  # pylint: disable=unused-import
     32 from tensorflow.python.platform import test
     33 
     34 
     35 class LRNOpTest(test.TestCase):
     36 
     37   def _LRN(self, input_image, lrn_depth_radius=5, bias=1.0, alpha=1.0,
     38            beta=0.5):
     39     """Compute expected result."""
     40     output = copy.deepcopy(input_image)
     41     batch_size = input_image.shape[0]
     42     rows = input_image.shape[1]
     43     cols = input_image.shape[2]
     44     depth = input_image.shape[3]
     45     for b in range(batch_size):
     46       for r in range(rows):
     47         for c in range(cols):
     48           for d in range(depth):
     49             begin = max(0, d - lrn_depth_radius)
     50             end = min(depth, d + lrn_depth_radius + 1)
     51             patch = input_image[b, r, c, begin:end]
     52             output[b, r, c, d] /= (
     53                 np.power(bias + alpha * np.sum(patch * patch), beta))
     54     return output
     55 
     56   def _RunAndVerify(self, dtype):
     57     with self.test_session(use_gpu=True):
     58       # random shape
     59       shape = np.random.randint(1, 16, size=4)
     60       # Make depth at least 2 to make it meaningful
     61       shape[3] += 1
     62       p = array_ops.placeholder(dtype, shape=shape)
     63       # random depth_radius, bias, alpha, beta. cuDNN requires depth_radius to
     64       # be in [1, 7].
     65       lrn_depth_radius = np.random.randint(1, min(8, shape[3]))
     66 
     67       bias = 1.0 + np.random.rand()
     68       alpha = 2.0 * np.random.rand()
     69       # cuDNN requires beta >= 0.01.
     70       beta = 0.01 + 2.0 * np.random.rand()
     71       lrn_t = nn.local_response_normalization(
     72           p,
     73           name="lrn",
     74           depth_radius=lrn_depth_radius,
     75           bias=bias,
     76           alpha=alpha,
     77           beta=beta)
     78       params = {p: np.random.rand(*shape).astype("f")}
     79       result = lrn_t.eval(feed_dict=params)
     80     expected = self._LRN(
     81         params[p],
     82         lrn_depth_radius=lrn_depth_radius,
     83         bias=bias,
     84         alpha=alpha,
     85         beta=beta)
     86     err = np.amax(np.abs(result - expected))
     87     print("LRN error for bias ", bias, "alpha ", alpha, " beta ", beta, " is ",
     88           err)
     89     if dtype == dtypes.float32:
     90       self.assertTrue(err < 1e-4)
     91     else:
     92       self.assertTrue(err < 1e-2)
     93     self.assertShapeEqual(expected, lrn_t)
     94 
     95   def testCompute(self):
     96     for _ in range(2):
     97       self._RunAndVerify(dtypes.float32)
     98       # Enable when LRN supports tf.float16 on GPU.
     99       if not test.is_gpu_available():
    100         self._RunAndVerify(dtypes.float16)
    101 
    102   def testGradientsZeroInput(self):
    103     with self.test_session(use_gpu=True):
    104       shape = [4, 4, 4, 4]
    105       p = array_ops.placeholder(dtypes.float32, shape=shape)
    106       inp_array = np.zeros(shape).astype("f")
    107       lrn_op = nn.local_response_normalization(p, 2, 1.0, 0.0, 1.0, name="lrn")
    108       grad = gradients_impl.gradients([lrn_op], [p])[0]
    109       params = {p: inp_array}
    110       r = grad.eval(feed_dict=params)
    111     expected = np.ones(shape).astype("f")
    112     self.assertAllClose(r, expected)
    113     self.assertShapeEqual(expected, grad)
    114 
    115   def _RunAndVerifyGradients(self, dtype):
    116     with self.test_session(use_gpu=True):
    117       # random shape
    118       shape = np.random.randint(1, 5, size=4)
    119       # Make depth at least 2 to make it meaningful
    120       shape[3] += 1
    121       # random depth_radius, bias, alpha, beta. cuDNN requires depth_radius to
    122       # be in [1, 7].
    123       lrn_depth_radius = np.random.randint(1, min(8, shape[3]))
    124       bias = 1.0 + np.random.rand()
    125       alpha = 1.0 * np.random.rand()
    126       # cuDNN requires beta >= 0.01.
    127       beta = 0.01 + 1.0 * np.random.rand()
    128       if dtype == dtypes.float32:
    129         inp_array = np.random.rand(*shape).astype(np.float32)
    130       else:
    131         inp_array = np.random.rand(*shape).astype(np.float16)
    132 
    133       inp = constant_op.constant(
    134           list(inp_array.ravel(order="C")), shape=shape, dtype=dtype)
    135       lrn_op = nn.local_response_normalization(
    136           inp,
    137           name="lrn",
    138           depth_radius=lrn_depth_radius,
    139           bias=bias,
    140           alpha=alpha,
    141           beta=beta)
    142       err = gradient_checker.compute_gradient_error(inp, shape, lrn_op, shape)
    143     print("LRN Gradient error for bias ", bias, "alpha ", alpha, " beta ", beta,
    144           " is ", err)
    145     if dtype == dtypes.float32:
    146       self.assertLess(err, 1e-4)
    147     else:
    148       self.assertLess(err, 1.0)
    149 
    150   def testGradients(self):
    151     for _ in range(2):
    152       self._RunAndVerifyGradients(dtypes.float32)
    153       # Enable when LRN supports tf.float16 on GPU.
    154       if not test.is_gpu_available():
    155         self._RunAndVerifyGradients(dtypes.float16)
    156 
    157 
    158 if __name__ == "__main__":
    159   test.main()
    160