class_docstr: Collection of EmbeddingTowers.
  
  Args:
      towers (List[EmbeddingTower]): list of embedding towers that make up the
          collection.
      device (Optional[torch.device]): default compute device.
  
  Example::
  
      ebc, ebc_interaction = EmbeddingBagCollection(), MyEBCInteractionModule()
      eb, eb_interaction = EmbeddingCollection(), MyECInteractionModule()
      tower_0 = EmbeddingTower(ebc, ebc_interaction, device)
      tower_1 = EmbeddingTower(eb, eb_interaction, device)
      tower_collection = EmbeddingTowerCollection([tower_0, tower_1])
      kjt = KeyedJaggedTensor()
      output = tower_collection(kjt)
docstr: Executes the collection of towers.
  
  Features and/or weighted features must be provided as required by the
  underlying embedding modules.
  
  Args:
      features (Optional[KeyedJaggedTensor]):
      weighted_features (Optional[KeyedJaggedTensor]):
  
  Returns:
      torch.Tensor: 2-D tensor of shape `M X B`, where `M = sum(N_i)` for tower output i, and `B` is local batch size.
docstr_tok: ["Executes","the","collection","of","towers",".","Features","and\/or","weighted","features","must","be","provided","as","required","by","the","underlying","embedding","modules",".","Args",":","features","(","Optional","[","KeyedJaggedTensor","]",")",":","weighted_features","(","Optional","[","KeyedJaggedTensor","]",")",":","Returns",":","torch.Tensor",":","2-D","tensor","of","shape","`","M","X","B","`",",","where","`","M","=","sum","(","N_i",")","`","for","tower","output","i",",","and","`","B","`","is","local","batch","size","."]
code: def forward(
      self,
      features: Optional[KeyedJaggedTensor] = None,
      weighted_features: Optional[KeyedJaggedTensor] = None,
  ) -> torch.Tensor:
      """
      Executes the collection of towers.
  
      Features and/or weighted features must be provided as required by the
      underlying embedding modules.
  
      Args:
          features (Optional[KeyedJaggedTensor]):
          weighted_features (Optional[KeyedJaggedTensor]):
  
      Returns:
          torch.Tensor: 2-D tensor of shape `M X B`, where `M = sum(N_i)` for tower output i, and `B` is local batch size.
      """
  
      tower_outputs = []
      for tower, input_params in zip(self.towers, self._input_params):
          has_kjt_param, has_wkjt_param = input_params
          if has_kjt_param and has_wkjt_param:
              assert features is not None
              assert weighted_features is not None
              tower_outputs.append(tower(features, weighted_features))
          elif has_wkjt_param:
              assert weighted_features is not None
              tower_outputs.append(tower(weighted_features))
          else:
              assert features is not None
              tower_outputs.append(tower(features))
  
      return torch.cat(tower_outputs, dim=1)
  
file_path: torchrec/torchrec/modules/embedding_tower.py
imports: from typing import List, Optional, Tuple
  import torch
  import torch.nn
  from torchrec.modules.embedding_modules import EmbeddingBagCollection, EmbeddingCollection
  from torchrec.sparse.jagged_tensor import KeyedJaggedTensor
label_desc: Use image node_id 2 for calling the EmbeddingTowerCollection obj's underlying member method code with example usage: obj.forward(features, weighted_features) and returns: torch