How to collect the predictions for each observation in pytorch?
Im trying to make a RNN myself using a loop rather than the nn.rnn module. But I would still like to use pytorch's backward for backpropogation. 

Each observation makes 1 prediction which is then used for subsequent predictions. But how should each prediction be stored such that we can calculate the loss and get back propagation? 

can we just create a normal list and append to it with each prediction? Or will that not allow back propogation?

Yes. That would work. PyTorch creates a computational graph with nodes for all the operations that you perform during the forward pass. So, for each operation in the for loop, no matter how you store the outputs (or even if you discard them), you should still be able to call backward on the loss as the information required for computing gradients is already there in the graph.

Here's a toy example:

import torch
from torch import nn
import torch.nn.functional as F

class RNN(nn.Module):
    def __init__(self, in_dim, hidden_dim, out_dim):
        super().__init__()
        self.wh = nn.Linear(hidden_dim, hidden_dim)
        self.wx = nn.Linear(in_dim, hidden_dim)
        self.wo = nn.Linear(hidden_dim, out_dim)
        self.hidden_dim = hidden_dim

    def forward(self, xs, hidden):
        outputs = []
        hiddens = []
        hiddens.append(hidden)
        for i, x in enumerate(xs):
            hiddens.append(torch.tanh(self.wx(x) + self.wh(hiddens[i])))
            outputs.append(F.log_softmax(self.wo(hiddens[i+1]), dim=0))
        return outputs, hiddens

    def init_hidden(self):
        return torch.zeros(self.hidden_dim)

# Initialize the input and output
x = torch.tensor([[1., 0., 0.], [0., 1., 0.], [1., 0., 0.]])
y = torch.tensor([1])

# Initialize the network, hidden state and loss function
rnn = RNN(3, 10, 2)
hidden = rnn.init_hidden()
nll = nn.NLLLoss()

# Forward pass
outputs, hidden_states = rnn(x, hidden)

# Compute loss
loss = nll(outputs[-1].unsqueeze(0), y)

# Call Backward on the loss
loss.backward()

# Inspect the computed gradients
print(rnn.wh.weight.grad)   # Gives a tensor of shape (10, 10) in this case


