| | """ |
| | Autoencoder configuration for Hugging Face Transformers. |
| | """ |
| |
|
| | from dataclasses import dataclass |
| | from typing import Union |
| |
|
| | |
| | try: |
| | from transformers.configuration_utils import PretrainedConfig |
| | except Exception: |
| | from transformers import PretrainedConfig |
| | from typing import List, Optional |
| |
|
| | |
| | try: |
| | from . import __version__ as _pkg_version |
| | except Exception: |
| | _pkg_version = None |
| |
|
| | @dataclass |
| | class BlockConfig: |
| | type: str |
| |
|
| |
|
| | @dataclass |
| | class LinearBlockConfig(BlockConfig): |
| | input_dim: int |
| | output_dim: int |
| | activation: str = "relu" |
| | normalization: Optional[str] = "batch" |
| | dropout_rate: float = 0.0 |
| | use_residual: bool = False |
| | residual_scale: float = 1.0 |
| |
|
| | def __init__(self, input_dim: int, output_dim: int, activation: str = "relu", normalization: Optional[str] = "batch", dropout_rate: float = 0.0, use_residual: bool = False, residual_scale: float = 1.0): |
| | super().__init__(type="linear") |
| | self.input_dim = input_dim |
| | self.output_dim = output_dim |
| | self.activation = activation |
| | self.normalization = normalization |
| | self.dropout_rate = dropout_rate |
| | self.use_residual = use_residual |
| | self.residual_scale = residual_scale |
| |
|
| |
|
| | @dataclass |
| | class AttentionBlockConfig(BlockConfig): |
| | input_dim: int |
| | num_heads: int = 8 |
| | ffn_dim: Optional[int] = None |
| | dropout_rate: float = 0.0 |
| |
|
| | def __init__(self, input_dim: int, num_heads: int = 8, ffn_dim: Optional[int] = None, dropout_rate: float = 0.0): |
| | super().__init__(type="attention") |
| | self.input_dim = input_dim |
| | self.num_heads = num_heads |
| | self.ffn_dim = ffn_dim |
| | self.dropout_rate = dropout_rate |
| |
|
| | @dataclass |
| | class RecurrentBlockConfig(BlockConfig): |
| | input_dim: int |
| | hidden_size: int |
| | num_layers: int = 1 |
| | rnn_type: str = "lstm" |
| | bidirectional: bool = False |
| | dropout_rate: float = 0.0 |
| | output_dim: Optional[int] = None |
| |
|
| | def __init__(self, input_dim: int, hidden_size: int, num_layers: int = 1, rnn_type: str = "lstm", bidirectional: bool = False, dropout_rate: float = 0.0, output_dim: Optional[int] = None): |
| | super().__init__(type="recurrent") |
| | self.input_dim = input_dim |
| | self.hidden_size = hidden_size |
| | self.num_layers = num_layers |
| | self.rnn_type = rnn_type |
| | self.bidirectional = bidirectional |
| | self.dropout_rate = dropout_rate |
| | self.output_dim = output_dim |
| |
|
| |
|
| | @dataclass |
| | class ConvolutionalBlockConfig(BlockConfig): |
| | input_dim: int |
| | output_dim: int |
| | kernel_size: int = 3 |
| | padding: Union[int, str] = "same" |
| | activation: str = "relu" |
| | normalization: Optional[str] = "batch" |
| | dropout_rate: float = 0.0 |
| |
|
| | def __init__(self, input_dim: int, output_dim: int, kernel_size: int = 3, padding: Union[int, str] = "same", activation: str = "relu", normalization: Optional[str] = "batch", dropout_rate: float = 0.0): |
| | super().__init__(type="conv1d") |
| | self.input_dim = input_dim |
| | self.output_dim = output_dim |
| | self.kernel_size = kernel_size |
| | self.padding = padding |
| | self.activation = activation |
| | self.normalization = normalization |
| | self.dropout_rate = dropout_rate |
| |
|
| | @dataclass |
| | class VariationalBlockConfig(BlockConfig): |
| | input_dim: int |
| | latent_dim: int |
| |
|
| | def __init__(self, input_dim: int, latent_dim: int): |
| | super().__init__(type="variational") |
| | self.input_dim = input_dim |
| | self.latent_dim = latent_dim |
| |
|
| |
|
| | class AutoencoderConfig(PretrainedConfig): |
| | """ |
| | Configuration class for Autoencoder models. |
| | |
| | This configuration class stores the configuration of an autoencoder model. It is used to instantiate |
| | an autoencoder model according to the specified arguments, defining the model architecture. |
| | |
| | Args: |
| | input_dim (int, optional): Dimensionality of the input data. Defaults to 784. |
| | hidden_dims (List[int], optional): Legacy: List of hidden layer dims for simple MLP encoder. |
| | encoder_blocks (List[dict], optional): New: List of block configs for encoder. |
| | decoder_blocks (List[dict], optional): New: List of block configs for decoder. |
| | latent_dim (int, optional): Dimensionality of the latent space. Defaults to 64. |
| | activation (str, optional): Default activation for Linear blocks. See supported list below. |
| | dropout_rate (float, optional): Default dropout for Linear blocks. Defaults to 0.1. |
| | use_batch_norm (bool, optional): Default normalization for Linear blocks (batch vs none). Defaults to True. |
| | tie_weights (bool, optional): Whether to tie encoder and decoder weights. Defaults to False. |
| | reconstruction_loss (str, optional): Type of reconstruction loss. Options: "mse", "bce", "l1", |
| | "huber", "smooth_l1", "kl_div", "cosine", "focal", "dice", "tversky", "ssim", "perceptual". |
| | Defaults to "mse". |
| | autoencoder_type (str, optional): Type of autoencoder architecture. Options: "classic", |
| | "variational", "beta_vae", "denoising", "sparse", "contractive", "recurrent". Defaults to "classic". |
| | beta (float, optional): Beta parameter for beta-VAE. Defaults to 1.0. |
| | temperature (float, optional): Temperature parameter for Gumbel softmax or other operations. Defaults to 1.0. |
| | noise_factor (float, optional): Noise factor for denoising autoencoders. Defaults to 0.1. |
| | rnn_type (str, optional): Type of RNN cell for recurrent autoencoders. Options: "lstm", "gru", "rnn". |
| | Defaults to "lstm". |
| | num_layers (int, optional): Number of RNN layers for recurrent autoencoders. Defaults to 2. |
| | bidirectional (bool, optional): Whether to use bidirectional RNN for encoding. Defaults to True. |
| | sequence_length (int, optional): Fixed sequence length. If None, supports variable length sequences. |
| | Defaults to None. |
| | teacher_forcing_ratio (float, optional): Ratio of teacher forcing during training for recurrent decoders. |
| | Defaults to 0.5. |
| | use_learnable_preprocessing (bool, optional): Whether to use learnable preprocessing. Defaults to False. |
| | preprocessing_type (str, optional): Type of learnable preprocessing. Options: "none", "neural_scaler", |
| | "normalizing_flow", "minmax_scaler", "robust_scaler", "yeo_johnson". Defaults to "none". |
| | preprocessing_hidden_dim (int, optional): Hidden dimension for preprocessing networks. Defaults to 64. |
| | preprocessing_num_layers (int, optional): Number of layers in preprocessing networks. Defaults to 2. |
| | learn_inverse_preprocessing (bool, optional): Whether to learn inverse preprocessing for reconstruction. |
| | Defaults to True. |
| | flow_coupling_layers (int, optional): Number of coupling layers for normalizing flows. Defaults to 4. |
| | **kwargs: Additional keyword arguments passed to the parent class. |
| | """ |
| |
|
| | model_type = "autoencoder" |
| |
|
| | def __init__( |
| | self, |
| | input_dim: int = 784, |
| | hidden_dims: List[int] = None, |
| | encoder_blocks: Optional[List[dict]] = None, |
| | decoder_blocks: Optional[List[dict]] = None, |
| | latent_dim: int = 64, |
| | activation: str = "relu", |
| | dropout_rate: float = 0.1, |
| | use_batch_norm: bool = True, |
| | tie_weights: bool = False, |
| | reconstruction_loss: str = "mse", |
| | autoencoder_type: str = "classic", |
| | beta: float = 1.0, |
| | temperature: float = 1.0, |
| | noise_factor: float = 0.1, |
| | |
| | rnn_type: str = "lstm", |
| | num_layers: int = 2, |
| | bidirectional: bool = True, |
| | sequence_length: Optional[int] = None, |
| | teacher_forcing_ratio: float = 0.5, |
| | |
| | use_learnable_preprocessing: bool = False, |
| | preprocessing_type: str = "none", |
| | preprocessing_hidden_dim: int = 64, |
| | preprocessing_num_layers: int = 2, |
| | learn_inverse_preprocessing: bool = True, |
| | flow_coupling_layers: int = 4, |
| | **kwargs, |
| | ): |
| | |
| | if hidden_dims is None: |
| | hidden_dims = [512, 256, 128] |
| |
|
| | |
| | valid_activations = [ |
| | "relu", "tanh", "sigmoid", "leaky_relu", "gelu", "swish", "silu", |
| | "elu", "prelu", "relu6", "hardtanh", "hardsigmoid", "hardswish", |
| | "mish", "softplus", "softsign", "tanhshrink", "threshold" |
| | ] |
| | if activation not in valid_activations: |
| | raise ValueError( |
| | f"`activation` must be one of {valid_activations}, got {activation}." |
| | ) |
| |
|
| | |
| | valid_losses = [ |
| | "mse", "bce", "l1", "huber", "smooth_l1", "kl_div", "cosine", |
| | "focal", "dice", "tversky", "ssim", "perceptual" |
| | ] |
| | if reconstruction_loss not in valid_losses: |
| | raise ValueError( |
| | f"`reconstruction_loss` must be one of {valid_losses}, got {reconstruction_loss}." |
| | ) |
| |
|
| | |
| | valid_types = ["classic", "variational", "beta_vae", "denoising", "sparse", "contractive", "recurrent"] |
| | if autoencoder_type not in valid_types: |
| | raise ValueError( |
| | f"`autoencoder_type` must be one of {valid_types}, got {autoencoder_type}." |
| | ) |
| |
|
| | |
| | valid_rnn_types = ["lstm", "gru", "rnn"] |
| | if rnn_type not in valid_rnn_types: |
| | raise ValueError( |
| | f"`rnn_type` must be one of {valid_rnn_types}, got {rnn_type}." |
| | ) |
| |
|
| | if not (0.0 <= dropout_rate <= 1.0): |
| | raise ValueError(f"`dropout_rate` must be between 0.0 and 1.0, got {dropout_rate}.") |
| |
|
| | if input_dim <= 0: |
| | raise ValueError(f"`input_dim` must be positive, got {input_dim}.") |
| |
|
| | if latent_dim <= 0: |
| | raise ValueError(f"`latent_dim` must be positive, got {latent_dim}.") |
| |
|
| | if not all(dim > 0 for dim in hidden_dims): |
| | raise ValueError("All dimensions in `hidden_dims` must be positive.") |
| |
|
| | if beta <= 0: |
| | raise ValueError(f"`beta` must be positive, got {beta}.") |
| |
|
| | if num_layers <= 0: |
| | raise ValueError(f"`num_layers` must be positive, got {num_layers}.") |
| |
|
| | if not (0.0 <= teacher_forcing_ratio <= 1.0): |
| | raise ValueError(f"`teacher_forcing_ratio` must be between 0.0 and 1.0, got {teacher_forcing_ratio}.") |
| |
|
| | if sequence_length is not None and sequence_length <= 0: |
| | raise ValueError(f"`sequence_length` must be positive when specified, got {sequence_length}.") |
| |
|
| | |
| | valid_preprocessing = [ |
| | "none", |
| | "neural_scaler", |
| | "normalizing_flow", |
| | "minmax_scaler", |
| | "robust_scaler", |
| | "yeo_johnson", |
| | ] |
| | if preprocessing_type not in valid_preprocessing: |
| | raise ValueError( |
| | f"`preprocessing_type` must be one of {valid_preprocessing}, got {preprocessing_type}." |
| | ) |
| |
|
| | if preprocessing_hidden_dim <= 0: |
| | raise ValueError(f"`preprocessing_hidden_dim` must be positive, got {preprocessing_hidden_dim}.") |
| |
|
| | if preprocessing_num_layers <= 0: |
| | raise ValueError(f"`preprocessing_num_layers` must be positive, got {preprocessing_num_layers}.") |
| |
|
| | if flow_coupling_layers <= 0: |
| | raise ValueError(f"`flow_coupling_layers` must be positive, got {flow_coupling_layers}.") |
| |
|
| | |
| | self.input_dim = input_dim |
| | self.hidden_dims = hidden_dims |
| | self.encoder_blocks = encoder_blocks |
| | self.decoder_blocks = decoder_blocks |
| | self.latent_dim = latent_dim |
| | self.activation = activation |
| | self.dropout_rate = dropout_rate |
| | self.use_batch_norm = use_batch_norm |
| | self.tie_weights = tie_weights |
| | self.reconstruction_loss = reconstruction_loss |
| | self.autoencoder_type = autoencoder_type |
| | self.beta = beta |
| | self.temperature = temperature |
| | self.noise_factor = noise_factor |
| | self.rnn_type = rnn_type |
| | self.num_layers = num_layers |
| | self.bidirectional = bidirectional |
| | self.sequence_length = sequence_length |
| | self.teacher_forcing_ratio = teacher_forcing_ratio |
| | self.use_learnable_preprocessing = use_learnable_preprocessing |
| | self.preprocessing_type = preprocessing_type |
| | self.preprocessing_hidden_dim = preprocessing_hidden_dim |
| | self.preprocessing_num_layers = preprocessing_num_layers |
| | self.learn_inverse_preprocessing = learn_inverse_preprocessing |
| | self.flow_coupling_layers = flow_coupling_layers |
| |
|
| | |
| | super().__init__(**kwargs) |
| |
|
| | @property |
| | def decoder_dims(self) -> List[int]: |
| | """Get decoder dimensions (reverse of encoder hidden dims).""" |
| | return list(reversed(self.hidden_dims)) |
| |
|
| | @property |
| | def has_block_lists(self) -> bool: |
| | """Whether explicit encoder/decoder block configs are provided.""" |
| | return (self.encoder_blocks is not None) or (self.decoder_blocks is not None) |
| |
|
| | @property |
| | def is_variational(self) -> bool: |
| | """Check if this is a variational autoencoder.""" |
| | return self.autoencoder_type in ["variational", "beta_vae"] |
| |
|
| | @property |
| | def is_denoising(self) -> bool: |
| | """Check if this is a denoising autoencoder.""" |
| | return self.autoencoder_type == "denoising" |
| |
|
| | @property |
| | def is_sparse(self) -> bool: |
| | """Check if this is a sparse autoencoder.""" |
| | return self.autoencoder_type == "sparse" |
| |
|
| | @property |
| | def is_contractive(self) -> bool: |
| | """Check if this is a contractive autoencoder.""" |
| | return self.autoencoder_type == "contractive" |
| |
|
| | @property |
| | def is_recurrent(self) -> bool: |
| | """Check if this is a recurrent autoencoder.""" |
| | return self.autoencoder_type == "recurrent" |
| |
|
| | @property |
| | def rnn_hidden_size(self) -> int: |
| | """Get the RNN hidden size (same as latent_dim for recurrent AE).""" |
| | return self.latent_dim |
| |
|
| | @property |
| | def rnn_output_size(self) -> int: |
| | """Get the RNN output size considering bidirectionality.""" |
| | return self.latent_dim * (2 if self.bidirectional else 1) |
| |
|
| | @property |
| | def has_preprocessing(self) -> bool: |
| | """Check if learnable preprocessing is enabled.""" |
| | return self.use_learnable_preprocessing and self.preprocessing_type != "none" |
| |
|
| | @property |
| | def is_neural_scaler(self) -> bool: |
| | """Check if using neural scaler preprocessing.""" |
| | return self.preprocessing_type == "neural_scaler" |
| |
|
| | @property |
| | def is_normalizing_flow(self) -> bool: |
| | """Check if using normalizing flow preprocessing.""" |
| | return self.preprocessing_type == "normalizing_flow" |
| |
|
| | @property |
| | def is_minmax_scaler(self) -> bool: |
| | """Check if using learnable MinMax scaler preprocessing.""" |
| | return self.preprocessing_type == "minmax_scaler" |
| |
|
| | @property |
| | def is_robust_scaler(self) -> bool: |
| | """Check if using learnable Robust scaler preprocessing.""" |
| | return self.preprocessing_type == "robust_scaler" |
| |
|
| | @property |
| | def is_yeo_johnson(self) -> bool: |
| | """Check if using learnable Yeo-Johnson power transform preprocessing.""" |
| | return self.preprocessing_type == "yeo_johnson" |
| |
|
| | def to_dict(self): |
| | """ |
| | Serializes this instance to a Python dictionary. |
| | """ |
| | output = super().to_dict() |
| | return output |
| |
|