We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
batch_first broken in AutogradRNN
The last line here fails on CPU or when CUDNN is otherwise unavailable:

```python
l, b, t, x, h = 2, 3, 5, 10, 20

rnn = nn.LSTM(x, h, l, batch_first=True)
inpt = Variable(torch.randn(b, t, x))
h0 = Variable(torch.randn(l, b, h))
c0 = Variable(torch.randn(l, b, h))
output, hn = rnn(inpt, (h0, c0))
```

This is because `AutogradRNN.forward` accidentally assumes `Tensor`'s in-place `transpose` semantics rather than the functional semantics of `Variable` (`cudnn.rnn.forward` gets it right):

```python
def forward(input, weight, hidden):
    if batch_first:
        input.transpose(0, 1)
    nexth, output = func(input, hidden, weight)
    if batch_first:
        output.transpose(0, 1)
```

I can push a PR that fixes this, or one of the devs can put it in the next bugfix PR:
```python
def forward(input, weight, hidden):
    if batch_first:
        input = input.transpose(0, 1)
    nexth, output = func(input, hidden, weight)
    if batch_first:
        output = output.transpose(0, 1)
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `torch/nn/functions/rnn.py`
Content:
```
1 from torch.autograd import Function, NestedIOFunction, Variable
2 from torch._thnn import type2backend
3 import torch.backends.cudnn as cudnn
4 try:
5     import torch.backends.cudnn.rnn
6 except ImportError:
7     pass
8 
9 
10 # FIXME: write a proper function library
11 from .thnn import Tanh, Sigmoid, Threshold
12 from .linear import Linear
13 from .dropout import Dropout
14 
15 
16 def _wrap(fn, *args):
17     def inner(*inner_args):
18         return fn(*args)(*inner_args)
19     return inner
20 tanh = _wrap(Tanh)
21 sigmoid = _wrap(Sigmoid)
22 ReLU = _wrap(Threshold, 0, 0, False)
23 
24 
25 # get around autograd's lack of None-handling
26 def linear(input, w, b):
27     if b is not None:
28         return Linear()(input, w, b)
29     else:
30         return Linear()(input, w)
31 
32 
33 def RNNReLUCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):
34         hy = ReLU(linear(input, w_ih, b_ih) + linear(hidden, w_hh, b_hh))
35         return hy
36 
37 
38 def RNNTanhCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):
39         hy = tanh(linear(input, w_ih, b_ih) + linear(hidden, w_hh, b_hh))
40         return hy
41 
42 
43 def LSTMCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):
44         hx, cx = hidden
45         gates = linear(input, w_ih, b_ih) + linear(hx, w_hh, b_hh)
46         ingate, forgetgate, cellgate, outgate = gates.chunk(4, 1)
47 
48         ingate = sigmoid(ingate)
49         forgetgate = sigmoid(forgetgate)
50         cellgate = tanh(cellgate)
51         outgate = sigmoid(outgate)
52 
53         cy = (forgetgate * cx) + (ingate * cellgate)
54         hy = outgate * tanh(cy)
55 
56         return hy, cy
57 
58 
59 def GRUCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):
60         gi = linear(input, w_ih, b_ih)
61         gh = linear(hidden, w_hh, b_hh)
62         i_r, i_i, i_n = gi.chunk(3, 1)
63         h_r, h_i, h_n = gh.chunk(3, 1)
64 
65         resetgate = sigmoid(i_r + h_r)
66         inputgate = sigmoid(i_i + h_i)
67         newgate = tanh(i_n + resetgate * h_n)
68         hy = newgate + inputgate * (hidden - newgate)
69 
70         return hy
71 
72 
73 def StackedRNN(inners, num_layers, lstm=False, dropout=0, train=True):
74 
75     num_directions = len(inners)
76     total_layers = num_layers * num_directions
77 
78     def forward(input, hidden, weight):
79         assert(len(weight) == total_layers)
80         next_hidden = []
81 
82         if lstm:
83             hidden = list(zip(*hidden))
84 
85         for i in range(num_layers):
86             all_output = []
87             for j, inner in enumerate(inners):
88                 l = i * num_directions + j
89 
90                 hy, output = inner(input, hidden[l], weight[l])
91                 next_hidden.append(hy)
92                 all_output.append(output)
93 
94             input = torch.cat(all_output, 2)
95 
96             if dropout != 0 and i < num_layers - 1:
97                 input = Dropout(p=dropout, train=train, inplace=False)(input)
98 
99         if lstm:
100             next_h, next_c = zip(*next_hidden)
101             next_hidden = (
102                 torch.cat(next_h, 0).view(total_layers, *next_h[0].size()),
103                 torch.cat(next_c, 0).view(total_layers, *next_c[0].size())
104             )
105         else:
106             next_hidden = torch.cat(next_hidden, 0).view(
107                 total_layers, *next_hidden[0].size())
108 
109         return next_hidden, input
110 
111     return forward
112 
113 def Recurrent(inner, reverse=False):
114     def forward(input, hidden, weight):
115         output = []
116         steps = range(input.size(0) - 1, -1, -1) if reverse else range(input.size(0))
117         for i in steps:
118             hidden = inner(input[i], hidden, *weight)
119             # hack to handle LSTM
120             output.append(isinstance(hidden, tuple) and hidden[0] or hidden)
121 
122         if reverse:
123             output.reverse()
124         output = torch.cat(output, 0).view(input.size(0), *output[0].size())
125 
126         return hidden, output
127 
128     return forward
129 
130 
131 def AutogradRNN(mode, input_size, hidden_size, num_layers=1, batch_first=False, dropout=0, train=True, bidirectional=False):
132 
133     if mode == 'RNN_RELU':
134         cell = RNNReLUCell
135     elif mode == 'RNN_TANH':
136         cell = RNNTanhCell
137     elif mode == 'LSTM':
138         cell = LSTMCell
139     elif mode == 'GRU':
140         cell = GRUCell
141     else:
142         raise Exception('Unknown mode: {}'.format(mode))
143 
144     if bidirectional:
145         layer = (Recurrent(cell), Recurrent(cell, reverse=True))
146     else:
147         layer = (Recurrent(cell),)
148 
149     func = StackedRNN(layer,
150                       num_layers,
151                       (mode == 'LSTM'),
152                       dropout=dropout,
153                       train=train)
154 
155     def forward(input, weight, hidden):
156         if batch_first:
157             input.transpose(0, 1)
158 
159         nexth, output = func(input, hidden, weight)
160 
161         if batch_first:
162             output.transpose(0, 1)
163 
164         return output, nexth
165 
166     return forward
167 
168 
169 class CudnnRNN(NestedIOFunction):
170     def __init__(self, mode, input_size, hidden_size, num_layers=1, batch_first=False, dropout=0, train=True, bidirectional=False):
171         super(CudnnRNN, self).__init__()
172         self.mode = cudnn.rnn.get_cudnn_mode(mode)
173         self.input_mode = cudnn.CUDNN_LINEAR_INPUT
174         self.input_size = input_size
175         self.hidden_size = hidden_size
176         self.num_layers = num_layers
177         self.batch_first = batch_first
178         self.dropout = dropout
179         self.train = train
180         self.bidirectional = 1 if bidirectional else 0
181         self.num_directions = 2 if bidirectional else 1
182         self.seed = torch.IntTensor(1).random_()[0]
183 
184     def forward_extended(self, input, weight, hx):
185 
186         assert(cudnn.is_acceptable(input))
187 
188         output = input.new()
189 
190         if torch.is_tensor(hx):
191             hy = hx.new()
192         else:
193             hy = tuple(h.new() for h in hx)
194 
195         cudnn.rnn.forward(self, input, hx, weight, output, hy)
196 
197         self.save_for_backward(input, hx, weight, output)
198         return output, hy
199 
200 
201     def backward_extended(self, grad_output, grad_hy):
202         input, hx, weight, output = self.saved_tensors
203 
204         grad_input, grad_weight, grad_hx = None, None, None
205 
206         assert(cudnn.is_acceptable(input))
207 
208         grad_input = input.new()
209         grad_weight = input.new()
210         grad_hx = input.new()
211         if torch.is_tensor(hx):
212             grad_hx = input.new()
213         else:
214             grad_hx = tuple(h.new() for h in hx)
215 
216         cudnn.rnn.backward_grad(
217             self,
218             input,
219             hx,
220             weight,
221             output,
222             grad_output,
223             grad_hy,
224             grad_input,
225             grad_hx)
226 
227         if self.needs_input_grad[1]:
228             grad_weight = [tuple(w.new().resize_as_(w).zero_() for w in layer_weight) for layer_weight in weight]
229             cudnn.rnn.backward_weight(
230                 self,
231                 input,
232                 hx,
233                 output,
234                 weight,
235                 grad_weight)
236 
237         return grad_input, grad_weight, grad_hx
238 
239 
240 def RNN(*args, **kwargs):
241     def forward(input, *fargs, **fkwargs):
242         if cudnn.is_acceptable(input.data):
243             func = CudnnRNN(*args, **kwargs)
244         else:
245             func = AutogradRNN(*args, **kwargs)
246         return func(input, *fargs, **fkwargs)
247 
248     return forward
249
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/torch/nn/functions/rnn.py b/torch/nn/functions/rnn.py
--- a/torch/nn/functions/rnn.py
+++ b/torch/nn/functions/rnn.py
@@ -154,12 +154,12 @@
 
     def forward(input, weight, hidden):
         if batch_first:
-            input.transpose(0, 1)
+            input = input.transpose(0, 1)
 
         nexth, output = func(input, hidden, weight)
 
         if batch_first:
-            output.transpose(0, 1)
+            output = output.transpose(0, 1)
 
         return output, nexth

{"golden_diff": "diff --git a/torch/nn/functions/rnn.py b/torch/nn/functions/rnn.py\n--- a/torch/nn/functions/rnn.py\n+++ b/torch/nn/functions/rnn.py\n@@ -154,12 +154,12 @@\n \n     def forward(input, weight, hidden):\n         if batch_first:\n-            input.transpose(0, 1)\n+            input = input.transpose(0, 1)\n \n         nexth, output = func(input, hidden, weight)\n \n         if batch_first:\n-            output.transpose(0, 1)\n+            output = output.transpose(0, 1)\n \n         return output, nexth\n", "issue": "batch_first broken in AutogradRNN\nThe last line here fails on CPU or when CUDNN is otherwise unavailable:\r\n\r\n```python\r\nl, b, t, x, h = 2, 3, 5, 10, 20\r\n\r\nrnn = nn.LSTM(x, h, l, batch_first=True)\r\ninpt = Variable(torch.randn(b, t, x))\r\nh0 = Variable(torch.randn(l, b, h))\r\nc0 = Variable(torch.randn(l, b, h))\r\noutput, hn = rnn(inpt, (h0, c0))\r\n```\r\n\r\nThis is because `AutogradRNN.forward` accidentally assumes `Tensor`'s in-place `transpose` semantics rather than the functional semantics of `Variable` (`cudnn.rnn.forward` gets it right):\r\n\r\n```python\r\ndef forward(input, weight, hidden):\r\n    if batch_first:\r\n        input.transpose(0, 1)\r\n    nexth, output = func(input, hidden, weight)\r\n    if batch_first:\r\n        output.transpose(0, 1)\r\n```\r\n\r\nI can push a PR that fixes this, or one of the devs can put it in the next bugfix PR:\r\n```python\r\ndef forward(input, weight, hidden):\r\n    if batch_first:\r\n        input = input.transpose(0, 1)\r\n    nexth, output = func(input, hidden, weight)\r\n    if batch_first:\r\n        output = output.transpose(0, 1)\r\n```\n", "before_files": [{"content": "from torch.autograd import Function, NestedIOFunction, Variable\nfrom torch._thnn import type2backend\nimport torch.backends.cudnn as cudnn\ntry:\n    import torch.backends.cudnn.rnn\nexcept ImportError:\n    pass\n\n\n# FIXME: write a proper function library\nfrom .thnn import Tanh, Sigmoid, Threshold\nfrom .linear import Linear\nfrom .dropout import Dropout\n\n\ndef _wrap(fn, *args):\n    def inner(*inner_args):\n        return fn(*args)(*inner_args)\n    return inner\ntanh = _wrap(Tanh)\nsigmoid = _wrap(Sigmoid)\nReLU = _wrap(Threshold, 0, 0, False)\n\n\n# get around autograd's lack of None-handling\ndef linear(input, w, b):\n    if b is not None:\n        return Linear()(input, w, b)\n    else:\n        return Linear()(input, w)\n\n\ndef RNNReLUCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        hy = ReLU(linear(input, w_ih, b_ih) + linear(hidden, w_hh, b_hh))\n        return hy\n\n\ndef RNNTanhCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        hy = tanh(linear(input, w_ih, b_ih) + linear(hidden, w_hh, b_hh))\n        return hy\n\n\ndef LSTMCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        hx, cx = hidden\n        gates = linear(input, w_ih, b_ih) + linear(hx, w_hh, b_hh)\n        ingate, forgetgate, cellgate, outgate = gates.chunk(4, 1)\n\n        ingate = sigmoid(ingate)\n        forgetgate = sigmoid(forgetgate)\n        cellgate = tanh(cellgate)\n        outgate = sigmoid(outgate)\n\n        cy = (forgetgate * cx) + (ingate * cellgate)\n        hy = outgate * tanh(cy)\n\n        return hy, cy\n\n\ndef GRUCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        gi = linear(input, w_ih, b_ih)\n        gh = linear(hidden, w_hh, b_hh)\n        i_r, i_i, i_n = gi.chunk(3, 1)\n        h_r, h_i, h_n = gh.chunk(3, 1)\n\n        resetgate = sigmoid(i_r + h_r)\n        inputgate = sigmoid(i_i + h_i)\n        newgate = tanh(i_n + resetgate * h_n)\n        hy = newgate + inputgate * (hidden - newgate)\n\n        return hy\n\n\ndef StackedRNN(inners, num_layers, lstm=False, dropout=0, train=True):\n\n    num_directions = len(inners)\n    total_layers = num_layers * num_directions\n\n    def forward(input, hidden, weight):\n        assert(len(weight) == total_layers)\n        next_hidden = []\n\n        if lstm:\n            hidden = list(zip(*hidden))\n\n        for i in range(num_layers):\n            all_output = []\n            for j, inner in enumerate(inners):\n                l = i * num_directions + j\n\n                hy, output = inner(input, hidden[l], weight[l])\n                next_hidden.append(hy)\n                all_output.append(output)\n\n            input = torch.cat(all_output, 2)\n\n            if dropout != 0 and i < num_layers - 1:\n                input = Dropout(p=dropout, train=train, inplace=False)(input)\n\n        if lstm:\n            next_h, next_c = zip(*next_hidden)\n            next_hidden = (\n                torch.cat(next_h, 0).view(total_layers, *next_h[0].size()),\n                torch.cat(next_c, 0).view(total_layers, *next_c[0].size())\n            )\n        else:\n            next_hidden = torch.cat(next_hidden, 0).view(\n                total_layers, *next_hidden[0].size())\n\n        return next_hidden, input\n\n    return forward\n\ndef Recurrent(inner, reverse=False):\n    def forward(input, hidden, weight):\n        output = []\n        steps = range(input.size(0) - 1, -1, -1) if reverse else range(input.size(0))\n        for i in steps:\n            hidden = inner(input[i], hidden, *weight)\n            # hack to handle LSTM\n            output.append(isinstance(hidden, tuple) and hidden[0] or hidden)\n\n        if reverse:\n            output.reverse()\n        output = torch.cat(output, 0).view(input.size(0), *output[0].size())\n\n        return hidden, output\n\n    return forward\n\n\ndef AutogradRNN(mode, input_size, hidden_size, num_layers=1, batch_first=False, dropout=0, train=True, bidirectional=False):\n\n    if mode == 'RNN_RELU':\n        cell = RNNReLUCell\n    elif mode == 'RNN_TANH':\n        cell = RNNTanhCell\n    elif mode == 'LSTM':\n        cell = LSTMCell\n    elif mode == 'GRU':\n        cell = GRUCell\n    else:\n        raise Exception('Unknown mode: {}'.format(mode))\n\n    if bidirectional:\n        layer = (Recurrent(cell), Recurrent(cell, reverse=True))\n    else:\n        layer = (Recurrent(cell),)\n\n    func = StackedRNN(layer,\n                      num_layers,\n                      (mode == 'LSTM'),\n                      dropout=dropout,\n                      train=train)\n\n    def forward(input, weight, hidden):\n        if batch_first:\n            input.transpose(0, 1)\n\n        nexth, output = func(input, hidden, weight)\n\n        if batch_first:\n            output.transpose(0, 1)\n\n        return output, nexth\n\n    return forward\n\n\nclass CudnnRNN(NestedIOFunction):\n    def __init__(self, mode, input_size, hidden_size, num_layers=1, batch_first=False, dropout=0, train=True, bidirectional=False):\n        super(CudnnRNN, self).__init__()\n        self.mode = cudnn.rnn.get_cudnn_mode(mode)\n        self.input_mode = cudnn.CUDNN_LINEAR_INPUT\n        self.input_size = input_size\n        self.hidden_size = hidden_size\n        self.num_layers = num_layers\n        self.batch_first = batch_first\n        self.dropout = dropout\n        self.train = train\n        self.bidirectional = 1 if bidirectional else 0\n        self.num_directions = 2 if bidirectional else 1\n        self.seed = torch.IntTensor(1).random_()[0]\n\n    def forward_extended(self, input, weight, hx):\n\n        assert(cudnn.is_acceptable(input))\n\n        output = input.new()\n\n        if torch.is_tensor(hx):\n            hy = hx.new()\n        else:\n            hy = tuple(h.new() for h in hx)\n\n        cudnn.rnn.forward(self, input, hx, weight, output, hy)\n\n        self.save_for_backward(input, hx, weight, output)\n        return output, hy\n\n\n    def backward_extended(self, grad_output, grad_hy):\n        input, hx, weight, output = self.saved_tensors\n\n        grad_input, grad_weight, grad_hx = None, None, None\n\n        assert(cudnn.is_acceptable(input))\n\n        grad_input = input.new()\n        grad_weight = input.new()\n        grad_hx = input.new()\n        if torch.is_tensor(hx):\n            grad_hx = input.new()\n        else:\n            grad_hx = tuple(h.new() for h in hx)\n\n        cudnn.rnn.backward_grad(\n            self,\n            input,\n            hx,\n            weight,\n            output,\n            grad_output,\n            grad_hy,\n            grad_input,\n            grad_hx)\n\n        if self.needs_input_grad[1]:\n            grad_weight = [tuple(w.new().resize_as_(w).zero_() for w in layer_weight) for layer_weight in weight]\n            cudnn.rnn.backward_weight(\n                self,\n                input,\n                hx,\n                output,\n                weight,\n                grad_weight)\n\n        return grad_input, grad_weight, grad_hx\n\n\ndef RNN(*args, **kwargs):\n    def forward(input, *fargs, **fkwargs):\n        if cudnn.is_acceptable(input.data):\n            func = CudnnRNN(*args, **kwargs)\n        else:\n            func = AutogradRNN(*args, **kwargs)\n        return func(input, *fargs, **fkwargs)\n\n    return forward\n", "path": "torch/nn/functions/rnn.py"}], "after_files": [{"content": "from torch.autograd import Function, NestedIOFunction, Variable\nfrom torch._thnn import type2backend\nimport torch.backends.cudnn as cudnn\ntry:\n    import torch.backends.cudnn.rnn\nexcept ImportError:\n    pass\n\n\n# FIXME: write a proper function library\nfrom .thnn import Tanh, Sigmoid, Threshold\nfrom .linear import Linear\nfrom .dropout import Dropout\n\n\ndef _wrap(fn, *args):\n    def inner(*inner_args):\n        return fn(*args)(*inner_args)\n    return inner\ntanh = _wrap(Tanh)\nsigmoid = _wrap(Sigmoid)\nReLU = _wrap(Threshold, 0, 0, False)\n\n\n# get around autograd's lack of None-handling\ndef linear(input, w, b):\n    if b is not None:\n        return Linear()(input, w, b)\n    else:\n        return Linear()(input, w)\n\n\ndef RNNReLUCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        hy = ReLU(linear(input, w_ih, b_ih) + linear(hidden, w_hh, b_hh))\n        return hy\n\n\ndef RNNTanhCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        hy = tanh(linear(input, w_ih, b_ih) + linear(hidden, w_hh, b_hh))\n        return hy\n\n\ndef LSTMCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        hx, cx = hidden\n        gates = linear(input, w_ih, b_ih) + linear(hx, w_hh, b_hh)\n        ingate, forgetgate, cellgate, outgate = gates.chunk(4, 1)\n\n        ingate = sigmoid(ingate)\n        forgetgate = sigmoid(forgetgate)\n        cellgate = tanh(cellgate)\n        outgate = sigmoid(outgate)\n\n        cy = (forgetgate * cx) + (ingate * cellgate)\n        hy = outgate * tanh(cy)\n\n        return hy, cy\n\n\ndef GRUCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):\n        gi = linear(input, w_ih, b_ih)\n        gh = linear(hidden, w_hh, b_hh)\n        i_r, i_i, i_n = gi.chunk(3, 1)\n        h_r, h_i, h_n = gh.chunk(3, 1)\n\n        resetgate = sigmoid(i_r + h_r)\n        inputgate = sigmoid(i_i + h_i)\n        newgate = tanh(i_n + resetgate * h_n)\n        hy = newgate + inputgate * (hidden - newgate)\n\n        return hy\n\n\ndef StackedRNN(inners, num_layers, lstm=False, dropout=0, train=True):\n\n    num_directions = len(inners)\n    total_layers = num_layers * num_directions\n\n    def forward(input, hidden, weight):\n        assert(len(weight) == total_layers)\n        next_hidden = []\n\n        if lstm:\n            hidden = list(zip(*hidden))\n\n        for i in range(num_layers):\n            all_output = []\n            for j, inner in enumerate(inners):\n                l = i * num_directions + j\n\n                hy, output = inner(input, hidden[l], weight[l])\n                next_hidden.append(hy)\n                all_output.append(output)\n\n            input = torch.cat(all_output, 2)\n\n            if dropout != 0 and i < num_layers - 1:\n                input = Dropout(p=dropout, train=train, inplace=False)(input)\n\n        if lstm:\n            next_h, next_c = zip(*next_hidden)\n            next_hidden = (\n                torch.cat(next_h, 0).view(total_layers, *next_h[0].size()),\n                torch.cat(next_c, 0).view(total_layers, *next_c[0].size())\n            )\n        else:\n            next_hidden = torch.cat(next_hidden, 0).view(\n                total_layers, *next_hidden[0].size())\n\n        return next_hidden, input\n\n    return forward\n\ndef Recurrent(inner, reverse=False):\n    def forward(input, hidden, weight):\n        output = []\n        steps = range(input.size(0) - 1, -1, -1) if reverse else range(input.size(0))\n        for i in steps:\n            hidden = inner(input[i], hidden, *weight)\n            # hack to handle LSTM\n            output.append(isinstance(hidden, tuple) and hidden[0] or hidden)\n\n        if reverse:\n            output.reverse()\n        output = torch.cat(output, 0).view(input.size(0), *output[0].size())\n\n        return hidden, output\n\n    return forward\n\n\ndef AutogradRNN(mode, input_size, hidden_size, num_layers=1, batch_first=False, dropout=0, train=True, bidirectional=False):\n\n    if mode == 'RNN_RELU':\n        cell = RNNReLUCell\n    elif mode == 'RNN_TANH':\n        cell = RNNTanhCell\n    elif mode == 'LSTM':\n        cell = LSTMCell\n    elif mode == 'GRU':\n        cell = GRUCell\n    else:\n        raise Exception('Unknown mode: {}'.format(mode))\n\n    if bidirectional:\n        layer = (Recurrent(cell), Recurrent(cell, reverse=True))\n    else:\n        layer = (Recurrent(cell),)\n\n    func = StackedRNN(layer,\n                      num_layers,\n                      (mode == 'LSTM'),\n                      dropout=dropout,\n                      train=train)\n\n    def forward(input, weight, hidden):\n        if batch_first:\n            input = input.transpose(0, 1)\n\n        nexth, output = func(input, hidden, weight)\n\n        if batch_first:\n            output = output.transpose(0, 1)\n\n        return output, nexth\n\n    return forward\n\n\nclass CudnnRNN(NestedIOFunction):\n    def __init__(self, mode, input_size, hidden_size, num_layers=1, batch_first=False, dropout=0, train=True, bidirectional=False):\n        super(CudnnRNN, self).__init__()\n        self.mode = cudnn.rnn.get_cudnn_mode(mode)\n        self.input_mode = cudnn.CUDNN_LINEAR_INPUT\n        self.input_size = input_size\n        self.hidden_size = hidden_size\n        self.num_layers = num_layers\n        self.batch_first = batch_first\n        self.dropout = dropout\n        self.train = train\n        self.bidirectional = 1 if bidirectional else 0\n        self.num_directions = 2 if bidirectional else 1\n        self.seed = torch.IntTensor(1).random_()[0]\n\n    def forward_extended(self, input, weight, hx):\n\n        assert(cudnn.is_acceptable(input))\n\n        output = input.new()\n\n        if torch.is_tensor(hx):\n            hy = hx.new()\n        else:\n            hy = tuple(h.new() for h in hx)\n\n        cudnn.rnn.forward(self, input, hx, weight, output, hy)\n\n        self.save_for_backward(input, hx, weight, output)\n        return output, hy\n\n\n    def backward_extended(self, grad_output, grad_hy):\n        input, hx, weight, output = self.saved_tensors\n\n        grad_input, grad_weight, grad_hx = None, None, None\n\n        assert(cudnn.is_acceptable(input))\n\n        grad_input = input.new()\n        grad_weight = input.new()\n        grad_hx = input.new()\n        if torch.is_tensor(hx):\n            grad_hx = input.new()\n        else:\n            grad_hx = tuple(h.new() for h in hx)\n\n        cudnn.rnn.backward_grad(\n            self,\n            input,\n            hx,\n            weight,\n            output,\n            grad_output,\n            grad_hy,\n            grad_input,\n            grad_hx)\n\n        if self.needs_input_grad[1]:\n            grad_weight = [tuple(w.new().resize_as_(w).zero_() for w in layer_weight) for layer_weight in weight]\n            cudnn.rnn.backward_weight(\n                self,\n                input,\n                hx,\n                output,\n                weight,\n                grad_weight)\n\n        return grad_input, grad_weight, grad_hx\n\n\ndef RNN(*args, **kwargs):\n    def forward(input, *fargs, **fkwargs):\n        if cudnn.is_acceptable(input.data):\n            func = CudnnRNN(*args, **kwargs)\n        else:\n            func = AutogradRNN(*args, **kwargs)\n        return func(input, *fargs, **fkwargs)\n\n    return forward\n", "path": "torch/nn/functions/rnn.py"}]}