torchcnnbuilder.builder

  1import math
  2from collections import OrderedDict
  3from typing import List, Optional, Sequence, Tuple, Union
  4
  5import torch.nn as nn
  6
  7from torchcnnbuilder._constants import (
  8    DEFAULT_CONV_PARAMS,
  9    DEFAULT_TRANSPOSE_CONV_PARAMS,
 10)
 11from torchcnnbuilder._formulas import _select_conv_calc
 12from torchcnnbuilder._utils import (
 13    _double_params,
 14    _select_adaptive_pooling_dimension,
 15    _select_conv_dimension,
 16    _select_norm_dimension,
 17    _set_conv_params,
 18    _triple_params,
 19)
 20from torchcnnbuilder._validation import (
 21    _validate_available_layers,
 22    _validate_build_transpose_convolve_init,
 23    _validate_channel_growth_rate_param,
 24    _validate_difference_in_dimensions,
 25    _validate_input_size_is_not_none,
 26    _validate_max_channels_number,
 27    _validate_min_channels_number,
 28    _validate_range_step,
 29)
 30from torchcnnbuilder.latent import LatentSpaceModule
 31
 32
 33# ------------------------------------
 34# CNN Builder class
 35# ------------------------------------
 36class Builder:
 37    """
 38    A class for creating СNN architectures
 39    """
 40
 41    def __init__(
 42        self,
 43        input_size: Optional[Sequence[int]] = None,
 44        minimum_feature_map_size: Union[Sequence[int], int] = 5,
 45        max_channels: int = 512,
 46        min_channels: int = 1,
 47        activation_function: nn.Module = nn.ReLU(inplace=True),
 48        finish_activation_function: Union[Optional[nn.Module], str] = None,
 49    ) -> None:
 50        """
 51        Initializes the Builder instance.
 52
 53        Args:
 54            input_size (Optional[Sequence[int]], optional):
 55                Input size of the input tensor. Necessary for creating
 56                convolution sequences. Defaults to None.
 57            minimum_feature_map_size (Union[Sequence[int], int], optional):
 58                Minimum feature map size. Defaults to 5.
 59            max_channels (int, optional):
 60                Maximum number of layers after any convolution. Defaults to 512.
 61            min_channels (int, optional):
 62                Minimum number of layers after any convolution. Defaults to 1.
 63            activation_function (nn.Module, optional):
 64                Activation function. Defaults to nn.ReLU(inplace=True).
 65            finish_activation_function (Union[Optional[nn.Module], str], optional):
 66                Last activation function, can be the same as activation_function
 67                (use string 'same' for that). Defaults to None.
 68
 69        Raises:
 70            ValueError: If input_size is not a valid shape.
 71        """
 72
 73        if input_size is None:
 74            self.input_size = input_size
 75        else:
 76            self.input_size = tuple(i for i in input_size)
 77
 78            if len(self.input_size) == 1:
 79                self.minimum_feature_map_size = (
 80                    (minimum_feature_map_size,)
 81                    if isinstance(minimum_feature_map_size, int)
 82                    else minimum_feature_map_size
 83                )
 84            if len(self.input_size) == 2:
 85                self.minimum_feature_map_size = (
 86                    _double_params(
 87                        minimum_feature_map_size,
 88                    )
 89                    if isinstance(minimum_feature_map_size, int)
 90                    else minimum_feature_map_size
 91                )
 92            if len(self.input_size) == 3:
 93                self.minimum_feature_map_size = (
 94                    _triple_params(
 95                        minimum_feature_map_size,
 96                    )
 97                    if isinstance(minimum_feature_map_size, int)
 98                    else minimum_feature_map_size
 99                )
100
101        self.max_channels = max_channels
102        self._initial_max_channels = max_channels
103
104        self.min_channels = min_channels
105        self._initial_min_channels = min_channels
106
107        self._default_convolve_params = DEFAULT_CONV_PARAMS
108        self._default_transpose_params = DEFAULT_TRANSPOSE_CONV_PARAMS
109
110        # finish_activation_function can be str 'same' which equals to activation_function
111        self.activation_function = activation_function
112        self.finish_activation_function = finish_activation_function
113
114        self._conv_channels = None
115        self._transpose_conv_channels = None
116
117        self._conv_layers = None
118        self._transpose_conv_layers = None
119
120    @property
121    def conv_channels(self) -> Optional[List[int]]:
122        """Gets the convolutional channels.
123
124        Returns:
125            A list of convolutional channel sizes or None
126            if not initialized.
127        """
128        return self._conv_channels
129
130    @property
131    def transpose_conv_channels(self) -> Optional[List[int]]:
132        """Gets the transposed convolutional channels.
133
134        Returns:
135            A list of transposed convolutional channel sizes
136            or None if not initialized.
137        """
138        return self._transpose_conv_channels
139
140    @property
141    def conv_layers(self) -> Optional[List[Tuple[int, ...]]]:
142        """Gets the convolutional layers.
143
144        Returns:
145            A list of tuples representing convolutional layer configurations or None if not initialized.
146        """
147        return self._conv_layers
148
149    @property
150    def transpose_conv_layers(self) -> Optional[List[Tuple[int, ...]]]:
151        """Gets the transposed convolutional layers.
152
153        Returns:
154            A list of tuples representing transposed convolutional layer configurations or None if not
155            initialized.
156        """
157        return self._transpose_conv_layers
158
159    def build_convolve_block(
160        self,
161        in_channels: int,
162        out_channels: int,
163        params: Optional[dict] = None,
164        normalization: Optional[str] = None,
165        sub_blocks: int = 1,
166        p: float = 0.5,
167        inplace: bool = False,
168        eps: float = 1e-5,
169        momentum: Optional[float] = 0.1,
170        affine: bool = True,
171        conv_dim: int = 2,
172    ) -> nn.Sequential:
173        """Builds a single block of convolution layers.
174
175        This method creates a sequential block that consists of convolutional layers,
176        optional normalization layers, and an activation function.
177
178        Args:
179            in_channels (int): Number of channels in the input image.
180            out_channels (int): Number of channels produced by the convolution.
181            params (Optional[dict], optional): Convolutional layer parameters
182                (for nn.ConvNd). Defaults to None.
183            normalization (Optional[str], optional): Type of normalization to apply.
184                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
185            sub_blocks (int, optional): Number of convolutional layers within the block.
186                Defaults to 1.
187            p (float, optional): Probability of an element being zeroed for dropout/instancenorm.
188                Defaults to 0.5.
189            inplace (bool, optional): If True, performs the operation in-place
190                for dropout/instancenorm. Defaults to False.
191            eps (float, optional): A value added to the denominator for numerical stability
192                (used in batchnorm/instancenorm). Defaults to 1e-5.
193            momentum (Optional[float], optional): Momentum for running_mean or running_var
194                computation (used in batchnorm). If None, a cumulative moving average is used.
195                Defaults to 0.1.
196            affine (bool, optional): If True, the module has learnable affine parameters
197                (used in batchnorm). Defaults to True.
198            conv_dim (int, optional): The dimension of the convolutional operation (2 for
199                2D convolution, 3 for 3D convolution). Defaults to 2.
200
201        Returns:
202            A sequential block containing convolutional layers,
203            optional normalization layers, and an activation function.
204        """
205        params = _set_conv_params(default_params=self._default_convolve_params, params=params)
206        convolution = _select_conv_dimension(conv_dim=conv_dim)
207
208        if sub_blocks > 1:
209            kernel_size = params["kernel_size"]
210            kernel_size = kernel_size if isinstance(kernel_size, int) else kernel_size[0]
211            params["padding"] = kernel_size // 2
212            params["stride"] = 1
213
214        blocks = []
215        for i in range(sub_blocks):
216            block = []
217
218            conv = convolution(in_channels=in_channels, out_channels=out_channels, **params)
219            in_channels = out_channels
220            block.append(conv)
221
222            if normalization:
223                norm = _select_norm_dimension(conv_dim=conv_dim, normalization=normalization)
224
225                if normalization in ("batchnorm", "instancenorm"):
226                    norm = norm(
227                        num_features=out_channels,
228                        eps=eps,
229                        momentum=momentum,
230                        affine=affine,
231                    )
232
233                if normalization == "dropout":
234                    norm = norm(p=p, inplace=inplace)
235
236                block.append(norm)
237
238            activation_function = self.activation_function
239            block.append(activation_function)
240
241            if sub_blocks > 1:
242                block = nn.Sequential(*block)
243                blocks.append((f"sub-block {i + 1}", block))
244            else:
245                blocks.extend(block)
246
247        if sub_blocks > 1:
248            return nn.Sequential(OrderedDict(blocks))
249
250        return nn.Sequential(*blocks)
251
252    def build_convolve_sequence(
253        self,
254        n_layers: int,
255        in_channels: int = 1,
256        params: Optional[dict] = None,
257        normalization: Optional[str] = None,
258        sub_blocks: int = 1,
259        p: float = 0.5,
260        inplace: bool = False,
261        eps: float = 1e-5,
262        momentum: Optional[float] = 0.1,
263        affine: bool = True,
264        ratio: float = 2.0,
265        start: int = 32,
266        channel_growth_rate: str = "exponential",
267        conv_dim: int = 2,
268    ) -> nn.Sequential:
269        """Builds a sequence of convolution blocks.
270
271        This method constructs a sequential block of convolutional layers,
272        with optional normalization and multiple sub-blocks per layer.
273
274        Args:
275            n_layers (int): Number of convolution layers in the encoder part.
276            in_channels (int, optional): Number of channels in the first input tensor.
277                Defaults to 1.
278            params (Optional[dict], optional): Convolutional layer parameters
279                (for nn.ConvNd). Defaults to None.
280            normalization (Optional[str], optional): Type of normalization to apply.
281                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
282            sub_blocks (int, optional): Number of convolutions within each layer.
283                Defaults to 1.
284            p (float, optional): Probability of an element being zeroed for dropout.
285                Defaults to 0.5.
286            inplace (bool, optional): If True, performs the operation in-place
287                for dropout. Defaults to False.
288            eps (float, optional): A value added to the denominator for numerical stability
289                (used in batchnorm/instancenorm). Defaults to 1e-5.
290            momentum (Optional[float], optional): Momentum for running_mean or running_var
291                computation (used in batchnorm). If None, a cumulative moving average is used.
292                Defaults to 0.1.
293            affine (bool, optional): If True, the module has learnable affine parameters
294                (used in batchnorm). Defaults to True.
295            ratio (float, optional): Multiplier for the geometric progression of increasing
296                channels (feature maps). Used for 'channel_growth_rate' as 'exponential'
297                or 'power'. Defaults to 2.0.
298            start (int, optional): Starting position of the geometric progression
299                when 'channel_growth_rate' is set to 'exponential'. Defaults to 32.
300            channel_growth_rate (str, optional): Method for calculating the number of
301                feature maps. Options include 'exponential', 'proportion', 'linear',
302                'power', and 'constant'. Defaults to 'exponential'.
303            conv_dim (int, optional): The dimension of the convolutional operation.
304                Defaults to 2.
305
306        Returns:
307            A sequential block containing the specified number of
308            convolutional layers.
309        """
310        _validate_input_size_is_not_none(self.input_size)
311        params = _set_conv_params(default_params=self._default_convolve_params, params=params)
312        conv_out = _select_conv_calc(conv_dim=conv_dim)
313
314        modules = []
315        input_layer_size_list = [self.input_size]
316        input_channels_count_list = self._calc_out_channels(
317            in_size=self.input_size,
318            in_channels=in_channels,
319            n_layers=n_layers,
320            ratio=ratio,
321            start=start,
322            channel_growth_rate=channel_growth_rate,
323        )
324
325        for layer in range(n_layers):
326            input_layer_size = input_layer_size_list[-1]
327
328            _validate_difference_in_dimensions(self.input_size, conv_dim)
329            _validate_available_layers(layer, input_layer_size, self.minimum_feature_map_size)
330            _validate_max_channels_number(layer, input_channels_count_list, self.max_channels)
331            _validate_min_channels_number(layer, input_channels_count_list, self.min_channels)
332
333            in_channels = input_channels_count_list[layer]
334            out_channels = input_channels_count_list[layer + 1]
335
336            out_layer_size = conv_out(input_size=input_layer_size, **params)
337            input_layer_size_list.append(out_layer_size)
338
339            convolve_block = self.build_convolve_block(
340                in_channels=in_channels,
341                out_channels=out_channels,
342                normalization=normalization,
343                sub_blocks=sub_blocks,
344                p=p,
345                inplace=inplace,
346                eps=eps,
347                momentum=momentum,
348                affine=affine,
349                params=params,
350                conv_dim=conv_dim,
351            )
352
353            modules.append((f"conv {layer + 1}", convolve_block))
354
355        self._conv_channels = input_channels_count_list
356        self._conv_layers = input_layer_size_list
357        return nn.Sequential(OrderedDict(modules))
358
359    def build_transpose_convolve_block(
360        self,
361        in_channels: int,
362        out_channels: int,
363        params: Optional[dict] = None,
364        normalization: Optional[str] = None,
365        sub_blocks: int = 1,
366        p: float = 0.5,
367        inplace: bool = False,
368        eps: float = 1e-5,
369        momentum: Optional[float] = 0.1,
370        affine: bool = True,
371        last_block: bool = False,
372        conv_dim: int = 2,
373    ) -> nn.Sequential:
374        """Builds a single block of transposed convolution layers.
375
376        This method constructs a sequential block of transposed convolutional layers,
377        with optional normalization and multiple sub-blocks per layer.
378
379        Args:
380            in_channels (int): Number of channels in the input image.
381            out_channels (int): Number of channels produced by the transposed convolution.
382            params (Optional[dict], optional): Parameters for the transposed convolutional layer
383                (for nn.ConvTranspose2d). Defaults to None.
384            normalization (Optional[str], optional): Type of normalization to apply.
385                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
386            sub_blocks (int, optional): Number of convolutions within each layer.
387                Defaults to 1.
388            p (float, optional): Probability of an element being zeroed for dropout.
389                Defaults to 0.5.
390            inplace (bool, optional): If True, performs the operation in-place
391                for dropout. Defaults to False.
392            eps (float, optional): A value added to the denominator for numerical stability
393                (used in batchnorm/instancenorm). Defaults to 1e-5.
394            momentum (Optional[float], optional): Momentum for running_mean or running_var
395                computation (used in batchnorm). If None, a cumulative moving average is used.
396                Defaults to 0.1.
397            affine (bool, optional): If True, the module has learnable affine parameters
398                (used in batchnorm). Defaults to True.
399            last_block (bool, optional): If True, no activation function is applied after
400                the transposed convolution. Defaults to False.
401            conv_dim (int, optional): The dimension of the convolutional operation.
402                Defaults to 2.
403
404        Returns:
405            A sequential block containing the specified transposed
406            convolutional layers, possibly including normalization and activation functions.
407        """
408        params = _set_conv_params(default_params=self._default_transpose_params, params=params)
409        convolution = _select_conv_dimension(conv_dim=conv_dim, transpose=True)
410
411        if sub_blocks > 1:
412            kernel_size = params["kernel_size"]
413            kernel_size = kernel_size if isinstance(kernel_size, int) else kernel_size[0]
414            params["padding"] = kernel_size // 2
415            params["stride"] = 1
416
417        blocks = []
418        last_out_channels = out_channels
419        for i in range(sub_blocks):
420            block = []
421
422            out_channels = last_out_channels if i == sub_blocks - 1 else in_channels
423            conv = convolution(in_channels=in_channels, out_channels=out_channels, **params)
424            block.append(conv)
425
426            if normalization:
427                norm = _select_norm_dimension(conv_dim=conv_dim, normalization=normalization)
428
429                if normalization in ("batchnorm", "instancenorm"):
430                    norm = norm(
431                        num_features=out_channels,
432                        eps=eps,
433                        momentum=momentum,
434                        affine=affine,
435                    )
436
437                if normalization == "dropout":
438                    norm = norm(p=p, inplace=inplace)
439
440                block.append(norm)
441
442            activation_function = self.activation_function
443            if last_block and i == sub_blocks - 1:
444                if self.finish_activation_function == "same":
445                    block.append(activation_function)
446                elif self.finish_activation_function:
447                    block.append(self.finish_activation_function)
448            else:
449                block.append(activation_function)
450
451            if sub_blocks > 1:
452                block = nn.Sequential(*block)
453                blocks.append((f"transpose sub-block {i + 1}", block))
454            else:
455                blocks.extend(block)
456
457        if sub_blocks > 1:
458            return nn.Sequential(OrderedDict(blocks))
459
460        return nn.Sequential(*blocks)
461
462    def build_transpose_convolve_sequence(
463        self,
464        n_layers: int,
465        in_channels: Optional[int] = None,
466        out_channels: int = 1,
467        out_size: Optional[tuple] = None,
468        params: Optional[dict] = None,
469        normalization: Optional[str] = None,
470        sub_blocks: int = 1,
471        p: float = 0.5,
472        inplace: bool = False,
473        eps: float = 1e-5,
474        momentum: Optional[float] = 0.1,
475        affine: bool = True,
476        ratio: float = 2.0,
477        channel_growth_rate: str = "exponential",
478        conv_dim: int = 2,
479        adaptive_pool: str = "avgpool",
480    ) -> nn.Sequential:
481        """Builds a sequence of transposed convolution blocks.
482
483        This method constructs a sequential layer of transposed convolution blocks,
484        allowing for customization through normalization, sub-blocks, and other parameters.
485
486        Args:
487            n_layers (int): Number of transposed convolution layers to create.
488            in_channels (Optional[int], optional): Number of channels in the first input tensor.
489                Defaults to None, which will use the last value from _conv_channels if available.
490            out_channels (int, optional): Number of channels after the transposed convolution sequence.
491                Defaults to 1.
492            out_size (Optional[tuple], optional): Desired output size after the transposed convolution sequence.
493                Defaults to None, which uses the input size.
494            params (Optional[dict], optional): Parameters for the transposed convolutional layer
495                (for nn.ConvTranspose2d). Defaults to None.
496            normalization (Optional[str], optional): Type of normalization to apply.
497                Options include 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
498            sub_blocks (int, optional): Number of transposed convolutions within each layer.
499                Defaults to 1.
500            p (float, optional): Probability of an element being zeroed for dropout.
501                Defaults to 0.5.
502            inplace (bool, optional): If True, performs the operation in-place
503                for dropout. Defaults to False.
504            eps (float, optional): A value added to the denominator for numerical stability
505                (used in batchnorm/instancenorm). Defaults to 1e-5.
506            momentum (Optional[float], optional): Momentum for running_mean or running_var
507                computation (used in batchnorm). If None, a cumulative moving average is used.
508                Defaults to 0.1.
509            affine (bool, optional): If True, the module has learnable affine parameters
510                (used in batchnorm). Defaults to True.
511            ratio (float, optional): Multiplier for the geometric progression of increasing channels
512                (feature maps). Used for 'channel_growth_rate' as 'exponential' or 'power'.
513                Defaults to 2 (powers of two).
514            channel_growth_rate (str, optional): Method of calculating the number of feature maps.
515                Options include 'exponential', 'proportion', 'linear', 'power', and 'constant'.
516                Defaults to 'exponential'.
517            conv_dim (int, optional): The dimension of the convolutional operation.
518                Defaults to 2.
519            adaptive_pool (str, optional): Type of adaptive pooling layer to apply last,
520                can be 'avgpool' or 'maxpool'. Defaults to 'avgpool'.
521
522        Returns:
523            A sequential block containing the specified transposed convolutional
524            layers, possibly including normalization and adaptive pooling.
525        """
526        _validate_input_size_is_not_none(self.input_size)
527        params = _set_conv_params(default_params=self._default_transpose_params, params=params)
528        conv_out = _select_conv_calc(conv_dim=conv_dim, transpose=True)
529
530        modules = []
531
532        if in_channels is None and self._conv_channels:
533            in_channels = self._conv_channels[-1]
534
535        _validate_build_transpose_convolve_init(in_channels, self._conv_channels)
536
537        if self._conv_layers:
538            input_layer_size_list = [self._conv_layers[-1]]
539
540        input_channels_count_list = self._calc_out_transpose_channels(
541            in_channels=in_channels,
542            out_channels=out_channels,
543            n_layers=n_layers,
544            ratio=ratio,
545            channel_growth_rate=channel_growth_rate,
546        )
547        for layer in range(n_layers):
548            _validate_max_channels_number(layer, input_channels_count_list, self.max_channels)
549            _validate_min_channels_number(layer, input_channels_count_list, min_channels=1)
550
551            in_channels = input_channels_count_list[layer]
552            out_channels = input_channels_count_list[layer + 1]
553
554            if self._conv_layers:
555                input_layer_size = input_layer_size_list[-1]
556                out_layer_size = conv_out(input_size=input_layer_size, **params)
557                input_layer_size_list.append(out_layer_size)
558
559            last_block_condition = layer == n_layers - 1
560            convolve_block = self.build_transpose_convolve_block(
561                in_channels=in_channels,
562                out_channels=out_channels,
563                normalization=normalization,
564                sub_blocks=sub_blocks,
565                p=p,
566                inplace=inplace,
567                eps=eps,
568                momentum=momentum,
569                affine=affine,
570                params=params,
571                last_block=last_block_condition,
572                conv_dim=conv_dim,
573            )
574
575            modules.append((f"deconv {layer + 1}", convolve_block))
576
577        self._transpose_conv_channels = input_channels_count_list
578
579        if self._conv_layers:
580            self._transpose_conv_layers = input_layer_size_list
581
582        if out_size is None:
583            out_size = self.input_size
584
585        adaptive_pooling = _select_adaptive_pooling_dimension(conv_dim=conv_dim, pooling=adaptive_pool)
586        resize_block = adaptive_pooling(output_size=tuple(out_size))
587        modules.append(("resize", resize_block))
588
589        return nn.Sequential(OrderedDict(modules))
590
591    def latent_block(
592        self,
593        input_shape: Sequence[int],
594        output_shape: Sequence[int],
595        n_layers: int = 1,
596        activation_function: Union[Optional[nn.Module], str] = None,
597    ):
598        """Creates a latent space transformation block.
599
600        This method constructs a latent space module that transforms an input tensor
601        of a specified shape into an output tensor of a desired shape using
602        linear layers and an optional activation function.
603
604        Args:
605            input_shape (Sequence[int]): The shape of the input tensor, typically
606                represented as a sequence of integers.
607            output_shape (Sequence[int]): The desired shape of the output tensor,
608                specified as a sequence of integers.
609            n_layers (int, optional): The number of linear layers to use in the
610                transformation. Defaults to 1.
611            activation_function (Union[Optional[nn.Module], str], optional):
612                Specifies the activation function to apply after the linear layers.
613                If set to 'same', it will use the instance's predefined activation
614                function. Defaults to None.
615
616        Returns:
617            An instance of the LatentSpaceModule class that
618            performs the specified transformation from input to output shape.
619        """
620        if activation_function == "same":
621            activation_function = self.activation_function
622
623        return LatentSpaceModule(input_shape, output_shape, n_layers, activation_function)
624
625    def _calc_out_channels(
626        self,
627        in_size: Sequence[int],
628        in_channels: int,
629        n_layers: int,
630        ratio: float = 2.0,
631        start: int = 32,
632        constant: int = 1,
633        channel_growth_rate: str = "exponential",
634    ) -> List[int]:
635        _validate_channel_growth_rate_param(channel_growth_rate)
636
637        if channel_growth_rate == "exponential":
638            self.max_channels = self._initial_max_channels
639            return [in_channels] + [int(start * ratio**i) for i in range(n_layers)]
640
641        if channel_growth_rate == "proportion":
642            range_start = in_channels
643            range_stop = int((sum(in_size) * 0.5) // len(in_size) + in_channels)
644            range_step = (range_stop - in_channels) // n_layers
645
646            _validate_range_step(range_step, n_layers)
647
648            channels = list(range(range_start, range_stop + 1, range_step))[: n_layers + 1]
649            self.max_channels = range_stop
650            return channels
651
652        if channel_growth_rate == "linear":
653            self.max_channels = self.min_channels + n_layers
654            return [in_channels] + [in_channels + i + 1 for i in range(n_layers)]
655
656        if channel_growth_rate == "constant":
657            self.max_channels = constant + 1
658            return [in_channels] + [constant for _ in range(n_layers)]
659
660        if channel_growth_rate == "power":
661            self.max_channels = self._initial_max_channels
662            return [in_channels] + [int((in_channels + i) ** ratio) for i in range(1, n_layers + 1)]
663
664    @staticmethod
665    def _calc_out_transpose_channels(
666        in_channels: int,
667        out_channels: int,
668        n_layers: int,
669        ratio: float = 2.0,
670        constant: int = 1,
671        channel_growth_rate: str = "exponential",
672    ) -> List[int]:
673        _validate_channel_growth_rate_param(channel_growth_rate)
674
675        if channel_growth_rate == "exponential":
676            return [int(in_channels / ratio**i) for i in range(n_layers)] + [out_channels]
677
678        if channel_growth_rate == "proportion":
679            channels = list(range(out_channels, in_channels, (in_channels - out_channels) // n_layers))[::-1]
680            channels = channels[:n_layers]
681            channels[-1] = out_channels
682            return [in_channels] + channels
683
684        if channel_growth_rate == "linear":
685            return [in_channels] + [in_channels - i for i in range(1, n_layers)] + [out_channels]
686
687        if channel_growth_rate == "constant":
688            return [in_channels] + [constant for _ in range(n_layers - 1)] + [out_channels]
689
690        if channel_growth_rate == "power":
691            return (
692                [in_channels] + [int(math.pow((n_layers - i + 1), ratio)) for i in range(1, n_layers)] + [out_channels]
693            )
class Builder:
 37class Builder:
 38    """
 39    A class for creating СNN architectures
 40    """
 41
 42    def __init__(
 43        self,
 44        input_size: Optional[Sequence[int]] = None,
 45        minimum_feature_map_size: Union[Sequence[int], int] = 5,
 46        max_channels: int = 512,
 47        min_channels: int = 1,
 48        activation_function: nn.Module = nn.ReLU(inplace=True),
 49        finish_activation_function: Union[Optional[nn.Module], str] = None,
 50    ) -> None:
 51        """
 52        Initializes the Builder instance.
 53
 54        Args:
 55            input_size (Optional[Sequence[int]], optional):
 56                Input size of the input tensor. Necessary for creating
 57                convolution sequences. Defaults to None.
 58            minimum_feature_map_size (Union[Sequence[int], int], optional):
 59                Minimum feature map size. Defaults to 5.
 60            max_channels (int, optional):
 61                Maximum number of layers after any convolution. Defaults to 512.
 62            min_channels (int, optional):
 63                Minimum number of layers after any convolution. Defaults to 1.
 64            activation_function (nn.Module, optional):
 65                Activation function. Defaults to nn.ReLU(inplace=True).
 66            finish_activation_function (Union[Optional[nn.Module], str], optional):
 67                Last activation function, can be the same as activation_function
 68                (use string 'same' for that). Defaults to None.
 69
 70        Raises:
 71            ValueError: If input_size is not a valid shape.
 72        """
 73
 74        if input_size is None:
 75            self.input_size = input_size
 76        else:
 77            self.input_size = tuple(i for i in input_size)
 78
 79            if len(self.input_size) == 1:
 80                self.minimum_feature_map_size = (
 81                    (minimum_feature_map_size,)
 82                    if isinstance(minimum_feature_map_size, int)
 83                    else minimum_feature_map_size
 84                )
 85            if len(self.input_size) == 2:
 86                self.minimum_feature_map_size = (
 87                    _double_params(
 88                        minimum_feature_map_size,
 89                    )
 90                    if isinstance(minimum_feature_map_size, int)
 91                    else minimum_feature_map_size
 92                )
 93            if len(self.input_size) == 3:
 94                self.minimum_feature_map_size = (
 95                    _triple_params(
 96                        minimum_feature_map_size,
 97                    )
 98                    if isinstance(minimum_feature_map_size, int)
 99                    else minimum_feature_map_size
100                )
101
102        self.max_channels = max_channels
103        self._initial_max_channels = max_channels
104
105        self.min_channels = min_channels
106        self._initial_min_channels = min_channels
107
108        self._default_convolve_params = DEFAULT_CONV_PARAMS
109        self._default_transpose_params = DEFAULT_TRANSPOSE_CONV_PARAMS
110
111        # finish_activation_function can be str 'same' which equals to activation_function
112        self.activation_function = activation_function
113        self.finish_activation_function = finish_activation_function
114
115        self._conv_channels = None
116        self._transpose_conv_channels = None
117
118        self._conv_layers = None
119        self._transpose_conv_layers = None
120
121    @property
122    def conv_channels(self) -> Optional[List[int]]:
123        """Gets the convolutional channels.
124
125        Returns:
126            A list of convolutional channel sizes or None
127            if not initialized.
128        """
129        return self._conv_channels
130
131    @property
132    def transpose_conv_channels(self) -> Optional[List[int]]:
133        """Gets the transposed convolutional channels.
134
135        Returns:
136            A list of transposed convolutional channel sizes
137            or None if not initialized.
138        """
139        return self._transpose_conv_channels
140
141    @property
142    def conv_layers(self) -> Optional[List[Tuple[int, ...]]]:
143        """Gets the convolutional layers.
144
145        Returns:
146            A list of tuples representing convolutional layer configurations or None if not initialized.
147        """
148        return self._conv_layers
149
150    @property
151    def transpose_conv_layers(self) -> Optional[List[Tuple[int, ...]]]:
152        """Gets the transposed convolutional layers.
153
154        Returns:
155            A list of tuples representing transposed convolutional layer configurations or None if not
156            initialized.
157        """
158        return self._transpose_conv_layers
159
160    def build_convolve_block(
161        self,
162        in_channels: int,
163        out_channels: int,
164        params: Optional[dict] = None,
165        normalization: Optional[str] = None,
166        sub_blocks: int = 1,
167        p: float = 0.5,
168        inplace: bool = False,
169        eps: float = 1e-5,
170        momentum: Optional[float] = 0.1,
171        affine: bool = True,
172        conv_dim: int = 2,
173    ) -> nn.Sequential:
174        """Builds a single block of convolution layers.
175
176        This method creates a sequential block that consists of convolutional layers,
177        optional normalization layers, and an activation function.
178
179        Args:
180            in_channels (int): Number of channels in the input image.
181            out_channels (int): Number of channels produced by the convolution.
182            params (Optional[dict], optional): Convolutional layer parameters
183                (for nn.ConvNd). Defaults to None.
184            normalization (Optional[str], optional): Type of normalization to apply.
185                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
186            sub_blocks (int, optional): Number of convolutional layers within the block.
187                Defaults to 1.
188            p (float, optional): Probability of an element being zeroed for dropout/instancenorm.
189                Defaults to 0.5.
190            inplace (bool, optional): If True, performs the operation in-place
191                for dropout/instancenorm. Defaults to False.
192            eps (float, optional): A value added to the denominator for numerical stability
193                (used in batchnorm/instancenorm). Defaults to 1e-5.
194            momentum (Optional[float], optional): Momentum for running_mean or running_var
195                computation (used in batchnorm). If None, a cumulative moving average is used.
196                Defaults to 0.1.
197            affine (bool, optional): If True, the module has learnable affine parameters
198                (used in batchnorm). Defaults to True.
199            conv_dim (int, optional): The dimension of the convolutional operation (2 for
200                2D convolution, 3 for 3D convolution). Defaults to 2.
201
202        Returns:
203            A sequential block containing convolutional layers,
204            optional normalization layers, and an activation function.
205        """
206        params = _set_conv_params(default_params=self._default_convolve_params, params=params)
207        convolution = _select_conv_dimension(conv_dim=conv_dim)
208
209        if sub_blocks > 1:
210            kernel_size = params["kernel_size"]
211            kernel_size = kernel_size if isinstance(kernel_size, int) else kernel_size[0]
212            params["padding"] = kernel_size // 2
213            params["stride"] = 1
214
215        blocks = []
216        for i in range(sub_blocks):
217            block = []
218
219            conv = convolution(in_channels=in_channels, out_channels=out_channels, **params)
220            in_channels = out_channels
221            block.append(conv)
222
223            if normalization:
224                norm = _select_norm_dimension(conv_dim=conv_dim, normalization=normalization)
225
226                if normalization in ("batchnorm", "instancenorm"):
227                    norm = norm(
228                        num_features=out_channels,
229                        eps=eps,
230                        momentum=momentum,
231                        affine=affine,
232                    )
233
234                if normalization == "dropout":
235                    norm = norm(p=p, inplace=inplace)
236
237                block.append(norm)
238
239            activation_function = self.activation_function
240            block.append(activation_function)
241
242            if sub_blocks > 1:
243                block = nn.Sequential(*block)
244                blocks.append((f"sub-block {i + 1}", block))
245            else:
246                blocks.extend(block)
247
248        if sub_blocks > 1:
249            return nn.Sequential(OrderedDict(blocks))
250
251        return nn.Sequential(*blocks)
252
253    def build_convolve_sequence(
254        self,
255        n_layers: int,
256        in_channels: int = 1,
257        params: Optional[dict] = None,
258        normalization: Optional[str] = None,
259        sub_blocks: int = 1,
260        p: float = 0.5,
261        inplace: bool = False,
262        eps: float = 1e-5,
263        momentum: Optional[float] = 0.1,
264        affine: bool = True,
265        ratio: float = 2.0,
266        start: int = 32,
267        channel_growth_rate: str = "exponential",
268        conv_dim: int = 2,
269    ) -> nn.Sequential:
270        """Builds a sequence of convolution blocks.
271
272        This method constructs a sequential block of convolutional layers,
273        with optional normalization and multiple sub-blocks per layer.
274
275        Args:
276            n_layers (int): Number of convolution layers in the encoder part.
277            in_channels (int, optional): Number of channels in the first input tensor.
278                Defaults to 1.
279            params (Optional[dict], optional): Convolutional layer parameters
280                (for nn.ConvNd). Defaults to None.
281            normalization (Optional[str], optional): Type of normalization to apply.
282                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
283            sub_blocks (int, optional): Number of convolutions within each layer.
284                Defaults to 1.
285            p (float, optional): Probability of an element being zeroed for dropout.
286                Defaults to 0.5.
287            inplace (bool, optional): If True, performs the operation in-place
288                for dropout. Defaults to False.
289            eps (float, optional): A value added to the denominator for numerical stability
290                (used in batchnorm/instancenorm). Defaults to 1e-5.
291            momentum (Optional[float], optional): Momentum for running_mean or running_var
292                computation (used in batchnorm). If None, a cumulative moving average is used.
293                Defaults to 0.1.
294            affine (bool, optional): If True, the module has learnable affine parameters
295                (used in batchnorm). Defaults to True.
296            ratio (float, optional): Multiplier for the geometric progression of increasing
297                channels (feature maps). Used for 'channel_growth_rate' as 'exponential'
298                or 'power'. Defaults to 2.0.
299            start (int, optional): Starting position of the geometric progression
300                when 'channel_growth_rate' is set to 'exponential'. Defaults to 32.
301            channel_growth_rate (str, optional): Method for calculating the number of
302                feature maps. Options include 'exponential', 'proportion', 'linear',
303                'power', and 'constant'. Defaults to 'exponential'.
304            conv_dim (int, optional): The dimension of the convolutional operation.
305                Defaults to 2.
306
307        Returns:
308            A sequential block containing the specified number of
309            convolutional layers.
310        """
311        _validate_input_size_is_not_none(self.input_size)
312        params = _set_conv_params(default_params=self._default_convolve_params, params=params)
313        conv_out = _select_conv_calc(conv_dim=conv_dim)
314
315        modules = []
316        input_layer_size_list = [self.input_size]
317        input_channels_count_list = self._calc_out_channels(
318            in_size=self.input_size,
319            in_channels=in_channels,
320            n_layers=n_layers,
321            ratio=ratio,
322            start=start,
323            channel_growth_rate=channel_growth_rate,
324        )
325
326        for layer in range(n_layers):
327            input_layer_size = input_layer_size_list[-1]
328
329            _validate_difference_in_dimensions(self.input_size, conv_dim)
330            _validate_available_layers(layer, input_layer_size, self.minimum_feature_map_size)
331            _validate_max_channels_number(layer, input_channels_count_list, self.max_channels)
332            _validate_min_channels_number(layer, input_channels_count_list, self.min_channels)
333
334            in_channels = input_channels_count_list[layer]
335            out_channels = input_channels_count_list[layer + 1]
336
337            out_layer_size = conv_out(input_size=input_layer_size, **params)
338            input_layer_size_list.append(out_layer_size)
339
340            convolve_block = self.build_convolve_block(
341                in_channels=in_channels,
342                out_channels=out_channels,
343                normalization=normalization,
344                sub_blocks=sub_blocks,
345                p=p,
346                inplace=inplace,
347                eps=eps,
348                momentum=momentum,
349                affine=affine,
350                params=params,
351                conv_dim=conv_dim,
352            )
353
354            modules.append((f"conv {layer + 1}", convolve_block))
355
356        self._conv_channels = input_channels_count_list
357        self._conv_layers = input_layer_size_list
358        return nn.Sequential(OrderedDict(modules))
359
360    def build_transpose_convolve_block(
361        self,
362        in_channels: int,
363        out_channels: int,
364        params: Optional[dict] = None,
365        normalization: Optional[str] = None,
366        sub_blocks: int = 1,
367        p: float = 0.5,
368        inplace: bool = False,
369        eps: float = 1e-5,
370        momentum: Optional[float] = 0.1,
371        affine: bool = True,
372        last_block: bool = False,
373        conv_dim: int = 2,
374    ) -> nn.Sequential:
375        """Builds a single block of transposed convolution layers.
376
377        This method constructs a sequential block of transposed convolutional layers,
378        with optional normalization and multiple sub-blocks per layer.
379
380        Args:
381            in_channels (int): Number of channels in the input image.
382            out_channels (int): Number of channels produced by the transposed convolution.
383            params (Optional[dict], optional): Parameters for the transposed convolutional layer
384                (for nn.ConvTranspose2d). Defaults to None.
385            normalization (Optional[str], optional): Type of normalization to apply.
386                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
387            sub_blocks (int, optional): Number of convolutions within each layer.
388                Defaults to 1.
389            p (float, optional): Probability of an element being zeroed for dropout.
390                Defaults to 0.5.
391            inplace (bool, optional): If True, performs the operation in-place
392                for dropout. Defaults to False.
393            eps (float, optional): A value added to the denominator for numerical stability
394                (used in batchnorm/instancenorm). Defaults to 1e-5.
395            momentum (Optional[float], optional): Momentum for running_mean or running_var
396                computation (used in batchnorm). If None, a cumulative moving average is used.
397                Defaults to 0.1.
398            affine (bool, optional): If True, the module has learnable affine parameters
399                (used in batchnorm). Defaults to True.
400            last_block (bool, optional): If True, no activation function is applied after
401                the transposed convolution. Defaults to False.
402            conv_dim (int, optional): The dimension of the convolutional operation.
403                Defaults to 2.
404
405        Returns:
406            A sequential block containing the specified transposed
407            convolutional layers, possibly including normalization and activation functions.
408        """
409        params = _set_conv_params(default_params=self._default_transpose_params, params=params)
410        convolution = _select_conv_dimension(conv_dim=conv_dim, transpose=True)
411
412        if sub_blocks > 1:
413            kernel_size = params["kernel_size"]
414            kernel_size = kernel_size if isinstance(kernel_size, int) else kernel_size[0]
415            params["padding"] = kernel_size // 2
416            params["stride"] = 1
417
418        blocks = []
419        last_out_channels = out_channels
420        for i in range(sub_blocks):
421            block = []
422
423            out_channels = last_out_channels if i == sub_blocks - 1 else in_channels
424            conv = convolution(in_channels=in_channels, out_channels=out_channels, **params)
425            block.append(conv)
426
427            if normalization:
428                norm = _select_norm_dimension(conv_dim=conv_dim, normalization=normalization)
429
430                if normalization in ("batchnorm", "instancenorm"):
431                    norm = norm(
432                        num_features=out_channels,
433                        eps=eps,
434                        momentum=momentum,
435                        affine=affine,
436                    )
437
438                if normalization == "dropout":
439                    norm = norm(p=p, inplace=inplace)
440
441                block.append(norm)
442
443            activation_function = self.activation_function
444            if last_block and i == sub_blocks - 1:
445                if self.finish_activation_function == "same":
446                    block.append(activation_function)
447                elif self.finish_activation_function:
448                    block.append(self.finish_activation_function)
449            else:
450                block.append(activation_function)
451
452            if sub_blocks > 1:
453                block = nn.Sequential(*block)
454                blocks.append((f"transpose sub-block {i + 1}", block))
455            else:
456                blocks.extend(block)
457
458        if sub_blocks > 1:
459            return nn.Sequential(OrderedDict(blocks))
460
461        return nn.Sequential(*blocks)
462
463    def build_transpose_convolve_sequence(
464        self,
465        n_layers: int,
466        in_channels: Optional[int] = None,
467        out_channels: int = 1,
468        out_size: Optional[tuple] = None,
469        params: Optional[dict] = None,
470        normalization: Optional[str] = None,
471        sub_blocks: int = 1,
472        p: float = 0.5,
473        inplace: bool = False,
474        eps: float = 1e-5,
475        momentum: Optional[float] = 0.1,
476        affine: bool = True,
477        ratio: float = 2.0,
478        channel_growth_rate: str = "exponential",
479        conv_dim: int = 2,
480        adaptive_pool: str = "avgpool",
481    ) -> nn.Sequential:
482        """Builds a sequence of transposed convolution blocks.
483
484        This method constructs a sequential layer of transposed convolution blocks,
485        allowing for customization through normalization, sub-blocks, and other parameters.
486
487        Args:
488            n_layers (int): Number of transposed convolution layers to create.
489            in_channels (Optional[int], optional): Number of channels in the first input tensor.
490                Defaults to None, which will use the last value from _conv_channels if available.
491            out_channels (int, optional): Number of channels after the transposed convolution sequence.
492                Defaults to 1.
493            out_size (Optional[tuple], optional): Desired output size after the transposed convolution sequence.
494                Defaults to None, which uses the input size.
495            params (Optional[dict], optional): Parameters for the transposed convolutional layer
496                (for nn.ConvTranspose2d). Defaults to None.
497            normalization (Optional[str], optional): Type of normalization to apply.
498                Options include 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
499            sub_blocks (int, optional): Number of transposed convolutions within each layer.
500                Defaults to 1.
501            p (float, optional): Probability of an element being zeroed for dropout.
502                Defaults to 0.5.
503            inplace (bool, optional): If True, performs the operation in-place
504                for dropout. Defaults to False.
505            eps (float, optional): A value added to the denominator for numerical stability
506                (used in batchnorm/instancenorm). Defaults to 1e-5.
507            momentum (Optional[float], optional): Momentum for running_mean or running_var
508                computation (used in batchnorm). If None, a cumulative moving average is used.
509                Defaults to 0.1.
510            affine (bool, optional): If True, the module has learnable affine parameters
511                (used in batchnorm). Defaults to True.
512            ratio (float, optional): Multiplier for the geometric progression of increasing channels
513                (feature maps). Used for 'channel_growth_rate' as 'exponential' or 'power'.
514                Defaults to 2 (powers of two).
515            channel_growth_rate (str, optional): Method of calculating the number of feature maps.
516                Options include 'exponential', 'proportion', 'linear', 'power', and 'constant'.
517                Defaults to 'exponential'.
518            conv_dim (int, optional): The dimension of the convolutional operation.
519                Defaults to 2.
520            adaptive_pool (str, optional): Type of adaptive pooling layer to apply last,
521                can be 'avgpool' or 'maxpool'. Defaults to 'avgpool'.
522
523        Returns:
524            A sequential block containing the specified transposed convolutional
525            layers, possibly including normalization and adaptive pooling.
526        """
527        _validate_input_size_is_not_none(self.input_size)
528        params = _set_conv_params(default_params=self._default_transpose_params, params=params)
529        conv_out = _select_conv_calc(conv_dim=conv_dim, transpose=True)
530
531        modules = []
532
533        if in_channels is None and self._conv_channels:
534            in_channels = self._conv_channels[-1]
535
536        _validate_build_transpose_convolve_init(in_channels, self._conv_channels)
537
538        if self._conv_layers:
539            input_layer_size_list = [self._conv_layers[-1]]
540
541        input_channels_count_list = self._calc_out_transpose_channels(
542            in_channels=in_channels,
543            out_channels=out_channels,
544            n_layers=n_layers,
545            ratio=ratio,
546            channel_growth_rate=channel_growth_rate,
547        )
548        for layer in range(n_layers):
549            _validate_max_channels_number(layer, input_channels_count_list, self.max_channels)
550            _validate_min_channels_number(layer, input_channels_count_list, min_channels=1)
551
552            in_channels = input_channels_count_list[layer]
553            out_channels = input_channels_count_list[layer + 1]
554
555            if self._conv_layers:
556                input_layer_size = input_layer_size_list[-1]
557                out_layer_size = conv_out(input_size=input_layer_size, **params)
558                input_layer_size_list.append(out_layer_size)
559
560            last_block_condition = layer == n_layers - 1
561            convolve_block = self.build_transpose_convolve_block(
562                in_channels=in_channels,
563                out_channels=out_channels,
564                normalization=normalization,
565                sub_blocks=sub_blocks,
566                p=p,
567                inplace=inplace,
568                eps=eps,
569                momentum=momentum,
570                affine=affine,
571                params=params,
572                last_block=last_block_condition,
573                conv_dim=conv_dim,
574            )
575
576            modules.append((f"deconv {layer + 1}", convolve_block))
577
578        self._transpose_conv_channels = input_channels_count_list
579
580        if self._conv_layers:
581            self._transpose_conv_layers = input_layer_size_list
582
583        if out_size is None:
584            out_size = self.input_size
585
586        adaptive_pooling = _select_adaptive_pooling_dimension(conv_dim=conv_dim, pooling=adaptive_pool)
587        resize_block = adaptive_pooling(output_size=tuple(out_size))
588        modules.append(("resize", resize_block))
589
590        return nn.Sequential(OrderedDict(modules))
591
592    def latent_block(
593        self,
594        input_shape: Sequence[int],
595        output_shape: Sequence[int],
596        n_layers: int = 1,
597        activation_function: Union[Optional[nn.Module], str] = None,
598    ):
599        """Creates a latent space transformation block.
600
601        This method constructs a latent space module that transforms an input tensor
602        of a specified shape into an output tensor of a desired shape using
603        linear layers and an optional activation function.
604
605        Args:
606            input_shape (Sequence[int]): The shape of the input tensor, typically
607                represented as a sequence of integers.
608            output_shape (Sequence[int]): The desired shape of the output tensor,
609                specified as a sequence of integers.
610            n_layers (int, optional): The number of linear layers to use in the
611                transformation. Defaults to 1.
612            activation_function (Union[Optional[nn.Module], str], optional):
613                Specifies the activation function to apply after the linear layers.
614                If set to 'same', it will use the instance's predefined activation
615                function. Defaults to None.
616
617        Returns:
618            An instance of the LatentSpaceModule class that
619            performs the specified transformation from input to output shape.
620        """
621        if activation_function == "same":
622            activation_function = self.activation_function
623
624        return LatentSpaceModule(input_shape, output_shape, n_layers, activation_function)
625
626    def _calc_out_channels(
627        self,
628        in_size: Sequence[int],
629        in_channels: int,
630        n_layers: int,
631        ratio: float = 2.0,
632        start: int = 32,
633        constant: int = 1,
634        channel_growth_rate: str = "exponential",
635    ) -> List[int]:
636        _validate_channel_growth_rate_param(channel_growth_rate)
637
638        if channel_growth_rate == "exponential":
639            self.max_channels = self._initial_max_channels
640            return [in_channels] + [int(start * ratio**i) for i in range(n_layers)]
641
642        if channel_growth_rate == "proportion":
643            range_start = in_channels
644            range_stop = int((sum(in_size) * 0.5) // len(in_size) + in_channels)
645            range_step = (range_stop - in_channels) // n_layers
646
647            _validate_range_step(range_step, n_layers)
648
649            channels = list(range(range_start, range_stop + 1, range_step))[: n_layers + 1]
650            self.max_channels = range_stop
651            return channels
652
653        if channel_growth_rate == "linear":
654            self.max_channels = self.min_channels + n_layers
655            return [in_channels] + [in_channels + i + 1 for i in range(n_layers)]
656
657        if channel_growth_rate == "constant":
658            self.max_channels = constant + 1
659            return [in_channels] + [constant for _ in range(n_layers)]
660
661        if channel_growth_rate == "power":
662            self.max_channels = self._initial_max_channels
663            return [in_channels] + [int((in_channels + i) ** ratio) for i in range(1, n_layers + 1)]
664
665    @staticmethod
666    def _calc_out_transpose_channels(
667        in_channels: int,
668        out_channels: int,
669        n_layers: int,
670        ratio: float = 2.0,
671        constant: int = 1,
672        channel_growth_rate: str = "exponential",
673    ) -> List[int]:
674        _validate_channel_growth_rate_param(channel_growth_rate)
675
676        if channel_growth_rate == "exponential":
677            return [int(in_channels / ratio**i) for i in range(n_layers)] + [out_channels]
678
679        if channel_growth_rate == "proportion":
680            channels = list(range(out_channels, in_channels, (in_channels - out_channels) // n_layers))[::-1]
681            channels = channels[:n_layers]
682            channels[-1] = out_channels
683            return [in_channels] + channels
684
685        if channel_growth_rate == "linear":
686            return [in_channels] + [in_channels - i for i in range(1, n_layers)] + [out_channels]
687
688        if channel_growth_rate == "constant":
689            return [in_channels] + [constant for _ in range(n_layers - 1)] + [out_channels]
690
691        if channel_growth_rate == "power":
692            return (
693                [in_channels] + [int(math.pow((n_layers - i + 1), ratio)) for i in range(1, n_layers)] + [out_channels]
694            )

A class for creating СNN architectures

Builder( input_size: Optional[Sequence[int]] = None, minimum_feature_map_size: Union[Sequence[int], int] = 5, max_channels: int = 512, min_channels: int = 1, activation_function: torch.nn.modules.module.Module = ReLU(inplace=True), finish_activation_function: Union[torch.nn.modules.module.Module, NoneType, str] = None)
 42    def __init__(
 43        self,
 44        input_size: Optional[Sequence[int]] = None,
 45        minimum_feature_map_size: Union[Sequence[int], int] = 5,
 46        max_channels: int = 512,
 47        min_channels: int = 1,
 48        activation_function: nn.Module = nn.ReLU(inplace=True),
 49        finish_activation_function: Union[Optional[nn.Module], str] = None,
 50    ) -> None:
 51        """
 52        Initializes the Builder instance.
 53
 54        Args:
 55            input_size (Optional[Sequence[int]], optional):
 56                Input size of the input tensor. Necessary for creating
 57                convolution sequences. Defaults to None.
 58            minimum_feature_map_size (Union[Sequence[int], int], optional):
 59                Minimum feature map size. Defaults to 5.
 60            max_channels (int, optional):
 61                Maximum number of layers after any convolution. Defaults to 512.
 62            min_channels (int, optional):
 63                Minimum number of layers after any convolution. Defaults to 1.
 64            activation_function (nn.Module, optional):
 65                Activation function. Defaults to nn.ReLU(inplace=True).
 66            finish_activation_function (Union[Optional[nn.Module], str], optional):
 67                Last activation function, can be the same as activation_function
 68                (use string 'same' for that). Defaults to None.
 69
 70        Raises:
 71            ValueError: If input_size is not a valid shape.
 72        """
 73
 74        if input_size is None:
 75            self.input_size = input_size
 76        else:
 77            self.input_size = tuple(i for i in input_size)
 78
 79            if len(self.input_size) == 1:
 80                self.minimum_feature_map_size = (
 81                    (minimum_feature_map_size,)
 82                    if isinstance(minimum_feature_map_size, int)
 83                    else minimum_feature_map_size
 84                )
 85            if len(self.input_size) == 2:
 86                self.minimum_feature_map_size = (
 87                    _double_params(
 88                        minimum_feature_map_size,
 89                    )
 90                    if isinstance(minimum_feature_map_size, int)
 91                    else minimum_feature_map_size
 92                )
 93            if len(self.input_size) == 3:
 94                self.minimum_feature_map_size = (
 95                    _triple_params(
 96                        minimum_feature_map_size,
 97                    )
 98                    if isinstance(minimum_feature_map_size, int)
 99                    else minimum_feature_map_size
100                )
101
102        self.max_channels = max_channels
103        self._initial_max_channels = max_channels
104
105        self.min_channels = min_channels
106        self._initial_min_channels = min_channels
107
108        self._default_convolve_params = DEFAULT_CONV_PARAMS
109        self._default_transpose_params = DEFAULT_TRANSPOSE_CONV_PARAMS
110
111        # finish_activation_function can be str 'same' which equals to activation_function
112        self.activation_function = activation_function
113        self.finish_activation_function = finish_activation_function
114
115        self._conv_channels = None
116        self._transpose_conv_channels = None
117
118        self._conv_layers = None
119        self._transpose_conv_layers = None

Initializes the Builder instance.

Arguments:
  • input_size (Optional[Sequence[int]], optional): Input size of the input tensor. Necessary for creating convolution sequences. Defaults to None.
  • minimum_feature_map_size (Union[Sequence[int], int], optional): Minimum feature map size. Defaults to 5.
  • max_channels (int, optional): Maximum number of layers after any convolution. Defaults to 512.
  • min_channels (int, optional): Minimum number of layers after any convolution. Defaults to 1.
  • activation_function (nn.Module, optional): Activation function. Defaults to nn.ReLU(inplace=True).
  • finish_activation_function (Union[Optional[nn.Module], str], optional): Last activation function, can be the same as activation_function (use string 'same' for that). Defaults to None.
Raises:
  • ValueError: If input_size is not a valid shape.
conv_channels: Optional[List[int]]
121    @property
122    def conv_channels(self) -> Optional[List[int]]:
123        """Gets the convolutional channels.
124
125        Returns:
126            A list of convolutional channel sizes or None
127            if not initialized.
128        """
129        return self._conv_channels

Gets the convolutional channels.

Returns:

A list of convolutional channel sizes or None if not initialized.

transpose_conv_channels: Optional[List[int]]
131    @property
132    def transpose_conv_channels(self) -> Optional[List[int]]:
133        """Gets the transposed convolutional channels.
134
135        Returns:
136            A list of transposed convolutional channel sizes
137            or None if not initialized.
138        """
139        return self._transpose_conv_channels

Gets the transposed convolutional channels.

Returns:

A list of transposed convolutional channel sizes or None if not initialized.

conv_layers: Optional[List[Tuple[int, ...]]]
141    @property
142    def conv_layers(self) -> Optional[List[Tuple[int, ...]]]:
143        """Gets the convolutional layers.
144
145        Returns:
146            A list of tuples representing convolutional layer configurations or None if not initialized.
147        """
148        return self._conv_layers

Gets the convolutional layers.

Returns:

A list of tuples representing convolutional layer configurations or None if not initialized.

transpose_conv_layers: Optional[List[Tuple[int, ...]]]
150    @property
151    def transpose_conv_layers(self) -> Optional[List[Tuple[int, ...]]]:
152        """Gets the transposed convolutional layers.
153
154        Returns:
155            A list of tuples representing transposed convolutional layer configurations or None if not
156            initialized.
157        """
158        return self._transpose_conv_layers

Gets the transposed convolutional layers.

Returns:

A list of tuples representing transposed convolutional layer configurations or None if not initialized.

def build_convolve_block( self, in_channels: int, out_channels: int, params: Optional[dict] = None, normalization: Optional[str] = None, sub_blocks: int = 1, p: float = 0.5, inplace: bool = False, eps: float = 1e-05, momentum: Optional[float] = 0.1, affine: bool = True, conv_dim: int = 2) -> torch.nn.modules.container.Sequential:
160    def build_convolve_block(
161        self,
162        in_channels: int,
163        out_channels: int,
164        params: Optional[dict] = None,
165        normalization: Optional[str] = None,
166        sub_blocks: int = 1,
167        p: float = 0.5,
168        inplace: bool = False,
169        eps: float = 1e-5,
170        momentum: Optional[float] = 0.1,
171        affine: bool = True,
172        conv_dim: int = 2,
173    ) -> nn.Sequential:
174        """Builds a single block of convolution layers.
175
176        This method creates a sequential block that consists of convolutional layers,
177        optional normalization layers, and an activation function.
178
179        Args:
180            in_channels (int): Number of channels in the input image.
181            out_channels (int): Number of channels produced by the convolution.
182            params (Optional[dict], optional): Convolutional layer parameters
183                (for nn.ConvNd). Defaults to None.
184            normalization (Optional[str], optional): Type of normalization to apply.
185                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
186            sub_blocks (int, optional): Number of convolutional layers within the block.
187                Defaults to 1.
188            p (float, optional): Probability of an element being zeroed for dropout/instancenorm.
189                Defaults to 0.5.
190            inplace (bool, optional): If True, performs the operation in-place
191                for dropout/instancenorm. Defaults to False.
192            eps (float, optional): A value added to the denominator for numerical stability
193                (used in batchnorm/instancenorm). Defaults to 1e-5.
194            momentum (Optional[float], optional): Momentum for running_mean or running_var
195                computation (used in batchnorm). If None, a cumulative moving average is used.
196                Defaults to 0.1.
197            affine (bool, optional): If True, the module has learnable affine parameters
198                (used in batchnorm). Defaults to True.
199            conv_dim (int, optional): The dimension of the convolutional operation (2 for
200                2D convolution, 3 for 3D convolution). Defaults to 2.
201
202        Returns:
203            A sequential block containing convolutional layers,
204            optional normalization layers, and an activation function.
205        """
206        params = _set_conv_params(default_params=self._default_convolve_params, params=params)
207        convolution = _select_conv_dimension(conv_dim=conv_dim)
208
209        if sub_blocks > 1:
210            kernel_size = params["kernel_size"]
211            kernel_size = kernel_size if isinstance(kernel_size, int) else kernel_size[0]
212            params["padding"] = kernel_size // 2
213            params["stride"] = 1
214
215        blocks = []
216        for i in range(sub_blocks):
217            block = []
218
219            conv = convolution(in_channels=in_channels, out_channels=out_channels, **params)
220            in_channels = out_channels
221            block.append(conv)
222
223            if normalization:
224                norm = _select_norm_dimension(conv_dim=conv_dim, normalization=normalization)
225
226                if normalization in ("batchnorm", "instancenorm"):
227                    norm = norm(
228                        num_features=out_channels,
229                        eps=eps,
230                        momentum=momentum,
231                        affine=affine,
232                    )
233
234                if normalization == "dropout":
235                    norm = norm(p=p, inplace=inplace)
236
237                block.append(norm)
238
239            activation_function = self.activation_function
240            block.append(activation_function)
241
242            if sub_blocks > 1:
243                block = nn.Sequential(*block)
244                blocks.append((f"sub-block {i + 1}", block))
245            else:
246                blocks.extend(block)
247
248        if sub_blocks > 1:
249            return nn.Sequential(OrderedDict(blocks))
250
251        return nn.Sequential(*blocks)

Builds a single block of convolution layers.

This method creates a sequential block that consists of convolutional layers, optional normalization layers, and an activation function.

Arguments:
  • in_channels (int): Number of channels in the input image.
  • out_channels (int): Number of channels produced by the convolution.
  • params (Optional[dict], optional): Convolutional layer parameters (for nn.ConvNd). Defaults to None.
  • normalization (Optional[str], optional): Type of normalization to apply. Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
  • sub_blocks (int, optional): Number of convolutional layers within the block. Defaults to 1.
  • p (float, optional): Probability of an element being zeroed for dropout/instancenorm. Defaults to 0.5.
  • inplace (bool, optional): If True, performs the operation in-place for dropout/instancenorm. Defaults to False.
  • eps (float, optional): A value added to the denominator for numerical stability (used in batchnorm/instancenorm). Defaults to 1e-5.
  • momentum (Optional[float], optional): Momentum for running_mean or running_var computation (used in batchnorm). If None, a cumulative moving average is used. Defaults to 0.1.
  • affine (bool, optional): If True, the module has learnable affine parameters (used in batchnorm). Defaults to True.
  • conv_dim (int, optional): The dimension of the convolutional operation (2 for 2D convolution, 3 for 3D convolution). Defaults to 2.
Returns:

A sequential block containing convolutional layers, optional normalization layers, and an activation function.

def build_convolve_sequence( self, n_layers: int, in_channels: int = 1, params: Optional[dict] = None, normalization: Optional[str] = None, sub_blocks: int = 1, p: float = 0.5, inplace: bool = False, eps: float = 1e-05, momentum: Optional[float] = 0.1, affine: bool = True, ratio: float = 2.0, start: int = 32, channel_growth_rate: str = 'exponential', conv_dim: int = 2) -> torch.nn.modules.container.Sequential:
253    def build_convolve_sequence(
254        self,
255        n_layers: int,
256        in_channels: int = 1,
257        params: Optional[dict] = None,
258        normalization: Optional[str] = None,
259        sub_blocks: int = 1,
260        p: float = 0.5,
261        inplace: bool = False,
262        eps: float = 1e-5,
263        momentum: Optional[float] = 0.1,
264        affine: bool = True,
265        ratio: float = 2.0,
266        start: int = 32,
267        channel_growth_rate: str = "exponential",
268        conv_dim: int = 2,
269    ) -> nn.Sequential:
270        """Builds a sequence of convolution blocks.
271
272        This method constructs a sequential block of convolutional layers,
273        with optional normalization and multiple sub-blocks per layer.
274
275        Args:
276            n_layers (int): Number of convolution layers in the encoder part.
277            in_channels (int, optional): Number of channels in the first input tensor.
278                Defaults to 1.
279            params (Optional[dict], optional): Convolutional layer parameters
280                (for nn.ConvNd). Defaults to None.
281            normalization (Optional[str], optional): Type of normalization to apply.
282                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
283            sub_blocks (int, optional): Number of convolutions within each layer.
284                Defaults to 1.
285            p (float, optional): Probability of an element being zeroed for dropout.
286                Defaults to 0.5.
287            inplace (bool, optional): If True, performs the operation in-place
288                for dropout. Defaults to False.
289            eps (float, optional): A value added to the denominator for numerical stability
290                (used in batchnorm/instancenorm). Defaults to 1e-5.
291            momentum (Optional[float], optional): Momentum for running_mean or running_var
292                computation (used in batchnorm). If None, a cumulative moving average is used.
293                Defaults to 0.1.
294            affine (bool, optional): If True, the module has learnable affine parameters
295                (used in batchnorm). Defaults to True.
296            ratio (float, optional): Multiplier for the geometric progression of increasing
297                channels (feature maps). Used for 'channel_growth_rate' as 'exponential'
298                or 'power'. Defaults to 2.0.
299            start (int, optional): Starting position of the geometric progression
300                when 'channel_growth_rate' is set to 'exponential'. Defaults to 32.
301            channel_growth_rate (str, optional): Method for calculating the number of
302                feature maps. Options include 'exponential', 'proportion', 'linear',
303                'power', and 'constant'. Defaults to 'exponential'.
304            conv_dim (int, optional): The dimension of the convolutional operation.
305                Defaults to 2.
306
307        Returns:
308            A sequential block containing the specified number of
309            convolutional layers.
310        """
311        _validate_input_size_is_not_none(self.input_size)
312        params = _set_conv_params(default_params=self._default_convolve_params, params=params)
313        conv_out = _select_conv_calc(conv_dim=conv_dim)
314
315        modules = []
316        input_layer_size_list = [self.input_size]
317        input_channels_count_list = self._calc_out_channels(
318            in_size=self.input_size,
319            in_channels=in_channels,
320            n_layers=n_layers,
321            ratio=ratio,
322            start=start,
323            channel_growth_rate=channel_growth_rate,
324        )
325
326        for layer in range(n_layers):
327            input_layer_size = input_layer_size_list[-1]
328
329            _validate_difference_in_dimensions(self.input_size, conv_dim)
330            _validate_available_layers(layer, input_layer_size, self.minimum_feature_map_size)
331            _validate_max_channels_number(layer, input_channels_count_list, self.max_channels)
332            _validate_min_channels_number(layer, input_channels_count_list, self.min_channels)
333
334            in_channels = input_channels_count_list[layer]
335            out_channels = input_channels_count_list[layer + 1]
336
337            out_layer_size = conv_out(input_size=input_layer_size, **params)
338            input_layer_size_list.append(out_layer_size)
339
340            convolve_block = self.build_convolve_block(
341                in_channels=in_channels,
342                out_channels=out_channels,
343                normalization=normalization,
344                sub_blocks=sub_blocks,
345                p=p,
346                inplace=inplace,
347                eps=eps,
348                momentum=momentum,
349                affine=affine,
350                params=params,
351                conv_dim=conv_dim,
352            )
353
354            modules.append((f"conv {layer + 1}", convolve_block))
355
356        self._conv_channels = input_channels_count_list
357        self._conv_layers = input_layer_size_list
358        return nn.Sequential(OrderedDict(modules))

Builds a sequence of convolution blocks.

This method constructs a sequential block of convolutional layers, with optional normalization and multiple sub-blocks per layer.

Arguments:
  • n_layers (int): Number of convolution layers in the encoder part.
  • in_channels (int, optional): Number of channels in the first input tensor. Defaults to 1.
  • params (Optional[dict], optional): Convolutional layer parameters (for nn.ConvNd). Defaults to None.
  • normalization (Optional[str], optional): Type of normalization to apply. Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
  • sub_blocks (int, optional): Number of convolutions within each layer. Defaults to 1.
  • p (float, optional): Probability of an element being zeroed for dropout. Defaults to 0.5.
  • inplace (bool, optional): If True, performs the operation in-place for dropout. Defaults to False.
  • eps (float, optional): A value added to the denominator for numerical stability (used in batchnorm/instancenorm). Defaults to 1e-5.
  • momentum (Optional[float], optional): Momentum for running_mean or running_var computation (used in batchnorm). If None, a cumulative moving average is used. Defaults to 0.1.
  • affine (bool, optional): If True, the module has learnable affine parameters (used in batchnorm). Defaults to True.
  • ratio (float, optional): Multiplier for the geometric progression of increasing channels (feature maps). Used for 'channel_growth_rate' as 'exponential' or 'power'. Defaults to 2.0.
  • start (int, optional): Starting position of the geometric progression when 'channel_growth_rate' is set to 'exponential'. Defaults to 32.
  • channel_growth_rate (str, optional): Method for calculating the number of feature maps. Options include 'exponential', 'proportion', 'linear', 'power', and 'constant'. Defaults to 'exponential'.
  • conv_dim (int, optional): The dimension of the convolutional operation. Defaults to 2.
Returns:

A sequential block containing the specified number of convolutional layers.

def build_transpose_convolve_block( self, in_channels: int, out_channels: int, params: Optional[dict] = None, normalization: Optional[str] = None, sub_blocks: int = 1, p: float = 0.5, inplace: bool = False, eps: float = 1e-05, momentum: Optional[float] = 0.1, affine: bool = True, last_block: bool = False, conv_dim: int = 2) -> torch.nn.modules.container.Sequential:
360    def build_transpose_convolve_block(
361        self,
362        in_channels: int,
363        out_channels: int,
364        params: Optional[dict] = None,
365        normalization: Optional[str] = None,
366        sub_blocks: int = 1,
367        p: float = 0.5,
368        inplace: bool = False,
369        eps: float = 1e-5,
370        momentum: Optional[float] = 0.1,
371        affine: bool = True,
372        last_block: bool = False,
373        conv_dim: int = 2,
374    ) -> nn.Sequential:
375        """Builds a single block of transposed convolution layers.
376
377        This method constructs a sequential block of transposed convolutional layers,
378        with optional normalization and multiple sub-blocks per layer.
379
380        Args:
381            in_channels (int): Number of channels in the input image.
382            out_channels (int): Number of channels produced by the transposed convolution.
383            params (Optional[dict], optional): Parameters for the transposed convolutional layer
384                (for nn.ConvTranspose2d). Defaults to None.
385            normalization (Optional[str], optional): Type of normalization to apply.
386                Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
387            sub_blocks (int, optional): Number of convolutions within each layer.
388                Defaults to 1.
389            p (float, optional): Probability of an element being zeroed for dropout.
390                Defaults to 0.5.
391            inplace (bool, optional): If True, performs the operation in-place
392                for dropout. Defaults to False.
393            eps (float, optional): A value added to the denominator for numerical stability
394                (used in batchnorm/instancenorm). Defaults to 1e-5.
395            momentum (Optional[float], optional): Momentum for running_mean or running_var
396                computation (used in batchnorm). If None, a cumulative moving average is used.
397                Defaults to 0.1.
398            affine (bool, optional): If True, the module has learnable affine parameters
399                (used in batchnorm). Defaults to True.
400            last_block (bool, optional): If True, no activation function is applied after
401                the transposed convolution. Defaults to False.
402            conv_dim (int, optional): The dimension of the convolutional operation.
403                Defaults to 2.
404
405        Returns:
406            A sequential block containing the specified transposed
407            convolutional layers, possibly including normalization and activation functions.
408        """
409        params = _set_conv_params(default_params=self._default_transpose_params, params=params)
410        convolution = _select_conv_dimension(conv_dim=conv_dim, transpose=True)
411
412        if sub_blocks > 1:
413            kernel_size = params["kernel_size"]
414            kernel_size = kernel_size if isinstance(kernel_size, int) else kernel_size[0]
415            params["padding"] = kernel_size // 2
416            params["stride"] = 1
417
418        blocks = []
419        last_out_channels = out_channels
420        for i in range(sub_blocks):
421            block = []
422
423            out_channels = last_out_channels if i == sub_blocks - 1 else in_channels
424            conv = convolution(in_channels=in_channels, out_channels=out_channels, **params)
425            block.append(conv)
426
427            if normalization:
428                norm = _select_norm_dimension(conv_dim=conv_dim, normalization=normalization)
429
430                if normalization in ("batchnorm", "instancenorm"):
431                    norm = norm(
432                        num_features=out_channels,
433                        eps=eps,
434                        momentum=momentum,
435                        affine=affine,
436                    )
437
438                if normalization == "dropout":
439                    norm = norm(p=p, inplace=inplace)
440
441                block.append(norm)
442
443            activation_function = self.activation_function
444            if last_block and i == sub_blocks - 1:
445                if self.finish_activation_function == "same":
446                    block.append(activation_function)
447                elif self.finish_activation_function:
448                    block.append(self.finish_activation_function)
449            else:
450                block.append(activation_function)
451
452            if sub_blocks > 1:
453                block = nn.Sequential(*block)
454                blocks.append((f"transpose sub-block {i + 1}", block))
455            else:
456                blocks.extend(block)
457
458        if sub_blocks > 1:
459            return nn.Sequential(OrderedDict(blocks))
460
461        return nn.Sequential(*blocks)

Builds a single block of transposed convolution layers.

This method constructs a sequential block of transposed convolutional layers, with optional normalization and multiple sub-blocks per layer.

Arguments:
  • in_channels (int): Number of channels in the input image.
  • out_channels (int): Number of channels produced by the transposed convolution.
  • params (Optional[dict], optional): Parameters for the transposed convolutional layer (for nn.ConvTranspose2d). Defaults to None.
  • normalization (Optional[str], optional): Type of normalization to apply. Options are 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
  • sub_blocks (int, optional): Number of convolutions within each layer. Defaults to 1.
  • p (float, optional): Probability of an element being zeroed for dropout. Defaults to 0.5.
  • inplace (bool, optional): If True, performs the operation in-place for dropout. Defaults to False.
  • eps (float, optional): A value added to the denominator for numerical stability (used in batchnorm/instancenorm). Defaults to 1e-5.
  • momentum (Optional[float], optional): Momentum for running_mean or running_var computation (used in batchnorm). If None, a cumulative moving average is used. Defaults to 0.1.
  • affine (bool, optional): If True, the module has learnable affine parameters (used in batchnorm). Defaults to True.
  • last_block (bool, optional): If True, no activation function is applied after the transposed convolution. Defaults to False.
  • conv_dim (int, optional): The dimension of the convolutional operation. Defaults to 2.
Returns:

A sequential block containing the specified transposed convolutional layers, possibly including normalization and activation functions.

def build_transpose_convolve_sequence( self, n_layers: int, in_channels: Optional[int] = None, out_channels: int = 1, out_size: Optional[tuple] = None, params: Optional[dict] = None, normalization: Optional[str] = None, sub_blocks: int = 1, p: float = 0.5, inplace: bool = False, eps: float = 1e-05, momentum: Optional[float] = 0.1, affine: bool = True, ratio: float = 2.0, channel_growth_rate: str = 'exponential', conv_dim: int = 2, adaptive_pool: str = 'avgpool') -> torch.nn.modules.container.Sequential:
463    def build_transpose_convolve_sequence(
464        self,
465        n_layers: int,
466        in_channels: Optional[int] = None,
467        out_channels: int = 1,
468        out_size: Optional[tuple] = None,
469        params: Optional[dict] = None,
470        normalization: Optional[str] = None,
471        sub_blocks: int = 1,
472        p: float = 0.5,
473        inplace: bool = False,
474        eps: float = 1e-5,
475        momentum: Optional[float] = 0.1,
476        affine: bool = True,
477        ratio: float = 2.0,
478        channel_growth_rate: str = "exponential",
479        conv_dim: int = 2,
480        adaptive_pool: str = "avgpool",
481    ) -> nn.Sequential:
482        """Builds a sequence of transposed convolution blocks.
483
484        This method constructs a sequential layer of transposed convolution blocks,
485        allowing for customization through normalization, sub-blocks, and other parameters.
486
487        Args:
488            n_layers (int): Number of transposed convolution layers to create.
489            in_channels (Optional[int], optional): Number of channels in the first input tensor.
490                Defaults to None, which will use the last value from _conv_channels if available.
491            out_channels (int, optional): Number of channels after the transposed convolution sequence.
492                Defaults to 1.
493            out_size (Optional[tuple], optional): Desired output size after the transposed convolution sequence.
494                Defaults to None, which uses the input size.
495            params (Optional[dict], optional): Parameters for the transposed convolutional layer
496                (for nn.ConvTranspose2d). Defaults to None.
497            normalization (Optional[str], optional): Type of normalization to apply.
498                Options include 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
499            sub_blocks (int, optional): Number of transposed convolutions within each layer.
500                Defaults to 1.
501            p (float, optional): Probability of an element being zeroed for dropout.
502                Defaults to 0.5.
503            inplace (bool, optional): If True, performs the operation in-place
504                for dropout. Defaults to False.
505            eps (float, optional): A value added to the denominator for numerical stability
506                (used in batchnorm/instancenorm). Defaults to 1e-5.
507            momentum (Optional[float], optional): Momentum for running_mean or running_var
508                computation (used in batchnorm). If None, a cumulative moving average is used.
509                Defaults to 0.1.
510            affine (bool, optional): If True, the module has learnable affine parameters
511                (used in batchnorm). Defaults to True.
512            ratio (float, optional): Multiplier for the geometric progression of increasing channels
513                (feature maps). Used for 'channel_growth_rate' as 'exponential' or 'power'.
514                Defaults to 2 (powers of two).
515            channel_growth_rate (str, optional): Method of calculating the number of feature maps.
516                Options include 'exponential', 'proportion', 'linear', 'power', and 'constant'.
517                Defaults to 'exponential'.
518            conv_dim (int, optional): The dimension of the convolutional operation.
519                Defaults to 2.
520            adaptive_pool (str, optional): Type of adaptive pooling layer to apply last,
521                can be 'avgpool' or 'maxpool'. Defaults to 'avgpool'.
522
523        Returns:
524            A sequential block containing the specified transposed convolutional
525            layers, possibly including normalization and adaptive pooling.
526        """
527        _validate_input_size_is_not_none(self.input_size)
528        params = _set_conv_params(default_params=self._default_transpose_params, params=params)
529        conv_out = _select_conv_calc(conv_dim=conv_dim, transpose=True)
530
531        modules = []
532
533        if in_channels is None and self._conv_channels:
534            in_channels = self._conv_channels[-1]
535
536        _validate_build_transpose_convolve_init(in_channels, self._conv_channels)
537
538        if self._conv_layers:
539            input_layer_size_list = [self._conv_layers[-1]]
540
541        input_channels_count_list = self._calc_out_transpose_channels(
542            in_channels=in_channels,
543            out_channels=out_channels,
544            n_layers=n_layers,
545            ratio=ratio,
546            channel_growth_rate=channel_growth_rate,
547        )
548        for layer in range(n_layers):
549            _validate_max_channels_number(layer, input_channels_count_list, self.max_channels)
550            _validate_min_channels_number(layer, input_channels_count_list, min_channels=1)
551
552            in_channels = input_channels_count_list[layer]
553            out_channels = input_channels_count_list[layer + 1]
554
555            if self._conv_layers:
556                input_layer_size = input_layer_size_list[-1]
557                out_layer_size = conv_out(input_size=input_layer_size, **params)
558                input_layer_size_list.append(out_layer_size)
559
560            last_block_condition = layer == n_layers - 1
561            convolve_block = self.build_transpose_convolve_block(
562                in_channels=in_channels,
563                out_channels=out_channels,
564                normalization=normalization,
565                sub_blocks=sub_blocks,
566                p=p,
567                inplace=inplace,
568                eps=eps,
569                momentum=momentum,
570                affine=affine,
571                params=params,
572                last_block=last_block_condition,
573                conv_dim=conv_dim,
574            )
575
576            modules.append((f"deconv {layer + 1}", convolve_block))
577
578        self._transpose_conv_channels = input_channels_count_list
579
580        if self._conv_layers:
581            self._transpose_conv_layers = input_layer_size_list
582
583        if out_size is None:
584            out_size = self.input_size
585
586        adaptive_pooling = _select_adaptive_pooling_dimension(conv_dim=conv_dim, pooling=adaptive_pool)
587        resize_block = adaptive_pooling(output_size=tuple(out_size))
588        modules.append(("resize", resize_block))
589
590        return nn.Sequential(OrderedDict(modules))

Builds a sequence of transposed convolution blocks.

This method constructs a sequential layer of transposed convolution blocks, allowing for customization through normalization, sub-blocks, and other parameters.

Arguments:
  • n_layers (int): Number of transposed convolution layers to create.
  • in_channels (Optional[int], optional): Number of channels in the first input tensor. Defaults to None, which will use the last value from _conv_channels if available.
  • out_channels (int, optional): Number of channels after the transposed convolution sequence. Defaults to 1.
  • out_size (Optional[tuple], optional): Desired output size after the transposed convolution sequence. Defaults to None, which uses the input size.
  • params (Optional[dict], optional): Parameters for the transposed convolutional layer (for nn.ConvTranspose2d). Defaults to None.
  • normalization (Optional[str], optional): Type of normalization to apply. Options include 'dropout', 'instancenorm', and 'batchnorm'. Defaults to None.
  • sub_blocks (int, optional): Number of transposed convolutions within each layer. Defaults to 1.
  • p (float, optional): Probability of an element being zeroed for dropout. Defaults to 0.5.
  • inplace (bool, optional): If True, performs the operation in-place for dropout. Defaults to False.
  • eps (float, optional): A value added to the denominator for numerical stability (used in batchnorm/instancenorm). Defaults to 1e-5.
  • momentum (Optional[float], optional): Momentum for running_mean or running_var computation (used in batchnorm). If None, a cumulative moving average is used. Defaults to 0.1.
  • affine (bool, optional): If True, the module has learnable affine parameters (used in batchnorm). Defaults to True.
  • ratio (float, optional): Multiplier for the geometric progression of increasing channels (feature maps). Used for 'channel_growth_rate' as 'exponential' or 'power'. Defaults to 2 (powers of two).
  • channel_growth_rate (str, optional): Method of calculating the number of feature maps. Options include 'exponential', 'proportion', 'linear', 'power', and 'constant'. Defaults to 'exponential'.
  • conv_dim (int, optional): The dimension of the convolutional operation. Defaults to 2.
  • adaptive_pool (str, optional): Type of adaptive pooling layer to apply last, can be 'avgpool' or 'maxpool'. Defaults to 'avgpool'.
Returns:

A sequential block containing the specified transposed convolutional layers, possibly including normalization and adaptive pooling.

def latent_block( self, input_shape: Sequence[int], output_shape: Sequence[int], n_layers: int = 1, activation_function: Union[torch.nn.modules.module.Module, NoneType, str] = None):
592    def latent_block(
593        self,
594        input_shape: Sequence[int],
595        output_shape: Sequence[int],
596        n_layers: int = 1,
597        activation_function: Union[Optional[nn.Module], str] = None,
598    ):
599        """Creates a latent space transformation block.
600
601        This method constructs a latent space module that transforms an input tensor
602        of a specified shape into an output tensor of a desired shape using
603        linear layers and an optional activation function.
604
605        Args:
606            input_shape (Sequence[int]): The shape of the input tensor, typically
607                represented as a sequence of integers.
608            output_shape (Sequence[int]): The desired shape of the output tensor,
609                specified as a sequence of integers.
610            n_layers (int, optional): The number of linear layers to use in the
611                transformation. Defaults to 1.
612            activation_function (Union[Optional[nn.Module], str], optional):
613                Specifies the activation function to apply after the linear layers.
614                If set to 'same', it will use the instance's predefined activation
615                function. Defaults to None.
616
617        Returns:
618            An instance of the LatentSpaceModule class that
619            performs the specified transformation from input to output shape.
620        """
621        if activation_function == "same":
622            activation_function = self.activation_function
623
624        return LatentSpaceModule(input_shape, output_shape, n_layers, activation_function)

Creates a latent space transformation block.

This method constructs a latent space module that transforms an input tensor of a specified shape into an output tensor of a desired shape using linear layers and an optional activation function.

Arguments:
  • input_shape (Sequence[int]): The shape of the input tensor, typically represented as a sequence of integers.
  • output_shape (Sequence[int]): The desired shape of the output tensor, specified as a sequence of integers.
  • n_layers (int, optional): The number of linear layers to use in the transformation. Defaults to 1.
  • activation_function (Union[Optional[nn.Module], str], optional): Specifies the activation function to apply after the linear layers. If set to 'same', it will use the instance's predefined activation function. Defaults to None.
Returns:

An instance of the LatentSpaceModule class that performs the specified transformation from input to output shape.