class_docstr: Combines multiple sparse and dense feature tensors into one dense tensor.
  
  This layer combines features from various featurisers into a single feature array
  per input example. All features must be of the same feature type, i.e. sentence-
  level or sequence-level (token-level).
  
  The layer combines a given list of tensors (whether sparse or dense) by:
  1. converting sparse tensors into dense ones
  2. optionally, applying dropout to sparse tensors before and/or after the conversion
  3. concatenating all tensors along the last dimension
  
  Arguments:
      attribute: Name of attribute (e.g. `text` or `label`) whose features will be
          processed.
      feature_type: Feature type to be processed -- `sequence` or `sentence`.
      feature_type_signature: A list of signatures for the given attribute and feature
          type.
      config: A model config for correctly parametrising the layer.
  
  Input shape:
      Tuple containing one list of N-D tensors, each with shape: `(batch_size, ...,
      input_dim)`.
      All dense tensors must have the same shape, except possibly the last dimension.
      All sparse tensors must have the same shape, including the last dimension.
  
  Output shape:
      N-D tensor with shape: `(batch_size, ..., units)` where `units` is the sum of
      the last dimension sizes across all input tensors, with sparse tensors instead
      contributing `config[DENSE_DIMENSION][attribute]` units each.
  
  Raises:
      A `TFLayerConfigException` if no feature signatures are provided.
  
  Attributes:
      output_units: The last dimension size of the layer's output.
class_docstr_tok: ["Combines","multiple","sparse","and","dense","feature","tensors","into","one","dense","tensor",".","This","layer","combines","features","from","various","featurisers","into","a","single","feature","array","per","input","example",".","All","features","must","be","of","the","same","feature","type",",","i.e",".","sentence-","level","or","sequence-level","(","token-level",")",".","The","layer","combines","a","given","list","of","tensors","(","whether","sparse","or","dense",")","by",":","1.","converting","sparse","tensors","into","dense","ones","2.","optionally",",","applying","dropout","to","sparse","tensors","before","and\/or","after","the","conversion","3.","concatenating","all","tensors","along","the","last","dimension","Arguments",":","attribute",":","Name","of","attribute","(","e.g",".","`","text","`","or","`","label","`",")","whose","features","will","be","processed",".","feature_type",":","Feature","type","to","be","processed","--","`","sequence","`","or","`","sentence","`",".","feature_type_signature",":","A","list","of","signatures","for","the","given","attribute","and","feature","type",".","config",":","A","model","config","for","correctly","parametrising","the","layer",".","Input","shape",":","Tuple","containing","one","list","of","N-D","tensors",",","each","with","shape",":","`","(","batch_size",",","...",",","input_dim",")","`",".","All","dense","tensors","must","have","the","same","shape",",","except","possibly","the","last","dimension",".","All","sparse","tensors","must","have","the","same","shape",",","including","the","last","dimension",".","Output","shape",":","N-D","tensor","with","shape",":","`","(","batch_size",",","...",",","units",")","`","where","`","units","`","is","the","sum","of","the","last","dimension","sizes","across","all","input","tensors",",","with","sparse","tensors","instead","contributing","`","config","[","DENSE_DIMENSION","]","[","attribute","]","`","units","each",".","Raises",":","A","`","TFLayerConfigException","`","if","no","feature","signatures","are","provided",".","Attributes",":","output_units",":","The","last","dimension","size","of","the","layer","'s","output","."]
docstr: Determines the output units from the provided feature signatures.
  
  Sparse features will be turned into dense ones, hence they each contribute with
  their future dense number of units.
docstr_tok: ["Determines","the","output","units","from","the","provided","feature","signatures",".","Sparse","features","will","be","turned","into","dense","ones",",","hence","they","each","contribute","with","their","future","dense","number","of","units","."]
code: def _calculate_output_units(
      attribute: Text,
      feature_type_signature: List[FeatureSignature],
      config: Dict[Text, Any],
  ) -> int:
      """Determines the output units from the provided feature signatures.
  
      Sparse features will be turned into dense ones, hence they each contribute with
      their future dense number of units.
      """
      return sum(
          [
              config[DENSE_DIMENSION][attribute]
              if signature.is_sparse
              else signature.units
              for signature in feature_type_signature
          ]
      )
  
imports: import tensorflow
  import numpy
  from typing import Text, List, Dict, Any, Union, Optional, Tuple, Callable
  from rasa.shared.nlu.constants import TEXT
  from rasa.utils.tensorflow.model_data import FeatureSignature
  from rasa.utils.tensorflow.constants import REGULARIZATION_CONSTANT, CONNECTION_DENSITY, NUM_TRANSFORMER_LAYERS, TRANSFORMER_SIZE, NUM_HEADS, UNIDIRECTIONAL_ENCODER, KEY_RELATIVE_ATTENTION, VALUE_RELATIVE_ATTENTION, MAX_RELATIVE_POSITION, MASKED_LM, HIDDEN_LAYERS_SIZES, DROP_RATE, SPARSE_INPUT_DROPOUT, DENSE_INPUT_DROPOUT, DENSE_DIMENSION, CONCAT_DIMENSION, DROP_RATE_ATTENTION, SEQUENCE, SENTENCE
  from rasa.utils.tensorflow import layers
  from rasa.utils.tensorflow.exceptions import TFLayerConfigException
  from rasa.utils.tensorflow.transformer import TransformerEncoder
  from rasa.nlu.constants import DEFAULT_TRANSFORMER_SIZE
label_desc: Use image node_id 4 for calling the ConcatenateSparseDenseFeatures obj's underlying member method code with example usage: obj._calculate_output_units(attribute, feature_type_signature, config) and returns: sum