class_docstr: Connect a sequence of blocks with shortcut connections.
  
  Note: all shortcuts start from the output of the first block,
  since the first block may change the shape significantly.
  
  Arguments
  ---------
  input_shape : tuple
      The shape of the
  shortcut_type : str
      One of:
      * "residual" - first block output passed to final output,
      * "dense" - input of each block is from all previous blocks,
      * "skip" - output of each block is passed to final output.
  shortcut_projection : bool
      Only has an effect if `shortcut_type` is passed. Whether to add a
      linear projection layer to the shortcut connection before combining
      with the output, to handle different sizes.
  shortcut_combine_fn : str or function
      Either a pre-defined function (one of "add", "sub", "mul", "div",
      "avg", "cat") or a user-defined function that takes the shortcut
      and next input, and combines them, as well as `init_params`
      in case parameters need to be initialized inside of the function.
  
  Example
  -------
  >>> inputs = torch.rand(10, 100, 20)
  >>> model = ConnectBlocks(
  ...     input_shape=inputs.shape, shortcut_projection=True
  ... )
  >>> model.append(Linear, n_neurons=10)
  >>> model.append(Linear, n_neurons=10, end_of_block=True)
  >>> model.append(Linear, n_neurons=10)
  >>> model.append(Linear, n_neurons=10, end_of_block=True)
  >>> outputs = model(inputs)
  >>> outputs.shape
  torch.Size([10, 100, 10])
docstr: Appends the specified module to the shortcut model.
  
  Arguments
  ---------
  layer : torch.nn.Module class
      This layer will get initialized with *args and **kwargs. Also,
      the argument ``input_shape`` will be passed if the layer takes it.
  *args, **kwargs
      Passed unchanged to the layer **EXCEPT** the kwarg ``end_of_block``
      which is used to indicate that the shortcut should be added in.
docstr_tok: ["Appends","the","specified","module","to","the","shortcut","model",".","Arguments","--","--","--","--","-","layer",":","torch.nn.Module","class","This","layer","will","get","initialized","with","*","args","and","*","*","kwargs",".","Also",",","the","argument","``","input_shape","``","will","be","passed","if","the","layer","takes","it",".","*","args",",","*","*","kwargs","Passed","unchanged","to","the","layer","*","*","EXCEPT","*","*","the","kwarg","``","end_of_block","``","which","is","used","to","indicate","that","the","shortcut","should","be","added","in","."]
code: def append(self, layer, *args, **kwargs):
      """Appends the specified module to the shortcut model.
  
      Arguments
      ---------
      layer : torch.nn.Module class
          This layer will get initialized with *args and **kwargs. Also,
          the argument ``input_shape`` will be passed if the layer takes it.
      *args, **kwargs
          Passed unchanged to the layer **EXCEPT** the kwarg ``end_of_block``
          which is used to indicate that the shortcut should be added in.
      """
      if self.new_block:
          self.blocks.append(
              Sequential(input_shape=self.block_input_shape)
          )
          self.new_block = False
  
      end_of_block = False
      if "end_of_block" in kwargs:
          end_of_block = kwargs["end_of_block"]
          del kwargs["end_of_block"]
  
      self.blocks[-1].append(layer, *args, **kwargs)
  
      # When we reach the end of the block, prepare to add shortcut
      if end_of_block:
          # Use dummy input to find shape of next block
          dummy_input = torch.zeros(self.block_input_shape)
          dummy_output = self.blocks[-1](dummy_input)
  
          # Initialize projection if necessary
          if self.shortcut_projection:
              projection_size = functools.reduce(
                  operator.mul, dummy_output.shape[2:], 1
              )
  
              if self.shortcut_type == "residual":
                  shape = self.first_input_shape
                  dummy_input = torch.zeros(self.first_input_shape)
              else:
                  shape = self.block_input_shape
  
              self.projections.append(
                  Linear(
                      n_neurons=projection_size,
                      input_shape=shape,
                      bias=False,
                      combine_dims=True,
                  )
              )
  
          # Prepare for next block
          self.new_block = True
          dummy_output = self._combine(dummy_input, dummy_output, -1)
          self.block_input_shape = dummy_output.shape
  
imports: import torch
  import inspect
  import logging
  import operator
  import functools
  from speechbrain.nnet.linear import Linear
  from speechbrain.utils.callchains import lengths_arg_exists
label_desc: Use image node_id 2 for calling the ConnectBlocks obj's underlying member method code with example usage: obj.append(layer) without return types