class_docstr: Implement some special requirement ops
class_docstr_tok: ["Implement","some","special","requirement","ops"]
docstr:  Implement convolution ops
  
  Args:
      output (int): the output channel size
      kernel (list): the kernel size of filter, with format [width, height]
      stride (list): the stride of convolution, with format [w_stride, h_stride]
      pad (bool): auto padding or not
      kernel_init (`np.array`): the tensor saving initialize values of filter
      bias_init (`np.array`): the tensor saving initialize values of bias
      group (int): the group size in the convolution
      dilation (list): the dilation of convolution, with format [w_dilation, h_dilation]
      name (str): the name of ops
  
  Return:
      :func:`~cntk.ops.as_block`: the function contains convolution ops
docstr_tok: ["Implement","convolution","ops","Args",":","output","(","int",")",":","the","output","channel","size","kernel","(","list",")",":","the","kernel","size","of","filter",",","with","format","[","width",",","height","]","stride","(","list",")",":","the","stride","of","convolution",",","with","format","[","w_stride",",","h_stride","]","pad","(","bool",")",":","auto","padding","or","not","kernel_init","(","`","np.array","`",")",":","the","tensor","saving","initialize","values","of","filter","bias_init","(","`","np.array","`",")",":","the","tensor","saving","initialize","values","of","bias","group","(","int",")",":","the","group","size","in","the","convolution","dilation","(","list",")",":","the","dilation","of","convolution",",","with","format","[","w_dilation",",","h_dilation","]","name","(","str",")",":","the","name","of","ops","Return",":",":","func",":","`","~cntk.ops.as_block","`",":","the","function","contains","convolution","ops"]
code: def convolution(
      output,
      kernel,
      stride,
      pad,
      kernel_init,
      bias_init,
      group,
      dilation,
      name,
  ):
      """
       Implement convolution ops
  
      Args:
          output (int): the output channel size
          kernel (list): the kernel size of filter, with format [width, height]
          stride (list): the stride of convolution, with format [w_stride, h_stride]
          pad (bool): auto padding or not
          kernel_init (`np.array`): the tensor saving initialize values of filter
          bias_init (`np.array`): the tensor saving initialize values of bias
          group (int): the group size in the convolution
          dilation (list): the dilation of convolution, with format [w_dilation, h_dilation]
          name (str): the name of ops
  
      Return:
          :func:`~cntk.ops.as_block`: the function contains convolution ops
      """
  
      def _conv_ops(weights, data):
          return ops.convolution(
              weights,
              data,
              strides=(cntk.InferredDimension,)
              + ops.sanitize_shape(stride),
              auto_padding=[False, pad, pad],
          )
  
      def _weights_parameter(output_channels, init, group_name):
          dilation_kernel = [
              (k - 1) * d + 1 for k, d in zip(kernel, dilation)
          ]
          # expand kernel to simulate dilation
          used_init = init.copy()
          if dilation_kernel != kernel:
              for axis in range(len(dilation)):
                  kernel_sequence = [
                      x * dilation[axis] for x in range(kernel[axis])
                  ]
                  insert_lines = list(
                      set([x for x in range(dilation_kernel[axis])])
                      ^ set(kernel_sequence)
                  )
                  for index in range(len(insert_lines)):
                      insert_lines[index] -= index
                  used_init = np.insert(
                      used_init,
                      insert_lines,
                      0,
                      axis=len(init.shape) - axis - 1,
                  )
          return ops.parameter(
              shape=(output_channels, cntk.InferredDimension)
              + ops.sanitize_shape(dilation_kernel),
              init=used_init,
              name=group_name,
          )
  
      if group == 1:
          w = _weights_parameter(
              output, kernel_init, ".".join((name, "W"))
          )
      else:
          sub_output_channels = int(output / group)
          groups_kernel_init = np.split(kernel_init, group)
          groups_kernel = [
              _weights_parameter(
                  sub_output_channels,
                  groups_kernel_init[i],
                  ".".join((name, str(i), "W")),
              )
              for i in range(0, group)
          ]
          sub_input_channels = groups_kernel[0].shape[1]
      if bias_init is not None:
          b = ops.parameter(
              shape=(output,),
              init=bias_init,
              name=".".join((name, "b")),
          )
  
      @BlockFunction("Convolution", name)
      def _convolution(x):
          if group == 1:
              apply_x = _conv_ops(w, x)
          else:
              groups_data = [
                  ops.slice(
                      x,
                      axis=0,
                      begin_index=i * sub_input_channels,
                      end_index=(i + 1) * sub_input_channels,
                  )
                  for i in range(0, group)
              ]
              apply_sub = [
                  _conv_ops(group_kernel, group_data)
                  for group_kernel, group_data in zip(
                      groups_kernel, groups_data
                  )
              ]
              apply_x = ops.splice(*apply_sub, axis=0)
          if bias_init is not None:
              apply_x += b
          return apply_x
  
      return _convolution
  
imports: from operator import mul
  from functools import reduce
  import numpy
  import cntk
  import cntk.io.transforms
  from cntk import ops, io, learners, internal
  from cntk import Trainer
  from cntk.layers.blocks import BlockFunction
label_desc: Use image node_id 1 for calling the BlockApiSetup obj's underlying member method code with example usage: obj.convolution(output, kernel, stride, pad, kernel_init, bias_init, group, dilation, name) and returns: _convolution, ops, ops, apply_x