class_docstr: Noise from BART.
class_docstr_tok: ["Noise","from","BART","."]
code: def whole_word_mask(self, tokens, p=1.0):  # text span mask/infilling
      is_word_start = torch.tensor(self._is_word_start(tokens)).int()
      n_mask = int(math.ceil(is_word_start.sum() * p))
      n_insert = 0
      if n_mask == 0:
          return tokens
  
      if (
          self.mask_span_distribution is not None
      ):  # Text (span) Infilling
          lengths = self.mask_span_distribution.sample(
              sample_shape=(n_mask,)
          )
  
          # Make sure we have enough to mask
          cum_length = torch.cumsum(lengths, 0)
          while cum_length[-1] < n_mask:
              lengths = torch.cat(
                  [
                      lengths,
                      self.mask_span_distribution.sample(
                          sample_shape=(n_mask,)
                      ),
                  ],
                  dim=0,
              )
              cum_length = torch.cumsum(lengths, 0)
  
          # Trim to masking budget
          i = 0
          while cum_length[i] < n_mask:
              i += 1
          lengths[i] = n_mask - (0 if i == 0 else cum_length[i - 1])
          n_mask = i + 1
          lengths = lengths[:n_mask]
  
          # Handle 0-length mask (inserts) separately
          lengths = lengths[lengths > 0]
          n_insert = n_mask - lengths.size(0)
          n_mask -= n_insert
          if n_mask == 0:
              return self.insertion_noise(
                  tokens, n_insert / len(tokens)
              )
  
          assert (lengths > 0).all()
      else:  # Token Masking
          lengths = torch.ones((n_mask,)).long()
      # assert is_word_start[-1] == 0
      word_starts = is_word_start.nonzero(as_tuple=False)
      indices = word_starts[
          torch.randperm(word_starts.size(0))[:n_mask]
      ].squeeze(1)
      mask_random = (
          torch.FloatTensor(n_mask).uniform_() < self.random_ratio
      )
  
      tokens_length = len(tokens)
      # assert tokens_length - 1 not in indices
      to_keep = torch.ones(tokens_length, dtype=torch.bool)
  
      if self.replace_length == 0:
          to_keep[indices] = 0
      else:
          # keep index, but replace it with [MASK]
          for i in indices.tolist():
              tokens[i] = self.mask_tok
          random_tok_ids = torch.randint(
              0, len(self.vocab), size=(mask_random.sum(),)
          ).tolist()
          for i, rid in zip(
              indices[mask_random].tolist(), random_tok_ids
          ):
              tokens[i] = self.vocab[rid]
  
      if tokens_length - 1 in indices:
          uncompleted = indices != tokens_length - 1
          indices = indices[uncompleted]
          mask_random = mask_random[uncompleted]
          lengths = lengths[uncompleted]
  
      # acts as a long length, so spans don't go over the end of doc
      is_word_start[-1] = 255
  
      if self.mask_span_distribution is not None:
          assert len(lengths.size()) == 1
          assert lengths.size() == indices.size()
          lengths -= 1  # 1 for the position already masked
          while indices.size(0) > 0:
              assert lengths.size() == indices.size()
              # next position from each word_start
              lengths -= is_word_start[indices + 1].long()
              uncompleted = lengths >= 0
              indices = indices[uncompleted] + 1
              mask_random = mask_random[uncompleted]
              lengths = lengths[uncompleted]
              if self.replace_length != -1:
                  # delete token: 1 mask/remove per span
                  to_keep[indices] = 0
              else:
                  # keep index, but replace it with [MASK]: 1 mask per token
                  for i in indices.tolist():
                      tokens[i] = self.mask_tok
                  random_tok_ids = torch.randint(
                      0, len(self.vocab), size=(mask_random.sum(),)
                  ).tolist()
                  for i, rid in zip(
                      indices[mask_random].tolist(), random_tok_ids
                  ):
                      tokens[i] = self.vocab[rid]
      else:
          # A bit faster when all lengths are 1
          while indices.size(0) > 0:
              # to cover whole token
              uncompleted = is_word_start[indices + 1] == 0
              indices = indices[uncompleted] + 1
              mask_random = mask_random[uncompleted]
              if self.replace_length != -1:
                  # delete token
                  to_keep[indices] = 0
              else:
                  # keep index, but replace it with [MASK]
                  for i in indices.tolist():
                      tokens[i] = self.mask_tok
                  random_tok_ids = torch.randint(
                      0, len(self.vocab), size=(mask_random.sum(),)
                  ).tolist()
                  for i, rid in zip(
                      indices[mask_random].tolist(), random_tok_ids
                  ):
                      tokens[i] = self.vocab[rid]
  
              # assert tokens_length - 1 not in indices
  
      tokens = [
          tok
          for tok, keep in zip(tokens, to_keep.tolist())
          if keep is True
      ]
  
      if n_insert > 0:
          tokens = self.insertion_noise(tokens, n_insert / len(tokens))
  
      return tokens
  
imports: import math
  import numpy
  import torch
  from typing import Sequence, Callable
  from onmt.constants import DefaultTokens, SubwordMarker
  from onmt.transforms import register_transform
  from .transform import Transform
label_desc: Use image node_id 6 for calling the BARTNoising obj's underlying member method code with example usage: obj.whole_word_mask(tokens, p) and returns: tokens, tokens, self