See LSTM's conversion function for its output shapes.
484498
def calculate_lstm_output_shapes(operator):
    '''
    
    '''
    check_input_and_output_numbers(operator, input_count_range=[1, 3], output_count_range=[1, 3])
    check_input_and_output_types(operator, good_input_types=[FloatTensorType])

    input_shape = operator.inputs[0].type.shape

    if len(input_shape) not in [2, 4]:
        raise RuntimeError('Input must be a 2-D tensor')

    params = operator.raw_operator.uniDirectionalLSTM

    # The following line is more accurate but it may break some tests
    # output_shape = ['None', params.outputVectorSize] if params.params.sequenceOutput else [1, params.outputVectorSize]
    output_shape = ['None', params.outputVectorSize]
    state_shape = [1, params.outputVectorSize]

    # TODO: Changing input shapes of an operator is dangerous, this should be move to Topology's _fix_shapes function
    if len(operator.inputs) > 1:
        Y_h_in = operator.inputs[1]  # The initial hidden state of a single sequence
        Y_h_in.type.shape = state_shape
    if len(operator.inputs) > 2:
        Y_c_in = operator.inputs[2]  # The initial cell state of a single sequence
        Y_c_in.type.shape = state_shape

    operator.outputs[0].type.shape = output_shape
    if len(operator.outputs) > 1:
        operator.outputs[1].type.shape = state_shape
    if len(operator.outputs) > 2:
        operator.outputs[2].type.shape = state_shape
766812
def calculate_reorganize_data_output_shapes(operator):
    '''
    
    '''
    check_input_and_output_numbers(operator, input_count_range=1, output_count_range=1)
    check_input_and_output_types(operator, good_input_types=[FloatTensorType])

    output_shape = copy.deepcopy(operator.inputs[0].type.shape)

    params = operator.raw_operator.reorganizeData

    from coremltools.proto.NeuralNetwork_pb2 import ReorganizeDataLayerParams as Params

    if params.mode == Params.DEPTH_TO_SPACE:
        if output_shape[1] % (params.blockSize * params.blockSize) != 0:
            raise RuntimeError('Channel number must be divisible by the square of block size')

        output_shape = [output_shape[0], output_shape[1] / params.blockSize / params.blockSize,
                        output_shape[2] * params.blockSize, output_shape[3] * params.blockSize]
    elif params.mode == Params.SPACE_TO_DEPTH:
        if output_shape[2] % params.blockSize != 0 or output_shape[3] % params.blockSize != 0:
            raise RuntimeError('Height and weight must be divisible by block size')

        output_shape = [output_shape[0], output_shape[1] * params.blockSize * params.blockSize,
                        output_shape[2] / params.blockSize, output_shape[3] / params.blockSize]
    else:
        raise ValueError('Unsupport reorganization mode {0}'.format(params.mode))

    operator.outputs[0].type = FloatTensorType([int(i) if i != 'None' else 'None' for i in output_shape],
                                               doc_string=operator.outputs[0].type.doc_string)
467416
def shape_list(x):
  """"""
  x = tf.convert_to_tensor(x)

  # If unknown rank, return dynamic shape
  if x.get_shape().dims is None:
    return tf.shape(x)

  static = x.get_shape().as_list()
  shape = tf.shape(x)

  ret = []
  for i, dim in enumerate(static):
    if dim is None:
      dim = shape[i]
    ret.append(dim)
  return ret
1102174
def calculate_crop_output_shapes(operator):
    '''
    
    '''
    check_input_and_output_numbers(operator, input_count_range=[1, 2], output_count_range=1)
    check_input_and_output_types(operator, good_input_types=[FloatTensorType])

    output_shape = copy.deepcopy(operator.inputs[0].type.shape)

    params = operator.raw_operator.crop
    if len(operator.inputs) == 1:
        if len(params.cropAmounts.borderAmounts) > 0:
            output_shape[2] -= params.cropAmounts.borderAmounts[0].startEdgeSize
            output_shape[2] -= params.cropAmounts.borderAmounts[0].endEdgeSize
            output_shape[3] -= params.cropAmounts.borderAmounts[1].startEdgeSize
            output_shape[3] -= params.cropAmounts.borderAmounts[1].endEdgeSize
    elif len(operator.inputs) == 2:
        output_shape[2] = operator.inputs[1].type.shape[2]
        output_shape[3] = operator.inputs[1].type.shape[3]
    else:
        raise RuntimeError('Too many inputs for Crop operator')

    operator.outputs[0].type.shape = output_shape
258909
def convert_simple_rnn(builder, layer, input_names, output_names, keras_layer):
    
    # Get input and output names
    hidden_size = keras_layer.units
    input_size = keras_layer.input_shape[-1]

    output_all = keras_layer.return_sequences
    reverse_input = keras_layer.go_backwards

    W_h = _np.zeros((hidden_size, hidden_size))
    W_x = _np.zeros((hidden_size, input_size))
    b = None

    implementation = keras_layer.implementation if hasattr(keras_layer,
            'implementation') else 0
    if implementation == 0:
        W_h = keras_layer.get_weights()[1].T
        W_x = keras_layer.get_weights()[0].T
        if keras_layer.use_bias:
            b = keras_layer.get_weights()[2]

    # Set actication type
    activation_str = _get_recurrent_activation_name_from_keras(keras_layer.activation)

    # Add to the network
    builder.add_simple_rnn(
        name = layer,
        W_h = W_h, W_x = W_x, b = b,
        hidden_size = hidden_size,
        input_size = input_size,
        activation = activation_str,
        input_names = input_names,
        output_names = output_names,
        output_all=output_all,
        reverse_input=reverse_input)
1147955
def _lstm_unroll_base(num_lstm_layer, seq_len, num_hidden):
    
    param_cells = []
    last_states = []
    for i in range(num_lstm_layer):
        param_cells.append(LSTMParam(i2h_weight=mx.sym.Variable("l%d_i2h_weight" % i),
                                     i2h_bias=mx.sym.Variable("l%d_i2h_bias" % i),
                                     h2h_weight=mx.sym.Variable("l%d_h2h_weight" % i),
                                     h2h_bias=mx.sym.Variable("l%d_h2h_bias" % i)))
        state = LSTMState(c=mx.sym.Variable("l%d_init_c" % i),
                          h=mx.sym.Variable("l%d_init_h" % i))
        last_states.append(state)
    assert len(last_states) == num_lstm_layer

    # embedding layer
    data = mx.sym.Variable('data')
    wordvec = mx.sym.SliceChannel(data=data, num_outputs=seq_len, squeeze_axis=1)

    hidden_all = []
    for seqidx in range(seq_len):
        hidden = wordvec[seqidx]
        for i in range(num_lstm_layer):
            next_state = _lstm(
                num_hidden=num_hidden,
                indata=hidden,
                prev_state=last_states[i],
                param=param_cells[i],
                seqidx=seqidx,
                layeridx=i)
            hidden = next_state.h
            last_states[i] = next_state
        hidden_all.append(hidden)

    hidden_concat = mx.sym.Concat(*hidden_all, dim=0)
    pred_fc = mx.sym.FullyConnected(data=hidden_concat, num_hidden=11, name="pred_fc")
    return pred_fc
547595
def _forward_kernel(self, F, inputs, states, **kwargs):
        
        if self._layout == 'NTC':
            inputs = F.swapaxes(inputs, dim1=0, dim2=1)
        if self._projection_size is None:
            params = (kwargs['{}{}_{}_{}'.format(d, l, g, t)].reshape(-1)
                      for t in ['weight', 'bias']
                      for l in range(self._num_layers)
                      for d in ['l', 'r'][:self._dir]
                      for g in ['i2h', 'h2h'])
        else:
            params = (kwargs['{}{}_{}_{}'.format(d, l, g, t)].reshape(-1)
                      for t in ['weight', 'bias']
                      for l in range(self._num_layers)
                      for d in ['l', 'r'][:self._dir]
                      for g in ['i2h', 'h2h', 'h2r']
                      if g != 'h2r' or t != 'bias')

        params = F._internal._rnn_param_concat(*params, dim=0)

        rnn = F.RNN(inputs, params, *states, state_size=self._hidden_size,
                    projection_size=self._projection_size,
                    num_layers=self._num_layers, bidirectional=self._dir == 2,
                    p=self._dropout, state_outputs=True, mode=self._mode,
                    lstm_state_clip_min=self._lstm_state_clip_min,
                    lstm_state_clip_max=self._lstm_state_clip_max,
                    lstm_state_clip_nan=self._lstm_state_clip_nan)

        if self._mode == 'lstm':
            outputs, states = rnn[0], [rnn[1], rnn[2]]
        else:
            outputs, states = rnn[0], [rnn[1]]

        if self._layout == 'NTC':
            outputs = F.swapaxes(outputs, dim1=0, dim2=1)

        return outputs, states
873149
def decode_to_shape(inputs, shape, scope):
  """"""
  with tf.variable_scope(scope, reuse=tf.AUTO_REUSE):
    x = inputs
    x = tfl.flatten(x)
    x = tfl.dense(x, shape[2], activation=None, name="dec_dense")
    x = tf.expand_dims(x, axis=1)
    return x
303639
def lstm_state_tuples(num_nodes, name):
  """"""
  if not isinstance(num_nodes, tf.compat.integral_types):
    raise ValueError('num_nodes must be an integer: %s' % num_nodes)
  return [(STATE_NAME % name + '_0', tf.float32, num_nodes),
          (STATE_NAME % name + '_1', tf.float32, num_nodes)]
813183
def state_size(self):
    """"""
    return LSTMState(tf.TensorShape([self._hidden_state_size]),
                     tf.TensorShape([self._hidden_size]))
370753
def compute_output(self, o, output_shape=None):
    
    if self.combine_dims:
      o = mtf.transpose(o, o.shape - self.o_dims + self.o_dims)
      o = mtf.replace_dimensions(o, self.o_dims, self.wo.shape.dims[0])
      reduced_dims = [self.wo.shape.dims[0]]
    else:
      reduced_dims = self.o_dims
    return mtf.einsum(
        [o, self.wo], output_shape=output_shape, reduced_dims=reduced_dims)
944017
def calculate_embedding_output_shapes(operator):
    '''
    
    '''
    check_input_and_output_numbers(operator, input_count_range=1, output_count_range=1)
    check_input_and_output_types(operator, good_input_types=[Int64Type, Int64TensorType])

    output = operator.outputs[0]

    input_shape = operator.inputs[0].type.shape

    if input_shape[1] != 1 or (len(input_shape) > 2 and (input_shape[2] != 1 or input_shape[3] != 1)):
        raise RuntimeError('If input is a 4-D tensor, its shape must be [N, 1, 1, 1]')

    params = operator.raw_operator.embedding
    if len(input_shape) == 4:
        output_shape = [input_shape[0], params.outputChannels, 1, 1]
    elif len(input_shape) == 2:
        output_shape = [input_shape[0], params.outputChannels]
    else:
        raise RuntimeError('Input must be a 2-D or a 4-D tensor')

    output.type.shape = output_shape
1101708
def standardize_shapes(features, batch_size=None):
  """"""
  for fname in ["inputs", "targets"]:
    if fname not in features:
      continue
    f = features[fname]
    while len(f.get_shape()) < 4:
      f = tf.expand_dims(f, axis=-1)
    features[fname] = f

  if batch_size:
    # Ensure batch size is set on all features
    for _, t in six.iteritems(features):
      shape = t.get_shape().as_list()
      shape[0] = batch_size
      t.set_shape(t.get_shape().merge_with(shape))
      # Assert shapes are fully known
      t.get_shape().assert_is_fully_defined()

  return features
198258
def calculate_batch_normalization_output_shapes(operator):
    '''
    
    '''
    check_input_and_output_numbers(operator, input_count_range=1, output_count_range=1)
    check_input_and_output_types(operator, good_input_types=[FloatTensorType])

    input_shape = operator.inputs[0].type.shape
    if len(input_shape) not in [2, 4]:
        raise RuntimeError('Input must be a 2-D or a 4-D tensor')

    operator.outputs[0].type.shape = copy.deepcopy(operator.inputs[0].type.shape)
51994
def calculate_inner_product_output_shapes(operator):
    '''
    
    '''
    check_input_and_output_numbers(operator, input_count_range=1, output_count_range=1)
    check_input_and_output_types(operator, good_input_types=[FloatTensorType])

    input = operator.inputs[0]
    output = operator.outputs[0]

    input_shape = input.type.shape
    if len(input_shape) == 4 and (input_shape[2] != 1 or input_shape[3] != 1):
        raise RuntimeError('If input is a 4-D tensor, its shape must be [N, C, 1, 1]')

    params = operator.raw_operator.innerProduct

    if input_shape[1] != params.inputChannels:
        raise RuntimeError('Dimension mismatch along C-axis. Expected %s but got %s' %
                           (params.inputChannels, input_shape[1]))

    if len(input_shape) == 4:
        output.type.shape = [input_shape[0], params.outputChannels, 1, 1]
    elif len(input_shape) == 2:
        output.type.shape = [input_shape[0], params.outputChannels]
    else:
        raise RuntimeError('Input must be a 2-D or a 4-D tensor')
763196
def calculate_concat_output_shapes(operator):
    '''
    
    '''
    check_input_and_output_numbers(operator, input_count_range=[1, None], output_count_range=[1, 1])

    output_shape = copy.deepcopy(operator.inputs[0].type.shape)
    dims = []
    for variable in operator.inputs:
        if variable.type.shape[0] != 'None' and variable.type.shape[0] != output_shape[0]:
            raise RuntimeError('Only dimensions along C-axis can be different')
        if variable.type.shape[2] != 'None' and variable.type.shape[2] != output_shape[2]:
            raise RuntimeError('Only dimensions along C-axis can be different')
        if variable.type.shape[3] != 'None' and variable.type.shape[3] != output_shape[3]:
            raise RuntimeError('Only dimensions along C-axis can be different')
        dims.append(variable.type.shape[1])

    output_shape[1] = 'None' if 'None' in dims else sum(dims)
    operator.outputs[0].type.shape = output_shape
549051
def transpose(self, *axes):
        """"""
        if self.ndim <= 1:
            return self
        ar = np.asarray(self).transpose(*axes)
        if axes[0] != 0:
            # then axis 0 is unaffected by the transposition
            newlabels = [self.labels[ax] for ax in axes]
            return Timeseries(ar, self.tspan, newlabels)
        else:
            return ar