Repository: Theano/Theano

Issue:
crash in gradient calculation of scan 
Consider this simple example. The combination of the two scans and the `.grad` call, causes an `IndexError: list assignment index out of range` error. This is when using `0.7rc2`

``` python
import numpy as np
import theano
import theano.tensor as T

# data input & output
x = T.tensor3('x')
t = T.imatrix('t')

# forward pass
W = theano.shared(
    np.random.randn(2, 2).astype('float32'),
    name="W", borrow=True)

def forward_scanner(x_t):
    a2_t = T.dot(x_t, W)
    y_t = T.nnet.softmax(a2_t)

    return y_t

y, _ = theano.scan(fn=forward_scanner, sequences=x, outputs_info=[None])

# loss function
def error_scanner(y_t, t_t):
    return T.mean(T.nnet.categorical_crossentropy(y_t, t_t))

L, _ = theano.scan(fn=error_scanner, sequences=[y, t], outputs_info=[None])
L = T.mean(L)

# backward pass
gW = T.grad(L, [W]) # this will raise an error
```

This is the total traceback:

```
Traceback (most recent call last):
  File "explore_theano/crash.py", line 37, in <module>
    gW = T.grad(L, [W])
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 546, in grad
    grad_dict, wrt, cost_name)
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 1284, in _populate_grad_dict
    rval = [access_grad_cache(elem) for elem in wrt]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 1284, in <listcomp>
    rval = [access_grad_cache(elem) for elem in wrt]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 1242, in access_grad_cache
    term = access_term_cache(node)[idx]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 952, in access_term_cache
    output_grads = [access_grad_cache(var) for var in node.outputs]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 952, in <listcomp>
    output_grads = [access_grad_cache(var) for var in node.outputs]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 1242, in access_grad_cache
    term = access_term_cache(node)[idx]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 952, in access_term_cache
    output_grads = [access_grad_cache(var) for var in node.outputs]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 952, in <listcomp>
    output_grads = [access_grad_cache(var) for var in node.outputs]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 1242, in access_grad_cache
    term = access_term_cache(node)[idx]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 952, in access_term_cache
    output_grads = [access_grad_cache(var) for var in node.outputs]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 952, in <listcomp>
    output_grads = [access_grad_cache(var) for var in node.outputs]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 1242, in access_grad_cache
    term = access_term_cache(node)[idx]
  File "/usr/local/lib/python3.4/site-packages/theano/gradient.py", line 1090, in access_term_cache
    input_grads = node.op.grad(inputs, new_output_grads)
  File "/usr/local/lib/python3.4/site-packages/theano/scan_module/scan_op.py", line 1936, in grad
    dtype=theano.config.floatX)
IndexError: list assignment index out of range
```



Discussion:

Resolving patch:
diff --git a/theano/scan_module/scan_op.py b/theano/scan_module/scan_op.py
--- a/theano/scan_module/scan_op.py
+++ b/theano/scan_module/scan_op.py
@@ -1931,9 +1931,10 @@ def compute_gradient(y, g_y):
                 type_outs.append(vl.type.why_null)
                 # Replace the inner output with a zero tensor of
                 # the right shape
-                inner_out_sitsot[_p] = tensor.zeros(
+                inner_out_nitsot[_p] = tensor.zeros(
                     diff_inputs[_p].shape,
                     dtype=theano.config.floatX)
+
             if through_shared:
                 type_outs.append('through_shared')
             elif disconnected_dC_dinps_t[_p]:


Test patch:
diff --git a/theano/scan_module/tests/test_scan.py b/theano/scan_module/tests/test_scan.py
--- a/theano/scan_module/tests/test_scan.py
+++ b/theano/scan_module/tests/test_scan.py
@@ -836,6 +836,36 @@ def fn(a_m2, a_m1, b_m2, b_m1):
                         n_steps=2)
         tensor.grad(a[-1], a0)
 
+    def test_grad_two_scans(self):
+
+        # data input & output
+        x = tensor.tensor3('x')
+        t = tensor.imatrix('t')
+
+        # forward pass
+        W = theano.shared(
+            numpy.random.randn(2, 2).astype('float32'),
+            name="W", borrow=True)
+
+        def forward_scanner(x_t):
+            a2_t = tensor.dot(x_t, W)
+            y_t = tensor.nnet.softmax(a2_t)
+            return y_t
+
+        y, _ = theano.scan(fn=forward_scanner, sequences=x,
+                           outputs_info=[None])
+
+        # loss function
+        def error_scanner(y_t, t_t):
+            return tensor.mean(tensor.nnet.categorical_crossentropy(y_t, t_t))
+
+        L, _ = theano.scan(fn=error_scanner, sequences=[y, t],
+                           outputs_info=[None])
+        L = tensor.mean(L)
+
+        # backward pass
+        gW = tensor.grad(L, [W])
+
     # simple rnn, one input, one state, weights for each; input/state are
     # vectors, weights are scalars; using shared variables and past
     # taps (sequences and outputs)