class_docstr: This class implements an attentive statistic pooling layer for each channel.
  It returns the concatenated mean and std of the input tensor.
  
  Arguments
  ---------
  channels: int
      The number of input channels.
  attention_channels: int
      The number of attention channels.
  
  Example
  -------
  >>> inp_tensor = torch.rand([8, 120, 64]).transpose(1, 2)
  >>> asp_layer = AttentiveStatisticsPooling(64)
  >>> lengths = torch.rand((8,))
  >>> out_tensor = asp_layer(inp_tensor, lengths).transpose(1, 2)
  >>> out_tensor.shape
  torch.Size([8, 1, 128])
class_docstr_tok: ["This","class","implements","an","attentive","statistic","pooling","layer","for","each","channel",".","It","returns","the","concatenated","mean","and","std","of","the","input","tensor",".","Arguments","--","--","--","--","-","channels",":","int","The","number","of","input","channels",".","attention_channels",":","int","The","number","of","attention","channels",".","Example","--","--","--","-",">",">",">","inp_tensor","=","torch.rand","(","[","8",",","120",",","64","]",")",".transpose","(","1",",","2",")",">",">",">","asp_layer","=","AttentiveStatisticsPooling","(","64",")",">",">",">","lengths","=","torch.rand","(","(","8",",",")",")",">",">",">","out_tensor","=","asp_layer","(","inp_tensor",",","lengths",")",".transpose","(","1",",","2",")",">",">",">","out_tensor.shape","torch.Size","(","[","8",",","1",",","128","]",")"]
docstr: Calculates mean and std for a batch (input tensor).
  
  Arguments
  ---------
  x : torch.Tensor
      Tensor of shape [N, C, L].
docstr_tok: ["Calculates","mean","and","std","for","a","batch","(","input","tensor",")",".","Arguments","--","--","--","--","-","x",":","torch.Tensor","Tensor","of","shape","[","N",",","C",",","L","]","."]
code: def forward(self, x, lengths=None):
      """Calculates mean and std for a batch (input tensor).
  
      Arguments
      ---------
      x : torch.Tensor
          Tensor of shape [N, C, L].
      """
      L = x.shape[-1]
  
      def _compute_statistics(x, m, dim=2, eps=self.eps):
          mean = (m * x).sum(dim)
          std = torch.sqrt(
              (m * (x - mean.unsqueeze(dim)).pow(2)).sum(dim).clamp(eps)
          )
          return mean, std
  
      if lengths is None:
          lengths = torch.ones(x.shape[0], device=x.device)
  
      # Make binary mask of shape [N, 1, L]
      mask = length_to_mask(lengths * L, max_len=L, device=x.device)
      mask = mask.unsqueeze(1)
  
      # Expand the temporal context of the pooling layer by allowing the
      # self-attention to look at global properties of the utterance.
      if self.global_context:
          # torch.std is unstable for backward computation
          # https://github.com/pytorch/pytorch/issues/4320
          total = mask.sum(dim=2, keepdim=True).float()
          mean, std = _compute_statistics(x, mask / total)
          mean = mean.unsqueeze(2).repeat(1, 1, L)
          std = std.unsqueeze(2).repeat(1, 1, L)
          attn = torch.cat([x, mean, std], dim=1)
      else:
          attn = x
  
      # Apply layers
      attn = self.conv(self.tanh(self.tdnn(attn)))
  
      # Filter out zero-paddings
      attn = attn.masked_fill(mask == 0, float("-inf"))
  
      attn = F.softmax(attn, dim=2)
      mean, std = _compute_statistics(x, attn)
      # Append mean and std of the batch
      pooled_stats = torch.cat((mean, std), dim=1)
      pooled_stats = pooled_stats.unsqueeze(2)
  
      return pooled_stats
  
imports: import torch
  import torch.nn
  import torch.nn.functional
  from speechbrain.dataio.dataio import length_to_mask
  from speechbrain.nnet.CNN import Conv1d
  from speechbrain.nnet.normalization import BatchNorm1d
  from speechbrain.nnet.linear import Linear
label_desc: Use image node_id 2 for calling the AttentiveStatisticsPooling obj's underlying member method code with example usage: obj.forward(x, lengths) and returns: pooled_stats, mean,  std