Pytorch simple text generator not working and loss keeps diverging
I am new to pytorch and deep learning in general , and am trying to build a simple text generator. For reasons I don't understand, the loss keeps diverging and the model doesn't. Here's the code.

class RNN(nn.Module):
    def __init__(self, embed_size, hidden_size):
        super(RNN, self).__init__()
        self.embeds = nn.Embedding(num_chars, embed_size)
        self.l1 = nn.Linear(embed_size, hidden_size)
        self.l2 = nn.Linear(hidden_size, hidden_size)
        self.l3 = nn.Linear(hidden_size, num_chars)
        self.relu = nn.ReLU()
        self.softmax = nn.Softmax()

    def forward(self, inp):
        out = self.embeds(inp)
        out = self.l3(self.relu(self.l2(self.relu(self.l1(out)))))
        return self.softmax(out)

rnn = RNN(10, 50)
optimizer = torch.optim.Adam(rnn.parameters(), lr = 0.002)
criterion = nn.NLLLoss()

def charTensor(x):
    out = torch.zeros(1, num_chars)
    out[0][all_chars.index(x)] = 1
    return out.long()

for epoch in range(5):
    epoch_loss = 0
    rnn.zero_grad()
    for i in range(len(train_str[:400])-1):

        inp = charTensor(train_str[i])
        output = rnn(inp)
        loss = criterion(output, charTensor(train_str[i+1]))
        epoch_loss += loss

        loss.backward(retain_graph=True)
        optimizer.step()

    print("Epoch Loss:", epoch_loss) //epoch loss is always tensor(-399)

first_char = 'c'
inp_t = charTensor(first_char)
fin = first_char
for i in range(10):
    next_t = rnn(inp_t)
    next_char = all_chars[torch.argmax(next_t).numpy()]   //always ends up as 0, which is the char for space
    fin += next_char   
    inp_t = charTensor(next_char)
print(fin)    //prints new line



Are you trying to implement an RNN? Because I see you are naming your model as RNN but the implementation doesn't seem to take signals from previous time steps.
It seems that you are not implementing batches and are training based on inputting 1 character and then backpropagating on that. This is known to cause instability. You may want to iterate over a few characters and accumulated the loss and average it before backpropagating.


In generating text, what you want to do is train the model by having prepared sequence of data for example "the fox jumped over the lazy dog". In a word level prediction, your input would be: 

["the","fox","jumped", "over","the","lazy"] 


and the target would be:

["fox","jumped", "over","the","lazy", "dog"]        


What model does is try to predict the next word given the previous words.
In character level, then simply change the list to each character withing the sentence. That way you will have a model that learns the probability distribution.

For PyTorch specific implementation check here: https://pytorch.org/tutorials/intermediate/char_rnn_generation_tutorial.html

Also, you don't need retain_graph=True as it will build up memory. Instead just type:

    loss.backward()
    optimizer.step()
    optimizer.zero_grad()

