class_docstr: ### Residual block
  
  A residual block has two convolution layers with group normalization.
  Each resolution is processed with two residual blocks.
class_docstr_tok: ["#","#","#","Residual","block","A","residual","block","has","two","convolution","layers","with","group","normalization",".","Each","resolution","is","processed","with","two","residual","blocks","."]
docstr: * `in_channels` is the number of input channels
  * `out_channels` is the number of input channels
  * `time_channels` is the number channels in the time step ($t$) embeddings
  * `n_groups` is the number of groups for [group normalization](../../normalization/group_norm/index.html)
  * `dropout` is the dropout rate
code: def __init__(
      self,
      in_channels: int,
      out_channels: int,
      time_channels: int,
      n_groups: int = 32,
      dropout: float = 0.1,
  ):
      """
      * `in_channels` is the number of input channels
      * `out_channels` is the number of input channels
      * `time_channels` is the number channels in the time step ($t$) embeddings
      * `n_groups` is the number of groups for [group normalization](../../normalization/group_norm/index.html)
      * `dropout` is the dropout rate
      """
      super().__init__()
      # Group normalization and the first convolution layer
      self.norm1 = nn.GroupNorm(n_groups, in_channels)
      self.act1 = Swish()
      self.conv1 = nn.Conv2d(
          in_channels, out_channels, kernel_size=(3, 3), padding=(1, 1)
      )
  
      # Group normalization and the second convolution layer
      self.norm2 = nn.GroupNorm(n_groups, out_channels)
      self.act2 = Swish()
      self.conv2 = nn.Conv2d(
          out_channels, out_channels, kernel_size=(3, 3), padding=(1, 1)
      )
  
      # If the number of input channels is not equal to the number of output channels we have to
      # project the shortcut connection
      if in_channels != out_channels:
          self.shortcut = nn.Conv2d(
              in_channels, out_channels, kernel_size=(1, 1)
          )
      else:
          self.shortcut = nn.Identity()
  
      # Linear layer for time embeddings
      self.time_emb = nn.Linear(time_channels, out_channels)
      self.time_act = Swish()
  
      self.dropout = nn.Dropout(dropout)
  
imports: import math
  from typing import Optional, Tuple, Union, List
  import torch
  from torch import nn
  from labml_helpers.module import Module
label_desc: Use image node_id 1 to create a new ResidualBlock object from inherited base classes: Module with example: obj = ResidualBlock(in_channels, out_channels, time_channels, n_groups, dropout)