Search code examples
pythontheanorecurrent-neural-network

Issue with computing gradient for Rnn in Theano


I am playing with vanilla Rnn's, training with gradient descent (non-batch version), and I am having an issue with the gradient computation for the (scalar) cost; here's the relevant portion of my code:

class Rnn(object):
# ............ [skipping the trivial initialization]
    def recurrence(x_t, h_tm_prev):
        h_t = T.tanh(T.dot(x_t, self.W_xh) +
                     T.dot(h_tm_prev, self.W_hh) + self.b_h)
        return h_t

    h, _ = theano.scan(
        recurrence,
        sequences=self.input,
        outputs_info=self.h0
    )

    y_t = T.dot(h[-1], self.W_hy) + self.b_y
    self.p_y_given_x = T.nnet.softmax(y_t)

    self.y_pred = T.argmax(self.p_y_given_x, axis=1)


def negative_log_likelihood(self, y):
    return -T.mean(T.log(self.p_y_given_x)[:, y])


def testRnn(dataset, vocabulary, learning_rate=0.01, n_epochs=50):
   # ............ [skipping the trivial initialization]
   index = T.lscalar('index')
   x = T.fmatrix('x')
   y = T.iscalar('y')
   rnn = Rnn(x, n_x=27, n_h=12, n_y=27)
   nll = rnn.negative_log_likelihood(y)
   cost = T.lscalar('cost')
   gparams = [T.grad(cost, param) for param in rnn.params]
   updates = [(param, param - learning_rate * gparam)
              for param, gparam in zip(rnn.params, gparams)
              ]
   train_model = theano.function(
       inputs=[index],
       outputs=nll,
       givens={
           x: train_set_x[index],
           y: train_set_y[index]
       },
   )
   sgd_step = theano.function(
       inputs=[cost],
       outputs=[],
       updates=updates
   )
   done_looping = False
   while(epoch < n_epochs) and (not done_looping):
       epoch += 1
       tr_cost = 0.
       for idx in xrange(n_train_examples):
           tr_cost += train_model(idx)
       # perform sgd step after going through the complete training set
       sgd_step(tr_cost)

For some reasons I don't want to pass complete (training) data to the train_model(..), instead I want to pass individual examples at a time. Now the problem is that each call to train_model(..) returns me the cost (negative log-likelihood) of that particular example and then I have to aggregate all the cost (of the complete (training) data-set) and then take derivative and perform the relevant update to the weight parameters in the sgd_step(..), and for obvious reasons with my current implementation I am getting this error: theano.gradient.DisconnectedInputError: grad method was asked to compute the gradient with respect to a variable that is not part of the computational graph of the cost, or is used only by a non-differentiable operator: W_xh. Now I don't understand how to make 'cost' a part of computational graph (as in my case when I have to wait for it to be aggregated) or is there any better/elegant way to achieve the same thing ?

Thanks.


Solution

  • It turns out one cannot bring the symbolic variable into Theano graph if they are not part of computational graph. Therefore, I have to change the way to pass data to the train_model(..); passing the complete training data instead of individual example fix the issue.