# Stateful RNN example

**URL:** <https://discuss.pytorch.org/t/stateful-rnn-example/10912>\
**Category:** Uncategorized\
**Created:** [December 8, 2017, 5:03am UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912 "2017-12-08T05:03:52Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![syhpoon](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/syhpoon/32/2623_2.png) [@syhpoon](https://discuss.pytorch.org/u/syhpoon)\
**Post date:** [December 8, 2017, 5:03am UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/1 "2017-12-08T05:03:52Z")

</div>

Hi there,

I’m trying to implement a time-series prediction rnn and for this I try to construct a stateful model.  
Basically because I have a huge sequence I want to reuse states from previous batches instead of having them reset every time. Keras RNN class has a `stateful` parameter enabling exactly this behavior:

> stateful: Boolean (default False). If True, the last state for each sample at index i in a batch will be used as initial state for the sample of index i in the following batch.

I couldn’t find anything similar for pytorch and my attempts to make something like this manually failed so far.  
Basically what I try to do is save variable tensors after `forward` pass and use them as initial state for `h` and `c` variables for LSTMCell on the subsequent `forward` calls.

I’m very new to pytorch so I’m probably doing something very wrong but so far I’m stuck.  
I’d really appreciate any hint or any example of stateful RNN in pytorch.

---

<div class="post-metadata">

**Author:** ![jodles](https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/j/8edcca/32.png) [@jodles](https://discuss.pytorch.org/u/jodles)\
**Post date:** [December 8, 2017, 9:13am UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/2 "2017-12-08T09:13:02Z")

</div>

This thread may be relevant: [[Solved] Training a simple RNN](https://discuss.pytorch.org/t/solved-training-a-simple-rnn/9055)

A key point is that to keep hidden state Variable across batches without having to specify `retain_graph=True` you need to detach the Variable: `hidden.detach()`.

---

<div class="post-metadata">

**Author:** ![dgriff](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/dgriff/32/1361_2.png) [@dgriff](https://discuss.pytorch.org/u/dgriff)\
**Post date:** [December 11, 2017, 10:06am UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/3 "2017-12-11T10:06:36Z")

</div>

to do something like this in pytorch you would just do something like:

```auto
class Model(torch.nn.Module):
    def __init__ (self, hidden_size):
        super(Model, self). __init__ ()
        self.lstm = nn.LSTMCell(1, hidden_size)
    def forward(self, inputs): #and then in def forward:
        x, (hx, cx) = inputs
        x = x.view(x.size(0), -1)
        hx, cx = self.lstm(x, (hx, cx))
        x = hx
        return x, (hx, cx)

flag=True #to flag when at start of time series

if flag: #beginning of sequence of data you want cell states from or when no longer need past cell state and starting fresh again
    cx = Variable(torch.zeros(1, hidden_size))
    hx = Variable(torch.zeros(1, hidden_size))
else: #get cell state from last sequence batch to use as start of new batch
    cx = Variable(cx.data)
    hx = Variable(hx.data)

#input equals Variable of 1 by num of features at each time step

model = Model(hidden_size)
output, (hx, cx) = model((input, (hx, cx))

```

---

<div class="post-metadata">

**Author:** ![syhpoon](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/syhpoon/32/2623_2.png) [@syhpoon](https://discuss.pytorch.org/u/syhpoon)\
**Post date:** [December 11, 2017, 4:46pm UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/4 "2017-12-11T16:46:49Z")

</div>

Thank you! This is very helpful.

---

<div class="post-metadata">

**Author:** ![dgriff](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/dgriff/32/1361_2.png) [@dgriff](https://discuss.pytorch.org/u/dgriff)\
**Post date:** [December 12, 2017, 7:14am UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/5 "2017-12-12T07:14:36Z")

</div>

glad to hear it 👍

oh fyi this part:

```auto
else: #get cell state from last sequence batch to use as start of new batch
    cx = Variable(cx.data)
    hx = Variable(hx.data)

```

This serves same function as the hidden.detach() part stated above. I just prefer to create a fresh new Variable for each batch than reuse the same one

---

<div class="post-metadata">

**Author:** ![syhpoon](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/syhpoon/32/2623_2.png) [@syhpoon](https://discuss.pytorch.org/u/syhpoon)\
**Post date:** [December 21, 2017, 3:28pm UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/6 "2017-12-21T15:28:00Z")

</div>

So here’s the model I’ve been able to make:

```python
#!/usr/bin/env python

import torch
import torch.nn as nn
import torch.optim as opt
import numpy as np

from torch.autograd import Variable
import pandas as pd

torch.manual_seed(1)

num_epochs = 1
hidden_size = 100

def var(tensor):
    if torch.cuda.is_available():
        return Variable(tensor.cuda())
    else:
        return Variable(tensor)

class Model(nn.Module):
    def __init__ (self, input_size=1, hidden_size=hidden_size, output_size=1,
                 num_layers=2):
        super(Model, self). __init__ ()
        self.num_layers = num_layers
        self.hidden_size = hidden_size

        self.lstm = nn.LSTM(input_size, hidden_size, num_layers=num_layers)
        self.linear = nn.Linear(hidden_size, hidden_size)
        self.relu = nn.ReLU()
        self.out = nn.Linear(hidden_size, output_size)

    def forward(self, x, hidden):
        lstm_out, hidden = self.lstm(x, hidden)
        linear_out = self.linear(lstm_out)
        relu_out = self.relu(linear_out)
        out = self.out(relu_out)

        return out, hidden

    def init_hidden(self):
        return (var(torch.zeros(self.num_layers, 1, self.hidden_size)),
                var(torch.zeros(self.num_layers, 1, self.hidden_size)))

def load_data(n):
    ix = np.arange(n)
    data = np.sin(2*np.pi*ix/float(n/2))

    return (torch.from_numpy(data[:-1]).float(),
            torch.from_numpy(data[1:]).float())

def train(ds):
    model = Model()
    # criterion = nn.MSELoss()
    criterion = nn.L1Loss()
    optimizer = opt.Adam(model.parameters(), lr=0.0002)

    if torch.cuda.is_available():
        print("Using GPU")
        model.cuda()

    lsum = 0.0
    lcount = 0.0

    hidden = model.init_hidden()

    losses = []

    for epoch in range(num_epochs):
        for i, (_x, _y) in enumerate(zip(ds[0], ds[1])):
            x = torch.zeros(1, 1, 1)
            y = torch.zeros(1, 1, 1)

            x[0][0][0] = _x
            y[0][0][0] = _y

            out, hidden = model(var(x), hidden)
            loss = criterion(out, var(y))
            loss.backward()
            hidden = (var(hidden[0].data), var(hidden[1].data))

            lsum += loss.data[0]
            lcount += 1
            losses.append(loss.data[0])

            optimizer.step()
            optimizer.zero_grad()

            if i % 1000 == 0:
                l = lsum / lcount
                print('Epoch: %i, Loss: %.7f' % (epoch, l))
                lsum = 0.0
                lcount = 0.0

if __name__ == " __main__":
    train(load_data(100000))

```

It does not seem to be able to learn even the simple sine function, here’s the plot of losses:

 ![loss](https://discuss.pytorch.org/uploads/default/original/2X/d/d1ce0939460495ceb92b30f4d5fa51fa1cba59d3.png)

The loss just seems to oscillate along with the input.  
I’d really appreciate any hint on what is it I’m doing wrong.

---

<div class="post-metadata">

**Author:** ![jpeg729](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/jpeg729/32/3464_2.png) [@jpeg729](https://discuss.pytorch.org/u/jpeg729)\
**Post date:** [December 21, 2017, 3:55pm UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/7 "2017-12-21T15:55:59Z")

</div>

Won’t detaching the hidden Variable cut off BPTT?

---

<div class="post-metadata">

**Author:** ![jodles](https://discuss.pytorch.org/letter_avatar_proxy/v4/letter/j/8edcca/32.png) [@jodles](https://discuss.pytorch.org/u/jodles)\
**Post date:** [December 21, 2017, 4:37pm UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/8 "2017-12-21T16:37:17Z")

</div>

Yes, but you’d do it between minibatches, like `Variable(hx.data)` as in dgriff’s example above and serves the same purpose.

---

<div class="post-metadata">

**Author:** ![Jianmo\_Ni](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/jianmo_ni/32/1770_2.png) [@Jianmo\_Ni](https://discuss.pytorch.org/u/Jianmo_Ni)\
**Post date:** [April 9, 2018, 1:17am UTC](https://discuss.pytorch.org/t/stateful-rnn-example/10912/9 "2018-04-09T01:17:34Z")

</div>

Hi, have you been able to figure out the reason why it did not work?
