def METHOD_NAME(self):
    self._model.train()
    unroll_length = self._config.unroll_length
    num_batches = (self._train_data.shape[0] - 1) // unroll_length
    state = self.get_initial_train_state(self._train_data.shape[1])
    for batch in range(num_batches):
        alf.summary.increment_global_counter()
        loss = []
        for t in range(batch * unroll_length, (batch + 1) * unroll_length):
            data = self._train_data[t]
            target = self._train_data[t + 1]
            output, state = self._model(data, state)
            l = self._lossf(output, target)
            loss.append(l)
        state = common.detach(state)
        loss = torch.stack(loss)
        ppl = loss.mean().exp()
        loss_info = LossInfo(loss=loss, extra=dict(ppl=ppl))
        loss_info, params = self.update_with_gradient(loss_info)
        self.summarize_train(None, None, loss_info, params)