code: def rnn(bptt, vocab_size, num_embed, nhid, num_layers, dropout, num_proj, batch_size):
      
      state_names = []
      data = S.var('data')
      weight = S.var("encoder_weight", stype='row_sparse')
      embed = S.sparse.Embedding(data=data, weight=weight, input_dim=vocab_size,
                                 output_dim=num_embed, name='embed', sparse_grad=True)
      states = []
      outputs = S.Dropout(embed, p=dropout)
      for i in range(num_layers):
          prefix = 'lstmp%d_' % i
          init_h = S.var(prefix + 'init_h', shape=(batch_size, num_proj), init=mx.init.Zero())
          init_c = S.var(prefix + 'init_c', shape=(batch_size, nhid), init=mx.init.Zero())
          state_names += [prefix + 'init_h', prefix + 'init_c']
          lstmp = mx.gluon.contrib.rnn.LSTMPCell(nhid, num_proj, prefix=prefix)
          outputs, next_states = lstmp.unroll(bptt, outputs, begin_state=[init_h, init_c], \
                                              layout='NTC', merge_outputs=True)
          outputs = S.Dropout(outputs, p=dropout)
          states += [S.stop_gradient(s) for s in next_states]
      outputs = S.reshape(outputs, shape=(-1, num_proj))
  
      trainable_lstm_args = []
      for arg in outputs.list_arguments():
          if 'lstmp' in arg and 'init' not in arg:
              trainable_lstm_args.append(arg)
      return outputs, states, trainable_lstm_args, state_names
docs: word embedding + LSTM Projected