class_docstr: An implementation for an explainable neural network for natural
  language processing and generating rationales used by that network.
  Based on the paper "Rethinking Cooperative Rationalization: Introspective
  Extraction and Complement Control" by Yu et. al.
docstr: Inputs:
      X_tokens -- torch Variable in shape of (batch_size, length)
      mask -- torch Variable in shape of (batch_size, length)
  Outputs:
      predict -- (batch_size, num_label)
      z -- rationale (batch_size, length)
docstr_tok: ["Inputs",":","X_tokens","--","torch","Variable","in","shape","of","(","batch_size",",","length",")","mask","--","torch","Variable","in","shape","of","(","batch_size",",","length",")","Outputs",":","predict","--","(","batch_size",",","num_label",")","z","--","rationale","(","batch_size",",","length",")"]
code: def forward(self, X_tokens, X_mask):
      """
      Inputs:
          X_tokens -- torch Variable in shape of (batch_size, length)
          mask -- torch Variable in shape of (batch_size, length)
      Outputs:
          predict -- (batch_size, num_label)
          z -- rationale (batch_size, length)
      """
      """Forward pass in the model.
  
          :param X_tokens: tokenized embedded examples with shape
              (batch_size, length)
          :type X_tokens: torch Variable
          :param X_mask: mask differentiating word from padding tokens
              with shape (batch_size, length)
          :type X_mask: torch Variable
  
          :return: dictionary with fields:
              "predict": prediction using generated rationales,
              "anti_predict": prediction using complements of generated
                  rationales,
              "cls_predict": prediction by the introspective classifier in the
                  generator,
              "z": generated rationale,
              "neg_log_probs": negative log probabilities of sampling each
                  rationale
          :rtype: dict
          """
      z_scores_, cls_predict, word_embeddings = self.generator(
          X_tokens, X_mask
      )
  
      z_probs_ = F.softmax(z_scores_, dim=-1)
  
      z_probs_ = (
          X_mask.unsqueeze(-1)
          * (
              (1 - self.exploration_rate) * z_probs_
              + self.exploration_rate / z_probs_.size(-1)
          )
      ) + ((1 - X_mask.unsqueeze(-1)) * z_probs_)
  
      z, neg_log_probs = self._generate_rationales(
          z_probs_
      )  # dimensions (batch_size, length)
  
      if not self.args.bert_explainers:
          predict = self.E_model(X_tokens, X_mask, z)[
              0
          ]  # the first output are the logits
          anti_predict = self.E_anti_model(X_tokens, X_mask, (1 - z))[0]
      else:
          predict = self.E_model(X_tokens, attention_mask=z)[
              0
          ]  # the first output are the logits
          anti_predict = self.E_anti_model(
              X_tokens, attention_mask=(1 - z)
          )[0]
      return {
          "predict": predict,
          "anti_predict": anti_predict,
          "cls_predict": cls_predict,
          "z": z,
          "neg_log_probs": neg_log_probs,
      }
  
imports: import logging
  import os
  import random
  from collections import deque
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from interpret_text.experimental.common.base_text_model import BaseTextModel
  from torch.autograd import Variable
  from tqdm import tqdm
  from interpret_text.experimental.common.utils_introspective_rationale import generate_data
label_desc: Use image node_id 7 for calling the IntrospectiveRationaleModel obj's underlying member method code with example usage: obj.forward(X_tokens, X_mask) and returns: dict