class_docstr: Class to convert MXNet to ONNX graph
class_docstr_tok: ["Class","to","convert","MXNet","to","ONNX","graph"]
docstr: Helper function to collect the output names, types, and shapes
  
  Parameters
  ----------
  sym : :class:`~mxnet.symbol.Symbol`
      MXNet symbol object
  params : dict of ``str`` to :class:`~mxnet.ndarray.NDArray`
      Dict of converted parameters stored in ``mxnet.ndarray.NDArray`` format
  in_shapes : list of tuple
      Input shapes
  out_label : ``str``
      Name of label typically used in loss that may be left in graph. This name is
      removed from list of inputs required by symbol
  in_types : list of Int
      Input ONNX data types
  dynamic : Boolean
      If True will allow for dynamic input shapes to the model
  dynamic_input_shapes: list of tuple
      Specifies the dynamic input_shapes. If None then all dimensions are set to None
  
  Returns
  in_shapes : list of tuple
      Updated input shapes
  graph_outputs : dict ``str`` to dict
      This maps output name to {'shape':tuple, 'dtype':Int}
  -------
docstr_tok: ["Helper","function","to","collect","the","output","names",",","types",",","and","shapes","Parameters","--","--","--","--","--","sym",":",":","class",":","`","~mxnet.symbol.Symbol","`","MXNet","symbol","object","params",":","dict","of","``","str","``","to",":","class",":","`","~mxnet.ndarray.NDArray","`","Dict","of","converted","parameters","stored","in","``","mxnet.ndarray.NDArray","``","format","in_shapes",":","list","of","tuple","Input","shapes","out_label",":","``","str","``","Name","of","label","typically","used","in","loss","that","may","be","left","in","graph",".","This","name","is","removed","from","list","of","inputs","required","by","symbol","in_types",":","list","of","Int","Input","ONNX","data","types","dynamic",":","Boolean","If","True","will","allow","for","dynamic","input","shapes","to","the","model","dynamic_input_shapes",":","list","of","tuple","Specifies","the","dynamic","input_shapes",".","If","None","then","all","dimensions","are","set","to","None","Returns","in_shapes",":","list","of","tuple","Updated","input","shapes","graph_outputs",":","dict","``","str","``","to","dict","This","maps","output","name","to","{","'shape","'",":","tuple",",","'dtype","'",":","Int","}","--","--","--","-"]
code: def get_outputs(
      sym,
      params,
      in_shapes,
      output_label,
      in_types,
      dynamic=False,
      dynamic_input_shapes=None,
  ):
      """Helper function to collect the output names, types, and shapes
  
      Parameters
      ----------
      sym : :class:`~mxnet.symbol.Symbol`
          MXNet symbol object
      params : dict of ``str`` to :class:`~mxnet.ndarray.NDArray`
          Dict of converted parameters stored in ``mxnet.ndarray.NDArray`` format
      in_shapes : list of tuple
          Input shapes
      out_label : ``str``
          Name of label typically used in loss that may be left in graph. This name is
          removed from list of inputs required by symbol
      in_types : list of Int
          Input ONNX data types
      dynamic : Boolean
          If True will allow for dynamic input shapes to the model
      dynamic_input_shapes: list of tuple
          Specifies the dynamic input_shapes. If None then all dimensions are set to None
  
      Returns
      in_shapes : list of tuple
          Updated input shapes
      graph_outputs : dict ``str`` to dict
          This maps output name to {'shape':tuple, 'dtype':Int}
      -------
      """
      from onnx import mapping
      import re
  
      # Collect graph output names
      out_names = list()
      for name in sym.list_outputs():
          if name.endswith(
              "_state_output"
          ):  # handel special cases for RNN operator
              out_names.append(name[: -len("_state_output")] + "1")
          elif name.endswith(
              "_statecell_output"
          ):  # handel special cases for RNN operator
              out_names.append(name[: -len("_statecell_output")] + "2")
          elif name.endswith("_output"):
              out_names.append(name[: -len("_output")])
          elif name.endswith("_out"):
              out_names.append(name[: -len("_out")])
          elif re.search(".*_output[0-9]$", name):
              out_names.append(name[: -len("_output0")] + name[-1])
          else:
              logging.info(
                  "output '%s' does not end with '_output'", name
              )
              out_names.append(name)
  
      # Collect graph output shapes
      # Remove any input listed in params from sym.list_inputs() and bind them to the input shapes provided
      # by user. Also remove output_label, which is the name of the label symbol that may have been used
      # as the label for loss during training.
      inputs = {
          n: tuple(s)
          for n, s in zip(
              [
                  n
                  for n in sym.list_inputs()
                  if n not in params and n != output_label
              ],
              in_shapes,
          )
      }
      # Add params and their shape to list of inputs
      inputs.update(
          {
              n: v.shape
              for n, v in params.items()
              if n in sym.list_inputs()
          }
      )
      # Provide input data as well as input params to infer_shape()
      _, out_shapes, _ = sym.infer_shape(**inputs)
      if dynamic:
          # Keep the dimensionality of the output shapes but change the values to None
          out_shapes = [tuple(None for _ in i_s) for i_s in out_shapes]
  
          if dynamic_input_shapes is None:
              # Set all dimensions to None
              in_shapes = [
                  tuple(None for _ in i_s) for i_s in in_shapes
              ]
          else:
              assert len(in_shapes) == len(dynamic_input_shapes), (
                  "The length of "
                  "dynamic_input_shapes must equal to the length of in_shapes."
              )
              for i_s, d_i_s in zip(in_shapes, dynamic_input_shapes):
                  assert len(i_s) == len(d_i_s), (
                      "The dimensionality " "of each shape must match."
                  )
              in_shapes = dynamic_input_shapes
      else:
          assert dynamic_input_shapes is None, (
              "dynamic_input_shapes is specified. Please "
              "set dynamic_input_shapes=True to enable dynamic input shapes"
          )
  
      # Collect graph output types
      # Remove any input listed in params from sym.list_inputs() and bind them to the input types provided
      # by user. Also remove output_label
      in_dtypes = {
          n: mapping.TENSOR_TYPE_TO_NP_TYPE[t]
          for n, t in zip(
              [
                  n
                  for n in sym.list_inputs()
                  if n not in params and n != output_label
              ],
              in_types,
          )
      }
      # Add params and their types to list of inputs
      in_dtypes.update(
          {
              n: v.dtype
              for n, v in params.items()
              if n in sym.list_inputs()
          }
      )
      _, out_type, _ = sym.infer_type(**in_dtypes)
      out_types = [
          mapping.NP_TYPE_TO_TENSOR_TYPE[o(0).dtype] for o in out_type
      ]
  
      # Make sure the types, names, and shapes all align up
      assert len(out_types) == len(out_names) == len(out_shapes)
  
      # Bind output shapes/types with output names
      graph_outputs = {
          n: {"shape": s, "dtype": d}
          for n, s, d in zip(out_names, out_shapes, out_types)
      }
  
      return in_shapes, graph_outputs
  
file_path: mxnet/python/mxnet/onnx/mx2onnx/_export_onnx.py
imports: import logging
  import json
  import numpy
  from mxnet import ndarray
label_desc: Use image node_id 5 for calling the MXNetGraph obj's underlying member method code with example usage: obj.get_outputs(sym, params, in_shapes, output_label, in_types, dynamic, dynamic_input_shapes) and returns: in_shapes,  graph_outputs