class_docstr: Gated Recurrent Unit (GRU)
  
  .. math::
     r_t = \rm{recurrent\_activation}(W_{ir} x_t + b_{ir} + W_{hr} h_{t-1} + b_{hr})
  
  .. math::
     z_t = \rm{recurrent\_activation}(W_{iz} x_t + b_{iz} + W_{hz} h_{t-1} + b_{hz})
  
  .. math::
     o_t = \rm{activation}(W_{io} x_t + b_{io} + r_t * W_{ho} h_{t-1} + b_{ho})
  
  .. math::
     h_t = (1 − z_t) * o_t + z_t * h_{t−1}
  
  Where:
  
  * :math:`W_{i[r|o|z]}` are state input weights for reset, output and update gate, respectively.
  * :math:`b_{i[r|o|z]}` are input biases for reset, output and update gate, respectively.
  * :math:`W_{h[r|o|z]}` are recurrent/hidden weights on hidden state to reset, output, and update gates, respectively.
  * :math:`b_{h[r|o|z]}` are recurrent/hidden biases on hidden state to reset, output, and update gates, respectively.
  * :math:`h_t`  is the hidden state at time ``t``.
  * :math:`x_t` is the input at time ``t``.
  * :math:`h_{t-1}` is the hidden state of the layer at time ``t-1`` or the initial
    hidden state at time ``0``.
  * :math:`r_t`, :math:`o_t`, and :math:`z_t` are the reset, new, and update gates, respectively.
  * :math:`*` is elementwise product.
  
  Parameters
  ----------
  x: <s, b, I, T> (Required)
      * ``s`` is the sequence length, ``b`` is the batch size, and ``I`` is the
        input dimension.
  
  initial_h: <b, H, T> (Required)
      * ``H`` denotes hidden size.
  
  weight_ih: const<3*H, I, T> (Required) - Weight matrix
      * ``weigh_ih = [W_{ir} | W_{io} | W_{iz}]`` where ``[a|b]`` denotes column
        concatenation and ``[a, b]`` denotes row concatenation. ``W_{ir}``,
        ``W_{io}``, and ``W_{iz}`` have shape ``(H, I)``.
      * This is used when direction="forward" or "reverse".
  
  weight_hh: const<3*H, H, T> (Required) - Weight matrix
      * ``weight_hh =  [W_{hr} | W_{ho} | W_{hz}]``: ``W_{hr}``, ``W_{ho}``, and
        ``W_{hz}`` have shape ``(H, H)``.
      * This is used when direction="forward" or "reverse".
  
  bias: const<3*H, T> (Optional) [Default all 0s]
      * ``bias[0]`` are input-hidden and hidden-hidden bias.
      * ``3*H`` are biases for ``[b_{ir} | b_{io} | b_{hz}]``.
      * This is used when direction="forward" or "reverse".
  
  direction: const<str> (Optional) [Default=forward]
      * Either ``forward`` or ``reverse``.
  
  output_sequence: const<bool> (Optional) [Default=False]
      * Outputs every step if ``True``.
  
  recurrent_activation: const<str> (Optional) [Default=sigmoid]
      * Activation applied on update and reset gate.
  
  activation: const<str> (Optional) [Default=tanh]
      * Activation applied on output gate.
  
  Returns
  -------
  <s, b, H, T> or <1, b, H, T>
      * If ``output_sequence == True`` (hidden states from every step):
        ``<s, b, H, T>``.
      * Else ``<1, b, H, T>`` (hidden states of the final step).
  <b, H, T>
      * Hidden states of the final step.
  
  Attributes
  ----------
  T: fp32
class_docstr_tok: ["Gated","Recurrent","Unit","(","GRU",")","..","math",":",":","r_t","=","\\rm","{","recurrent\\_activation","}","(","W_","{","ir","}","x_t","+","b_","{","ir","}","+","W_","{","hr","}","h_","{","t-1","}","+","b_","{","hr","}",")","..","math",":",":","z_t","=","\\rm","{","recurrent\\_activation","}","(","W_","{","iz","}","x_t","+","b_","{","iz","}","+","W_","{","hz","}","h_","{","t-1","}","+","b_","{","hz","}",")","..","math",":",":","o_t","=","\\rm","{","activation","}","(","W_","{","io","}","x_t","+","b_","{","io","}","+","r_t","*","W_","{","ho","}","h_","{","t-1","}","+","b_","{","ho","}",")","..","math",":",":","h_t","=","(","1","\u2212","z_t",")","*","o_t","+","z_t","*","h_","{","t\u22121","}","Where",":","*",":","math",":","`","W_","{","i","[","r|o|z","]","}","`","are","state","input","weights","for","reset",",","output","and","update","gate",",","respectively",".","*",":","math",":","`","b_","{","i","[","r|o|z","]","}","`","are","input","biases","for","reset",",","output","and","update","gate",",","respectively",".","*",":","math",":","`","W_","{","h","[","r|o|z","]","}","`","are","recurrent\/hidden","weights","on","hidden","state","to","reset",",","output",",","and","update","gates",",","respectively",".","*",":","math",":","`","b_","{","h","[","r|o|z","]","}","`","are","recurrent\/hidden","biases","on","hidden","state","to","reset",",","output",",","and","update","gates",",","respectively",".","*",":","math",":","`","h_t","`","is","the","hidden","state","at","time","``","t","``",".","*",":","math",":","`","x_t","`","is","the","input","at","time","``","t","``",".","*",":","math",":","`","h_","{","t-1","}","`","is","the","hidden","state","of","the","layer","at","time","``","t-1","``","or","the","initial","hidden","state","at","time","``","0","``",".","*",":","math",":","`","r_t","`",",",":","math",":","`","o_t","`",",","and",":","math",":","`","z_t","`","are","the","reset",",","new",",","and","update","gates",",","respectively",".","*",":","math",":","`","*","`","is","elementwise","product",".","Parameters","--","--","--","--","--","x",":","<","s",",","b",",","I",",","T",">","(","Required",")","*","``","s","``","is","the","sequence","length",",","``","b","``","is","the","batch","size",",","and","``","I","``","is","the","input","dimension",".","initial_h",":","<","b",",","H",",","T",">","(","Required",")","*","``","H","``","denotes","hidden","size",".","weight_ih",":","const","<","3","*","H",",","I",",","T",">","(","Required",")","-","Weight","matrix","*","``","weigh_ih","=","[","W_","{","ir","}","|","W_","{","io","}","|","W_","{","iz","}","]","``","where","``","[","a|b","]","``","denotes","column","concatenation","and","``","[","a",",","b","]","``","denotes","row","concatenation",".","``","W_","{","ir","}","``",",","``","W_","{","io","}","``",",","and","``","W_","{","iz","}","``","have","shape","``","(","H",",","I",")","``",".","*","This","is","used","when","direction=","''","forward","''","or","``","reverse","''",".","weight_hh",":","const","<","3","*","H",",","H",",","T",">","(","Required",")","-","Weight","matrix","*","``","weight_hh","=","[","W_","{","hr","}","|","W_","{","ho","}","|","W_","{","hz","}","]","``",":","``","W_","{","hr","}","``",",","``","W_","{","ho","}","``",",","and","``","W_","{","hz","}","``","have","shape","``","(","H",",","H",")","``",".","*","This","is","used","when","direction=","''","forward","''","or","``","reverse","''",".","bias",":","const","<","3","*","H",",","T",">","(","Optional",")","[","Default","all","0s","]","*","``","bias","[","0","]","``","are","input-hidden","and","hidden-hidden","bias",".","*","``","3","*","H","``","are","biases","for","``","[","b_","{","ir","}","|","b_","{","io","}","|","b_","{","hz","}","]","``",".","*","This","is","used","when","direction=","''","forward","''","or","``","reverse","''",".","direction",":","const","<","str",">","(","Optional",")","[","Default=forward","]","*","Either","``","forward","``","or","``","reverse","``",".","output_sequence",":","const","<","bool",">","(","Optional",")","[","Default=False","]","*","Outputs","every","step","if","``","True","``",".","recurrent_activation",":","const","<","str",">","(","Optional",")","[","Default=sigmoid","]","*","Activation","applied","on","update","and","reset","gate",".","activation",":","const","<","str",">","(","Optional",")","[","Default=tanh","]","*","Activation","applied","on","output","gate",".","Returns","--","--","--","-","<","s",",","b",",","H",",","T",">","or","<","1",",","b",",","H",",","T",">","*","If","``","output_sequence","==","True","``","(","hidden","states","from","every","step",")",":","``","<","s",",","b",",","H",",","T",">","``",".","*","Else","``","<","1",",","b",",","H",",","T",">","``","(","hidden","states","of","the","final","step",")",".","<","b",",","H",",","T",">","*","Hidden","states","of","the","final","step",".","Attributes","--","--","--","--","--","T",":","fp32"]
code: def type_inference(self):
      if self.x.rank != 3:
          raise ValueError(
              "Invalid input shape. Expecting Rank 3 input, got {}".format(
                  len(self.x.rank)
              )
          )
  
      sequence_length, batch_size, input_size = self.x.shape
  
      if self.weight_ih.rank != 2:
          raise ValueError(
              "Invalid weight shape. Expecting Rank 2 input, got {}".format(
                  len(self.weight_ih.rank)
              )
          )
      if self.weight_hh.rank != 2:
          raise ValueError(
              "Invalid weight shape. Expecting Rank 2 input, got {}".format(
                  len(self.weight_hh.rank)
              )
          )
  
      hidden_dim, hidden_size = self.weight_hh.shape
  
      direction = self.direction.val
      valid_directions = {"forward", "reverse"}
      if direction not in valid_directions:
          raise ValueError(
              "Direction {} not supported. Supported directions: {}".format(
                  direction, valid_directions
              )
          )
  
      dim_factor = 3
      if hidden_size != (hidden_dim // dim_factor):
          raise ValueError(
              "Incorrect weight matrix: hidden dim size mismatch. \
                  Provided weight_ih {}, weight_hh {}. Expecting <b, 3*H>".format(
                  self.weight_ih.shape, self.weight_hh.shape
              )
          )
  
      out_seq_len = sequence_length if self.output_sequence.val else 1
      output_shape = [out_seq_len, batch_size, hidden_size]
      output_h_shape = [batch_size, hidden_size]
      return (
          types.tensor(self.x.dtype, tuple(output_shape)),
          types.tensor(self.x.dtype, tuple(output_h_shape)),
      )
  
file_path: coremltools/coremltools/converters/mil/mil/ops/defs/iOS15/recurrent.py
imports: from coremltools.converters.mil.mil import Operation, Var, types
  from coremltools.converters.mil.mil.input_type import DefaultInputs, InputSpec, TensorInputType
  from coremltools.converters.mil.mil.ops.defs._op_reqs import register_op
label_desc: Use image node_id 2 for calling the gru obj's underlying member method code with example usage: obj.type_inference() and returns: types,  types