class_docstr: Reduction Op Superclasses
code: def type_inference(self):
      x_type = self.x.dtype
      x_shape = self.x.shape
      axes = self.axes.val if self.axes is not None else None
      if axes is None:
          axes = range(self.x.rank)
      keep_dims = self.keep_dims.val
  
      reduced_shape = list(x_shape)
      if keep_dims:
          for i in axes:
              reduced_shape[i] = 1
      else:
          # sort reverse so we can delete shape elements back to front
          axes = [
              axis if axis >= 0 else axis + len(reduced_shape)
              for axis in axes
          ]
          for i in sorted(axes)[::-1]:
              reduced_shape.pop(i)
      if len(reduced_shape) == 0:
          return x_type  # scalar
  
      return types.tensor(x_type, tuple(reduced_shape))
  
imports: import numpy
  from coremltools.converters.mil.mil import Operation, precondition, types
  from coremltools.converters.mil.mil.input_type import DefaultInputs, InputSpec, TensorInputType
  from coremltools.converters.mil.mil.operation import VALUE
  from coremltools.converters.mil.mil.ops.defs._op_reqs import register_op
  from coremltools.converters.mil.mil.types import nptype_from_builtin
label_desc: Use image node_id 2 for calling the ReductionAxes obj's underlying member method code with example usage: obj.type_inference() and returns: types, x_type