docstr: :param image_shape: The constant shape info passed to corrMM.
  :param filter_shape: The constant shape info passed to corrMM.
code: def validate(
      self,
      image_shape,
      filter_shape,
      border_mode="valid",
      subsample=(1, 1),
      input=None,
      filters=None,
      verify_grad=True,
      non_contiguous=False,
      filter_dilation=(1, 1),
  ):
      """
      :param image_shape: The constant shape info passed to corrMM.
      :param filter_shape: The constant shape info passed to corrMM.
      """
      if not theano.config.cxx:
          raise SkipTest("Need cxx to test conv2d")
      N_image_shape = [
          T.get_scalar_constant_value(T.as_tensor_variable(x))
          for x in image_shape
      ]
      N_filter_shape = [
          T.get_scalar_constant_value(T.as_tensor_variable(x))
          for x in filter_shape
      ]
  
      if input is None:
          input = self.input
      if filters is None:
          filters = self.filters
  
      # THEANO IMPLEMENTATION
  
      # we create a symbolic function so that verify_grad can work
      def sym_CorrMM(input, filters):
          # define theano graph and function
          input.name = "input"
          filters.name = "filters"
          rval = corr.CorrMM(border_mode, subsample, filter_dilation)(
              input, filters
          )
          rval.name = "corr_output"
          return rval
  
      output = sym_CorrMM(input, filters)
      output.name = "CorrMM()(%s,%s)" % (input.name, filters.name)
      theano_corr = theano.function(
          [input, filters], output, mode=self.mode
      )
  
      # initialize input and compute result
      image_data = np.random.random(N_image_shape).astype(self.dtype)
      filter_data = np.random.random(N_filter_shape).astype(self.dtype)
      if non_contiguous:
          image_data = np.transpose(image_data, axes=(0, 1, 3, 2))
          image_data = image_data.copy()
          image_data = np.transpose(image_data, axes=(0, 1, 3, 2))
          filter_data = np.transpose(filter_data, axes=(0, 1, 3, 2))
          filter_data = filter_data.copy()
          filter_data = np.transpose(filter_data, axes=(0, 1, 3, 2))
          assert not image_data.flags["CONTIGUOUS"]
          assert not filter_data.flags["CONTIGUOUS"]
  
      theano_output = theano_corr(image_data, filter_data)
  
      # REFERENCE IMPLEMENTATION
      # Testing correlation, not convolution. Reverse filters.
      filter_data_corr = np.array(
          filter_data[:, :, ::-1, ::-1], copy=True, order="C"
      )
      orig_image_data = image_data
      img_shape2d = np.array(N_image_shape[-2:])
      fil_shape2d = np.array(N_filter_shape[-2:])
      dil_shape2d = np.array(filter_dilation)
      dil_fil_shape2d = (fil_shape2d - 1) * dil_shape2d + 1
      subsample2d = np.array(subsample)
      if border_mode == "full":
          padHW = dil_fil_shape2d - 1
      elif border_mode == "valid":
          padHW = np.array([0, 0])
      elif border_mode == "half":
          padHW = np.floor(dil_fil_shape2d / 2).astype("int32")
      elif isinstance(border_mode, tuple):
          padHW = np.array(border_mode)
      elif isinstance(border_mode, integer_types):
          padHW = np.array([border_mode, border_mode])
      else:
          raise NotImplementedError(
              "Unsupported border_mode {}".format(border_mode)
          )
      out_shape2d = (
          np.floor(
              (img_shape2d + 2 * (padHW) - dil_fil_shape2d)
              / subsample2d
          )
          + 1
      )
      # avoid numpy deprecation
      out_shape2d = out_shape2d.astype("int32")
      out_shape = (N_image_shape[0], N_filter_shape[0]) + tuple(
          out_shape2d
      )
      ref_output = np.zeros(out_shape)
  
      # loop over output feature maps
      ref_output.fill(0)
      image_data2 = np.zeros(
          (
              N_image_shape[0],
              N_image_shape[1],
              N_image_shape[2] + 2 * padHW[0],
              N_image_shape[3] + 2 * padHW[1],
          )
      )
      image_data2[
          :,
          :,
          padHW[0] : padHW[0] + N_image_shape[2],
          padHW[1] : padHW[1] + N_image_shape[3],
      ] = image_data
      image_data = image_data2
      N_image_shape = image_data.shape
      for bb in range(N_image_shape[0]):
          for nn in range(N_filter_shape[0]):
              for im0 in range(N_image_shape[1]):
                  filter2d = filter_data_corr[nn, im0, :, :]
                  image2d = image_data[bb, im0, :, :]
                  for row in range(ref_output.shape[2]):
                      irow = row * subsample[0]  # image row
                      for col in range(ref_output.shape[3]):
                          icol = col * subsample[1]  # image col
                          ref_output[bb, nn, row, col] += (
                              image2d[
                                  irow : irow
                                  + dil_fil_shape2d[
                                      0
                                  ] : filter_dilation[0],
                                  icol : icol
                                  + dil_fil_shape2d[
                                      1
                                  ] : filter_dilation[1],
                              ]
                              * filter2d[::-1, ::-1]
                          ).sum()
  
      utt.assert_allclose(ref_output, theano_output)
  
      # TEST GRADIENT
      if verify_grad:
          utt.verify_grad(
              sym_CorrMM, [orig_image_data, filter_data], mode=self.mode
          )
  
imports: from __future__ import absolute_import, print_function, division
  from nose.plugins.skip import SkipTest
  from nose.plugins.attrib import attr
  from nose.tools import assert_equals
  import numpy
  from six import integer_types
  import theano
  import theano.tensor
  from theano.tests import unittest_tools
  from theano.tensor.nnet import corr, conv
  from theano.tensor.nnet.tests.test_abstract_conv import Grouped_conv_noOptim, TestUnsharedConv
  from theano.tensor.nnet.tests.test_abstract_conv import TestAsymmetricPadding, TestCausalConv
label_desc: Use image node_id 2 for calling the TestCorr2D obj's underlying member method code with example usage: obj.validate(image_shape, filter_shape, border_mode, subsample, input, filters, verify_grad, non_contiguous, filter_dilation) and returns: rval