class_docstr: Performs pooling (max or mean) on the token embeddings.
  
  Using pooling, it generates from a variable sized sentence a fixed sized sentence embedding. This layer also allows to use the CLS token if it is returned by the underlying word embedding model.
  You can concatenate multiple poolings together.
  
  :param word_embedding_dimension: Dimensions for the word embeddings
  :param pooling_mode: Can be a string: mean/max/cls. If set, overwrites the other pooling_mode_* settings
  :param pooling_mode_cls_token: Use the first token (CLS token) as text representations
  :param pooling_mode_max_tokens: Use max in each dimension over all tokens.
  :param pooling_mode_mean_tokens: Perform mean-pooling
  :param pooling_mode_mean_sqrt_len_tokens: Perform mean-pooling, but divide by sqrt(input_length).
  :param pooling_mode_weightedmean_tokens: Perform (position) weighted mean pooling, see https://arxiv.org/abs/2202.08904
  :param pooling_mode_lasttoken: Perform last token pooling, see https://arxiv.org/abs/2202.08904 & https://arxiv.org/abs/2201.10005
code: def forward(self, features: Dict[str, Tensor]):
      token_embeddings = features["token_embeddings"]
      attention_mask = features["attention_mask"]
  
      ## Pooling strategy
      output_vectors = []
      if self.pooling_mode_cls_token:
          cls_token = features.get(
              "cls_token_embeddings", token_embeddings[:, 0]
          )  # Take first token by default
          output_vectors.append(cls_token)
      if self.pooling_mode_max_tokens:
          input_mask_expanded = (
              attention_mask.unsqueeze(-1)
              .expand(token_embeddings.size())
              .float()
          )
          token_embeddings[
              input_mask_expanded == 0
          ] = -1e9  # Set padding tokens to large negative value
          max_over_time = torch.max(token_embeddings, 1)[0]
          output_vectors.append(max_over_time)
      if (
          self.pooling_mode_mean_tokens
          or self.pooling_mode_mean_sqrt_len_tokens
      ):
          input_mask_expanded = (
              attention_mask.unsqueeze(-1)
              .expand(token_embeddings.size())
              .float()
          )
          sum_embeddings = torch.sum(
              token_embeddings * input_mask_expanded, 1
          )
  
          # If tokens are weighted (by WordWeights layer), feature 'token_weights_sum' will be present
          if "token_weights_sum" in features:
              sum_mask = (
                  features["token_weights_sum"]
                  .unsqueeze(-1)
                  .expand(sum_embeddings.size())
              )
          else:
              sum_mask = input_mask_expanded.sum(1)
  
          sum_mask = torch.clamp(sum_mask, min=1e-9)
  
          if self.pooling_mode_mean_tokens:
              output_vectors.append(sum_embeddings / sum_mask)
          if self.pooling_mode_mean_sqrt_len_tokens:
              output_vectors.append(
                  sum_embeddings / torch.sqrt(sum_mask)
              )
      if self.pooling_mode_weightedmean_tokens:
          input_mask_expanded = (
              attention_mask.unsqueeze(-1)
              .expand(token_embeddings.size())
              .float()
          )
          # token_embeddings shape: bs, seq, hidden_dim
          weights = (
              torch.arange(start=1, end=token_embeddings.shape[1] + 1)
              .unsqueeze(0)
              .unsqueeze(-1)
              .expand(token_embeddings.size())
              .float()
              .to(token_embeddings.device)
          )
          assert (
              weights.shape
              == token_embeddings.shape
              == input_mask_expanded.shape
          )
          input_mask_expanded = input_mask_expanded * weights
  
          sum_embeddings = torch.sum(
              token_embeddings * input_mask_expanded, 1
          )
  
          # If tokens are weighted (by WordWeights layer), feature 'token_weights_sum' will be present
          if "token_weights_sum" in features:
              sum_mask = (
                  features["token_weights_sum"]
                  .unsqueeze(-1)
                  .expand(sum_embeddings.size())
              )
          else:
              sum_mask = input_mask_expanded.sum(1)
  
          sum_mask = torch.clamp(sum_mask, min=1e-9)
          output_vectors.append(sum_embeddings / sum_mask)
      if self.pooling_mode_lasttoken:
          bs, seq_len, hidden_dim = token_embeddings.shape
          # attention_mask shape: (bs, seq_len)
          # Get shape [bs] indices of the last token (i.e. the last token for each batch item)
          # argmin gives us the index of the first 0 in the attention mask; We get the last 1 index by subtracting 1
          # Any sequence where min == 1, we use the entire sequence length since argmin = 0
          values, indices = torch.min(attention_mask, 1, keepdim=False)
          gather_indices = (
              torch.where(values == 0, indices, seq_len) - 1
          )  # Shape [bs]
  
          # There are empty sequences, where the index would become -1 which will crash
          gather_indices = torch.clamp(gather_indices, min=0)
  
          # Turn indices from shape [bs] --> [bs, 1, hidden_dim]
          gather_indices = gather_indices.unsqueeze(-1).repeat(
              1, hidden_dim
          )
          gather_indices = gather_indices.unsqueeze(1)
          assert gather_indices.shape == (bs, 1, hidden_dim)
  
          # Gather along the 1st dim (seq_len) (bs, seq_len, hidden_dim -> bs, hidden_dim)
          # Actually no need for the attention mask as we gather the last token where attn_mask = 1
          # but as we set some indices (which shouldn't be attended to) to 0 with clamp, we
          # use the attention mask to ignore them again
          input_mask_expanded = (
              attention_mask.unsqueeze(-1)
              .expand(token_embeddings.size())
              .float()
          )
          embedding = torch.gather(
              token_embeddings * input_mask_expanded, 1, gather_indices
          ).squeeze(dim=1)
          output_vectors.append(embedding)
  
      output_vector = torch.cat(output_vectors, 1)
      features.update({"sentence_embedding": output_vector})
      return features
  
file_path: sentence-transformers/sentence_transformers/models/Pooling.py
imports: import torch
  from torch import Tensor
  from torch import nn
  from typing import Dict
  import os
  import json
label_desc: Use image node_id 4 for calling the Pooling obj's underlying member method code with example usage: obj.forward(features) and returns: features