text: import torch
  import torch.nn as nn
  from torch.autograd import Variable
  from torch.nn import functional as F
  import pdb, math
  
  
  class RNNModel(nn.Module):
      """Container module with an encoder, a recurrent module, and a decoder."""
  
      def __init__(self, rnn_type, ntoken, ninp, nhid, nlayers, dropout=0.5, tie_weights=False):
          super(RNNModel, self).__init__()
          self.drop = nn.Dropout(dropout)
          self.encoder = nn.Embedding(ntoken, ninp)
          self.rnn = nn.LSTM(ninp, nhid, nlayers, dropout=0)
          self.decoder = nn.Linear(nhid, ntoken)
          self.criterion = nn.CrossEntropyLoss().cuda()
          self.nvol_grad = None
  
          # Optionally tie weights as in:
          # "Using the Output Embedding to Improve Language Models" (Press & Wolf 2016)
          # https://arxiv.org/abs/1608.05859
          # and
          # "Tying Word Vectors and Word Classifiers: A Loss Framework for Language Modeling" (Inan et al. 2016)
          # https://arxiv.org/abs/1611.01462
          if tie_weights:
              if nhid != ninp:
                  raise ValueError('When using the tied flag, nhid must be equal to emsize')
              self.decoder.weight = self.encoder.weight
  
          self.init_weights()
  
          self.rnn_type = rnn_type
          self.nhid = nhid
          self.nlayers = nlayers
  
      def init_hidden(self, bsz):
          weight = next(self.parameters()).data
          return (Variable(weight.new(self.nlayers, bsz, self.nhid).zero_()),
                  Variable(weight.new(self.nlayers, bsz, self.nhid).zero_()))
  
      def init_weights(self):
          initrange = 0.1
          self.encoder.weight.data.uniform_(-initrange, initrange)
          self.decoder.bias.data.fill_(0)
          self.decoder.weight.data.uniform_(-initrange, initrange)
  
      def save_grad(self):
          def hook(grad):
              self.nvol_grad = grad
          return hook
  
      def forward(self, input, hidden):
          emb = self.drop(self.encoder(input))
          output, hidden = self.rnn(emb, hidden)
          output = self.drop(output)
          decoded = self.decoder(output.view(output.size(0)*output.size(1), output.size(2)))
          return decoded.view(output.size(0), output.size(1), decoded.size(1)), hidden
  
  