def JSD_loss(self, inp, target):
        """
        Returns a JSDGAN loss

        :param inp: batch_size x seq_len, inp should be target with <s> (start letter) prepended
        :param target: batch_size x seq_len
        :return loss: loss to optimize
        """
        batch_size, seq_len = inp.size()
        hidden = self.init_hidden(batch_size)
        pred = self.forward(inp, hidden).view(batch_size, self.max_seq_len, self.vocab_size)
        target_onehot = F.one_hot(target, self.vocab_size).float()  # batch_size * seq_len * vocab_size
        pred = torch.sum(pred * target_onehot, dim=-1)  # batch_size * seq_len

        # calculate probabilities of sentences
        prob_gen = torch.exp(torch.sum(pred, dim=-1).double())  # sum of log prob
        prob_gen = self.min_max_normal(prob_gen).clamp(min=1e-10)
        prob_data = torch.DoubleTensor([1 / batch_size] * prob_gen.size(0))
        if self.gpu:
            prob_data = prob_data.cuda()

        # calculate the reward
        reward = torch.log(1. - torch.div(prob_data, prob_data + prob_gen))  # batch_size

        # check if nan
        if torch.isnan(reward).sum() > 0:
            print('Reward is nan!!!')
            exit(1)

        loss = torch.sum((prob_gen * reward).detach() * torch.sum(pred.double(), dim=-1))

        return loss

        Returns a JSDGAN loss

        :param inp: batch_size x seq_len, inp should be target with <s> (start letter) prepended
        :param target: batch_size x seq_len
        :return loss: loss to optimize
        
models/JSDGAN_G.py