clinicadl.networks.nn.ResNet

class clinicadl.networks.nn.ResNet(spatial_dims: int, in_channels: int, num_outputs: int | None, block_type: str | ResNetBlockType = ResNetBlockType.BASIC, n_res_blocks: Sequence[int] = (2, 2, 2, 2), n_features: Sequence[int] = (64, 128, 256, 512), init_conv_size: Sequence[int] | int = 7, init_conv_stride: Sequence[int] | int = 2, bottleneck_reduction: int = 4, act: ActFunction | tuple[ActFunction, dict[str, Any]] = ('relu', {'inplace': True}), output_act: ActFunction | tuple[ActFunction, dict[str, Any]] | None = None) None[source]

ResNet, based on Deep Residual Learning for Image Recognition.

Adapted from MONAI's implementation.

The user can customize the number of residual blocks, the number of downsampling blocks, the number of channels in each block, as well as other parameters like the type of residual block used.

ResNet is a fully convolutional network that can work with an input of any size, provided that it is large enough not to be reduced to a 1-pixel image (before the adaptative average pooling).

Works with 2D or 3D images (with additional batch and channel dimensions).

Parameters:
  • spatial_dims (int) – Number of spatial dimensions of the input image.

  • in_channels (int) – Number of channels in the input image.

  • num_outputs (Optional[int]) – Number of output variables after the last linear layer. If None, the feature map before the last fully connected layer will be returned.

  • block_type (Union[str, ResNetBlockType], default="basic") – Type of residual block. Either basic or bottleneck. Default to basic, as in ResNet-18.

  • n_res_blocks (Sequence[int], default=(2, 2, 2, 2)) – Number of residual block in each ResNet layer. A ResNet layer refers here to a set of residual blocks between two downsamplings. The length of n_res_blocks thus determines the number of ResNet layers. Default to (2, 2, 2, 2), as in ResNet-18.

  • n_features (Sequence[int], default=(64, 128, 256, 512)) –

    Number of output feature maps for each ResNet layer. The length of n_features must be equal to the length of n_res_blocks. All elements of n_features must be divisible by bottleneck_reduction.

    Default to (64, 128, 256, 512), as in ResNet-18.

  • init_conv_size (Union[Sequence[int], int], default=7) – Kernel size for the first convolution. If tuple, it will be understood as the values for each dimension. Default to 7, as in the original paper.

  • init_conv_stride (Union[Sequence[int], int], default=2) – Stride for the first convolution. If tuple, it will be understood as the values for each dimension. Default to 2, as in the original paper.

  • bottleneck_reduction (int, default=4) – If block_type="bottleneck", bottleneck_reduction determines the reduction factor for the number of feature maps in bottleneck layers (1x1 convolutions). Default to 4, as in the original paper.

  • act (ActivationParameters, default=("relu", {"inplace": True})) –

    The activation function used after a convolutional layer, and optionally its arguments. Must be passed as activation_name or (activation_name, arguments), where arguments is a dictionary.

    activation_name can be any value in {"celu", "elu", "gelu", "leakyrelu", "logsoftmax", "mish", "prelu", "relu", "relu6", "selu", "sigmoid", "softmax", "tanh"}. Please refer to PyTorch activation functions to know the arguments for each of them.

    Default is relu, as in the original paper.

  • output_act (Optional[ActivationParameters], default=None) – A potential activation layer applied to the output of the network. Must be passed in the same way as act. If None, no last activation will be applied.

Raises:
  • ValueError – If len(n_features)!=len(n_res_blocks).

  • ValueError – If some elements of n_features are not divisible by bottleneck_reduction.

See also

torch.nn.Module

To see all the methods of this neural network.

SEResNet

Examples

>>> ResNet(
        spatial_dims=2,
        in_channels=1,
        num_outputs=2,
        block_type="bottleneck",
        bottleneck_reduction=4,
        n_features=(8, 16),
        n_res_blocks=(2, 2),
        output_act="softmax",
        init_conv_size=5,
    )
ResNet(
    (conv0): Conv2d(1, 2, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2), bias=False)
    (norm0): BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (act0): ReLU(inplace=True)
    (pool0): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
    (layer1): Sequential(
        (0): ResNetBottleneck(
            (conv1): Conv2d(2, 2, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm1): BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act1): ReLU(inplace=True)
            (conv2): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
            (norm2): BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act2): ReLU(inplace=True)
            (conv3): Conv2d(2, 8, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm3): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (downsample): Sequential(
                (0): Conv2d(2, 8, kernel_size=(1, 1), stride=(1, 1), bias=False)
                (1): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            )
            (act3): ReLU(inplace=True)
        )
        (1): ResNetBottleneck(
            (conv1): Conv2d(8, 2, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm1): BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act1): ReLU(inplace=True)
            (conv2): Conv2d(2, 2, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
            (norm2): BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act2): ReLU(inplace=True)
            (conv3): Conv2d(2, 8, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm3): BatchNorm2d(8, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act3): ReLU(inplace=True)
        )
    )
    (layer2): Sequential(
        (0): ResNetBottleneck(
            (conv1): Conv2d(8, 4, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm1): BatchNorm2d(4, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act1): ReLU(inplace=True)
            (conv2): Conv2d(4, 4, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
            (norm2): BatchNorm2d(4, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act2): ReLU(inplace=True)
            (conv3): Conv2d(4, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm3): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (downsample): Sequential(
                (0): Conv2d(8, 16, kernel_size=(1, 1), stride=(2, 2), bias=False)
                (1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            )
            (act3): ReLU(inplace=True)
        )
        (1): ResNetBottleneck(
            (conv1): Conv2d(16, 4, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm1): BatchNorm2d(4, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act1): ReLU(inplace=True)
            (conv2): Conv2d(4, 4, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
            (norm2): BatchNorm2d(4, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act2): ReLU(inplace=True)
            (conv3): Conv2d(4, 16, kernel_size=(1, 1), stride=(1, 1), bias=False)
            (norm3): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
            (act3): ReLU(inplace=True)
        )
    )
    (fc): Sequential(
        (pool): AdaptiveAvgPool2d(output_size=(1, 1))
        (flatten): Flatten(start_dim=1, end_dim=-1)
        (out): Linear(in_features=16, out_features=2, bias=True)
        (output_act): Softmax(dim=None)
    )
)