class_docstr: SplitCrossEntropyLoss calculates an approximate softmax
code: def logprob(
      self,
      weight,
      bias,
      hiddens,
      splits=None,
      softmaxed_head_res=None,
      verbose=False,
  ):
      # First we perform the first softmax on the head vocabulary and the tombstones
      if softmaxed_head_res is None:
          start, end = self.splits[0], self.splits[1]
          head_weight = None if end - start == 0 else weight[start:end]
          head_bias = None if end - start == 0 else bias[start:end]
          # We only add the tombstones if we have more than one split
          if self.nsplits > 1:
              head_weight = (
                  self.tail_vectors
                  if head_weight is None
                  else torch.cat([head_weight, self.tail_vectors])
              )
              head_bias = (
                  self.tail_bias
                  if head_bias is None
                  else torch.cat([head_bias, self.tail_bias])
              )
  
          # Perform the softmax calculation for the word vectors in the head for all splits
          # We need to guard against empty splits as torch.cat does not like random lists
          head_res = torch.nn.functional.linear(
              hiddens, head_weight, bias=head_bias
          )
          softmaxed_head_res = torch.nn.functional.log_softmax(
              head_res, dim=-1
          )
  
      if splits is None:
          splits = list(range(self.nsplits))
  
      results = []
      running_offset = 0
      for idx in splits:
          # For those targets in the head (idx == 0) we only need to return their loss
          if idx == 0:
              results.append(
                  softmaxed_head_res[:, : -(self.nsplits - 1)]
              )
  
          # If the target is in one of the splits, the probability is the p(tombstone) * p(word within tombstone)
          else:
              start, end = self.splits[idx], self.splits[idx + 1]
              tail_weight = weight[start:end]
              tail_bias = bias[start:end]
  
              # Calculate the softmax for the words in the tombstone
              tail_res = torch.nn.functional.linear(
                  hiddens, tail_weight, bias=tail_bias
              )
  
              # Then we calculate p(tombstone) * p(word in tombstone)
              # Adding is equivalent to multiplication in log space
              head_entropy = (softmaxed_head_res[:, -idx]).contiguous()
              tail_entropy = torch.nn.functional.log_softmax(
                  tail_res, dim=-1
              )
              results.append(head_entropy.view(-1, 1) + tail_entropy)
  
      if len(results) > 1:
          return torch.cat(results, dim=1)
      return results[0]
  
file_path: awd-lstm-lm/splitcross.py
imports: from collections import defaultdict
  import torch
  import torch.nn
  import numpy
label_desc: Use image node_id 2 for calling the SplitCrossEntropyLoss obj's underlying member method code with example usage: obj.logprob(weight, bias, hiddens, splits, softmaxed_head_res, verbose) and returns: results, torch