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 )
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.