class_docstr: <a id="bottleneck_residual_block"></a>
  
  ## Bottleneck Residual Block
  
  This implements the bottleneck block described in the paper.
  It has $1   imes 1$, $3     imes 3$, and $1         imes 1$ convolution layers.
  
  ![Bottlenext Block](bottleneck_block.svg)
  
  The first convolution layer maps from `in_channels` to `bottleneck_channels` with a $1      imes 1$
  convolution,
  where the `bottleneck_channels` is lower than `in_channels`.
  
  The second $3       imes 3$ convolution layer maps from `bottleneck_channels` to `bottleneck_channels`.
  This can have a stride length greater than $1$ when we want to compress the
  feature map size.
  
  The third, final $1         imes 1$ convolution layer maps to `out_channels`.
  `out_channels` is higher than `in_channels` if the stride length is greater than $1$;
  otherwise, $out_channels$ is equal to `in_channels`.
  
  `bottleneck_channels` is less than `in_channels` and the $3         imes 3$ convolution is performed
  on this shrunk space (hence the bottleneck). The two $1     imes 1$ convolution decreases and increases
  the number of channels.
class_docstr_tok: ["<","a","id=","''","bottleneck_residual_block","''",">","<","\/a",">","#","#","Bottleneck","Residual","Block","This","implements","the","bottleneck","block","described","in","the","paper",".","It","has","$","1","imes","1","$",",","$","3","imes","3","$",",","and","$","1","imes","1","$","convolution","layers",".","!","[","Bottlenext","Block","]","(","bottleneck_block.svg",")","The","first","convolution","layer","maps","from","`","in_channels","`","to","`","bottleneck_channels","`","with","a","$","1","imes","1","$","convolution",",","where","the","`","bottleneck_channels","`","is","lower","than","`","in_channels","`",".","The","second","$","3","imes","3","$","convolution","layer","maps","from","`","bottleneck_channels","`","to","`","bottleneck_channels","`",".","This","can","have","a","stride","length","greater","than","$","1","$","when","we","want","to","compress","the","feature","map","size",".","The","third",",","final","$","1","imes","1","$","convolution","layer","maps","to","`","out_channels","`",".","`","out_channels","`","is","higher","than","`","in_channels","`","if","the","stride","length","is","greater","than","$","1","$",";","otherwise",",","$","out_channels","$","is","equal","to","`","in_channels","`",".","`","bottleneck_channels","`","is","less","than","`","in_channels","`","and","the","$","3","imes","3","$","convolution","is","performed","on","this","shrunk","space","(","hence","the","bottleneck",")",".","The","two","$","1","imes","1","$","convolution","decreases","and","increases","the","number","of","channels","."]
docstr: * `x` is the input of shape `[batch_size, in_channels, height, width]`
docstr_tok: ["*","`","x","`","is","the","input","of","shape","`","[","batch_size",",","in_channels",",","height",",","width","]","`"]
code: def forward(self, x: torch.Tensor):
      """
      * `x` is the input of shape `[batch_size, in_channels, height, width]`
      """
      # Get the shortcut connection
      shortcut = self.shortcut(x)
      # First convolution and activation
      x = self.act1(self.bn1(self.conv1(x)))
      # Second convolution and activation
      x = self.act2(self.bn2(self.conv2(x)))
      # Third convolution
      x = self.bn3(self.conv3(x))
      # Activation function after adding the shortcut
      return self.act3(x + shortcut)
  
file_path: annotated_deep_learning_paper_implementations/labml_nn/resnet/__init__.py
imports: from typing import List, Optional
  import torch
  from torch import nn
  from labml_helpers.module import Module
label_desc: Use image node_id 2 for calling the BottleneckResidualBlock obj's underlying member method code with example usage: obj.forward(x) and returns: self