Autoencoder for Hugging Face Transformers (Block-based)

A flexible, production-grade Autoencoder implementation built to fit naturally into the Transformers ecosystem. It supports a new block-based architecture with ready-to-use templates for classic MLP, VAE/beta-VAE, Transformer, Recurrent, Convolutional, mixed hybrids, and learnable preprocessing.

Key features

  • Block-based architecture: Linear, Attention, Recurrent (LSTM/GRU), Convolutional, Variational blocks
  • Class-based configuration presets in template.py for quick starts
  • Variational and beta-VAE variants (KL-controlled)
  • Learnable preprocessing and inverse transforms
  • Hugging Face-compatible config/model API and from_pretrained/save_pretrained

Install and load from the Hub (code repo)

from huggingface_hub import snapshot_download
import sys, torch

repo_dir = snapshot_download(
    repo_id="amaye15/autoencoder",
    repo_type="model",
    allow_patterns=["*.py", "config.json", "*.safetensors"],
)
sys.path.append(repo_dir)

from modeling_autoencoder import AutoencoderForReconstruction
model = AutoencoderForReconstruction.from_pretrained(repo_dir)

x = torch.randn(8, 20)
out = model(input_values=x)
print("latent:", out.last_hidden_state.shape, "reconstructed:", out.reconstructed.shape)

Quickstart with class-based templates

from modeling_autoencoder import AutoencoderModel
from template import ClassicAutoencoderConfig

cfg = ClassicAutoencoderConfig(input_dim=784, latent_dim=64)
model = AutoencoderModel(cfg)

x = torch.randn(4, 784)
out = model(x, return_dict=True)
print(out.last_hidden_state.shape, out.reconstructed.shape)

Available presets (template.py)

  • ClassicAutoencoderConfig: Dense MLP AE
  • VariationalAutoencoderConfig: VAE with KL regularization
  • BetaVariationalAutoencoderConfig: beta-VAE (beta > 1)
  • TransformerAutoencoderConfig: Attention-based encoder for sequences
  • RecurrentAutoencoderConfig: LSTM/GRU encoder for sequences
  • ConvolutionalAutoencoderConfig: 1D Conv encoder for sequences
  • ConvAttentionAutoencoderConfig: Mixed Conv + Attention encoder
  • LinearRecurrentAutoencoderConfig: Linear down-projection + RNN
  • PreprocessedAutoencoderConfig: MLP AE with learnable preprocessing

Block-based architecture

The autoencoder uses a modular block system where you define encoder_blocks and decoder_blocks as lists of dictionaries. Each block dict specifies its type and parameters.

Available block types

LinearBlock

Dense layer with optional normalization, activation, dropout, and residual connections.

{
    "type": "linear",
    "input_dim": 256,
    "output_dim": 128,
    "activation": "relu",           # relu, gelu, tanh, sigmoid, etc.
    "normalization": "batch",       # batch, layer, group, instance, none
    "dropout_rate": 0.1,
    "use_residual": False,          # adds skip connection if input_dim == output_dim
    "residual_scale": 1.0
}

AttentionBlock

Multi-head self-attention with feed-forward network. Works with 2D (B, D) or 3D (B, T, D) inputs.

{
    "type": "attention",
    "input_dim": 128,
    "num_heads": 8,
    "ffn_dim": 512,                 # if None, defaults to 4 * input_dim
    "dropout_rate": 0.1
}

RecurrentBlock

LSTM, GRU, or vanilla RNN encoder. Outputs final hidden state or all timesteps.

{
    "type": "recurrent",
    "input_dim": 64,
    "hidden_size": 128,
    "num_layers": 2,
    "rnn_type": "lstm",             # lstm, gru, rnn
    "bidirectional": True,
    "dropout_rate": 0.1,
    "output_dim": 128               # final output dimension
}

ConvolutionalBlock

1D convolution for sequence data. Expects 3D input (B, T, D).

{
    "type": "conv1d",
    "input_dim": 64,                # input channels
    "output_dim": 128,              # output channels
    "kernel_size": 3,
    "padding": "same",              # "same" or integer
    "activation": "relu",
    "normalization": "batch",
    "dropout_rate": 0.1
}

VariationalBlock

Produces mu and logvar for VAE reparameterization. Used internally by the model when autoencoder_type="variational".

{
    "type": "variational",
    "input_dim": 128,
    "latent_dim": 64
}

Custom configuration examples

Mixed architecture (Conv + Attention + Linear)

from configuration_autoencoder import AutoencoderConfig

enc = [
    # 1D convolution for local patterns
    {"type": "conv1d", "input_dim": 64, "output_dim": 128, "kernel_size": 3, "padding": "same", "activation": "relu"},
    {"type": "conv1d", "input_dim": 128, "output_dim": 128, "kernel_size": 3, "padding": "same", "activation": "relu"},

    # Self-attention for global dependencies
    {"type": "attention", "input_dim": 128, "num_heads": 8, "ffn_dim": 512, "dropout_rate": 0.1},

    # Final linear projection
    {"type": "linear", "input_dim": 128, "output_dim": 64, "activation": "relu", "normalization": "batch"}
]

dec = [
    {"type": "linear", "input_dim": 32, "output_dim": 64, "activation": "relu", "normalization": "batch"},
    {"type": "linear", "input_dim": 64, "output_dim": 128, "activation": "relu", "normalization": "batch"},
    {"type": "linear", "input_dim": 128, "output_dim": 64, "activation": "identity", "normalization": "none"}
]

cfg = AutoencoderConfig(
    input_dim=64,
    latent_dim=32,
    autoencoder_type="classic",
    encoder_blocks=enc,
    decoder_blocks=dec
)

Hierarchical encoder (multiple scales)

enc = [
    # Local features
    {"type": "linear", "input_dim": 784, "output_dim": 512, "activation": "relu", "normalization": "batch"},
    {"type": "linear", "input_dim": 512, "output_dim": 256, "activation": "relu", "normalization": "batch"},

    # Mid-level features with residual
    {"type": "linear", "input_dim": 256, "output_dim": 256, "activation": "relu", "normalization": "batch", "use_residual": True},
    {"type": "linear", "input_dim": 256, "output_dim": 256, "activation": "relu", "normalization": "batch", "use_residual": True},

    # High-level features
    {"type": "linear", "input_dim": 256, "output_dim": 128, "activation": "relu", "normalization": "batch"},
    {"type": "linear", "input_dim": 128, "output_dim": 64, "activation": "relu", "normalization": "batch"}
]

Sequence-to-sequence with recurrent encoder

enc = [
    {"type": "recurrent", "input_dim": 100, "hidden_size": 128, "num_layers": 2, "rnn_type": "lstm", "bidirectional": True, "output_dim": 256},
    {"type": "linear", "input_dim": 256, "output_dim": 128, "activation": "tanh", "normalization": "layer"}
]

dec = [
    {"type": "linear", "input_dim": 64, "output_dim": 128, "activation": "tanh", "normalization": "layer"},
    {"type": "linear", "input_dim": 128, "output_dim": 100, "activation": "identity", "normalization": "none"}
]

Input shape handling

  • 2D inputs (B, D): Work with Linear blocks directly. Attention/Recurrent/Conv blocks treat as (B, 1, D)
  • 3D inputs (B, T, D): Work with all block types. Linear blocks operate per-timestep
  • Output shapes: Decoder typically outputs same shape as input. For sequence models, final shape depends on decoder architecture

Configuration (configuration_autoencoder.py)

AutoencoderConfig is the core configuration class. Important fields:

  • input_dim: feature dimension (D)
  • latent_dim: latent size
  • encoder_blocks, decoder_blocks: block lists (see block types above)
  • activation, dropout_rate, use_batch_norm: defaults used by some presets
  • autoencoder_type: classic | variational | beta_vae | denoising | sparse | contractive | recurrent
  • Reconstruction losses: mse | bce | l1 | huber | smooth_l1 | kl_div | cosine | focal | dice | tversky | ssim | perceptual
  • Preprocessing: use_learnable_preprocessing, preprocessing_type, learn_inverse_preprocessing

Example:

from configuration_autoencoder import AutoencoderConfig
cfg = AutoencoderConfig(
    input_dim=128,
    latent_dim=32,
    autoencoder_type="variational",
    encoder_blocks=[{"type": "linear", "input_dim": 128, "output_dim": 64, "activation": "relu"}],
    decoder_blocks=[{"type": "linear", "input_dim": 32, "output_dim": 128, "activation": "identity", "normalization": "none"}],
)

Models (modeling_autoencoder.py)

Main classes:

  • AutoencoderModel: core module exposing forward that returns last_hidden_state (latent) and reconstructed
  • AutoencoderForReconstruction: HF-compatible model wrapper with from_pretrained/save_pretrained

Forward usage:

from modeling_autoencoder import AutoencoderModel
x = torch.randn(8, 20)
out = model(x, return_dict=True)
print(out.last_hidden_state.shape, out.reconstructed.shape)

Variational behavior

If cfg.autoencoder_type == "variational" or "beta_vae":

  • The model uses an internal VariationalBlock to compute mu and logvar
  • Samples z during training; uses mu during eval
  • KL term available via model._mu/_logvar (exposed in hidden_states when requested)
out = model(x, return_dict=True, output_hidden_states=True)
latent, mu, logvar = out.hidden_states

Preprocessing (preprocessing.py)

  • PreprocessingBlock wraps LearnablePreprocessor and can be placed before/after the core encoder/decoder
  • When enabled via config.use_learnable_preprocessing, the model constructs two blocks: pre (forward) and post (inverse)
  • The block tracks reg_loss, which is added to preprocessing_loss in the model output
from template import PreprocessedAutoencoderConfig
cfg = PreprocessedAutoencoderConfig(input_dim=64, latent_dim=32, preprocessing_type="neural_scaler")
model = AutoencoderModel(cfg)

Utilities (utils.py)

Common helpers:

  • _get_activation(name)
  • _get_norm(name, num_groups=None)
  • _flatten_3d_to_2d(x), _maybe_restore_3d(x, ref)

Training examples

Basic MSE reconstruction

from modeling_autoencoder import AutoencoderModel
from template import ClassicAutoencoderConfig

cfg = ClassicAutoencoderConfig(input_dim=784, latent_dim=64)
model = AutoencoderModel(cfg)
opt = torch.optim.Adam(model.parameters(), lr=1e-3)

for x in dataloader:  # x: (B, 784)
    out = model(x, return_dict=True)
    loss = torch.nn.functional.mse_loss(out.reconstructed, x)
    loss.backward(); opt.step(); opt.zero_grad()

VAE with KL term

from template import VariationalAutoencoderConfig
cfg = VariationalAutoencoderConfig(input_dim=784, latent_dim=32)
model = AutoencoderModel(cfg)

for x in dataloader:
    out = model(x, return_dict=True, output_hidden_states=True)
    recon = torch.nn.functional.mse_loss(out.reconstructed, x)
    _, mu, logvar = out.hidden_states
    kl = -0.5 * torch.mean(1 + logvar - mu.pow(2) - logvar.exp())
    loss = recon + cfg.beta * kl
    loss.backward(); opt.step(); opt.zero_grad()

Sequence reconstruction (Conv + Attention)

from template import ConvAttentionAutoencoderConfig
cfg = ConvAttentionAutoencoderConfig(input_dim=64, latent_dim=64)
model = AutoencoderModel(cfg)

x = torch.randn(8, 50, 64)  # (B, T, D)
out = model(x, return_dict=True)

End-to-end saving/loading

from modeling_autoencoder import AutoencoderForReconstruction

model.save_pretrained("./my_ae")
reloaded = AutoencoderForReconstruction.from_pretrained("./my_ae")

Troubleshooting

  • Check that block input_dim/output_dim align across adjacent blocks
  • For attention/recurrent/conv blocks, prefer 3D inputs (B, T, D). 2D inputs are coerced to (B, 1, D)
  • For variational/beta-VAE, ensure latent_dim is set; KL term available via hidden states
  • When preprocessing is enabled, preprocessing_loss is included in the output for logging/regularization

Full AutoencoderConfig reference

Below is a comprehensive reference for all fields in configuration_autoencoder.AutoencoderConfig. Some fields are primarily used by presets or advanced features but are documented here for completeness.

  • input_dim (int, default=784): Input feature dimension D. For sequences, D is per-timestep feature size.
  • hidden_dims (List[int], default=[512,256,128]): Legacy convenience list for simple MLPs. Prefer encoder_blocks.
  • encoder_blocks (List[dict] | None): Block list for encoder. See Block-based architecture for block schemas.
  • decoder_blocks (List[dict] | None): Block list for decoder. If omitted, model may derive a simple decoder from hidden_dims.
  • latent_dim (int, default=64): Latent space dimension.
  • activation (str, default="relu"): Default activation for Linear blocks when using legacy paths or presets.
  • dropout_rate (float, default=0.1): Default dropout used in presets and some layers.
  • use_batch_norm (bool, default=True): Default normalization flag used in presets ("batch" if True, else "none").
  • tie_weights (bool, default=False): If True, share/tie encoder and decoder weights (feature not always active depending on architecture).
  • reconstruction_loss (str, default="mse"): Which loss to use in AutoencoderForReconstruction. One of:
    • "mse", "bce", "l1", "huber", "smooth_l1", "kl_div", "cosine", "focal", "dice", "tversky", "ssim", "perceptual".
  • autoencoder_type (str, default="classic"): Architecture variant. One of:
    • "classic", "variational", "beta_vae", "denoising", "sparse", "contractive", "recurrent".
  • beta (float, default=1.0): KL weight for VAE/beta-VAE.
  • temperature (float, default=1.0): Reserved for temperature-based operations.
  • noise_factor (float, default=0.1): Denoising strength used by Denoising variants.
  • rnn_type (str, default="lstm"): For recurrent variants. One of: "lstm", "gru", "rnn".
  • num_layers (int, default=2): Number of RNN layers for recurrent variants.
  • bidirectional (bool, default=True): Whether RNN is bidirectional in recurrent variants.
  • sequence_length (int | None, default=None): Optional fixed sequence length; if None, variable length is supported.
  • teacher_forcing_ratio (float, default=0.5): For recurrent decoders that use teacher forcing.
  • use_learnable_preprocessing (bool, default=False): Enable learnable preprocessing.
  • preprocessing_type (str, default="none"): One of: "none", "neural_scaler", "normalizing_flow", "minmax_scaler", "robust_scaler", "yeo_johnson".
  • preprocessing_hidden_dim (int, default=64): Hidden size for preprocessing networks.
  • preprocessing_num_layers (int, default=2): Number of layers for preprocessing networks.
  • learn_inverse_preprocessing (bool, default=True): Whether to learn inverse transform for reconstruction.
  • flow_coupling_layers (int, default=4): Number of coupling layers for normalizing flows.

Derived helpers and flags:

  • has_block_lists: True if either encoder_blocks or decoder_blocks is provided.
  • is_variational: True if autoencoder_type in {"variational", "beta_vae"}.
  • is_denoising, is_sparse, is_contractive, is_recurrent: Variant flags.
  • has_preprocessing: True if preprocessing enabled and type != "none".

Validation notes:

  • activation must be one of the supported list in configuration_autoencoder.py
  • reconstruction_loss must be one of the supported list
  • Many numeric parameters are validated to be positive or within [0,1]

Training with Hugging Face Trainer

The AutoencoderForReconstruction model computes reconstruction loss internally using config.reconstruction_loss. For VAEs/beta-VAEs, it adds the KL term scaled by config.beta. You can plug it directly into transformers.Trainer.

from transformers import Trainer, TrainingArguments
from modeling_autoencoder import AutoencoderForReconstruction
from template import ClassicAutoencoderConfig
import torch
from torch.utils.data import Dataset

# 1) Config and model
cfg = ClassicAutoencoderConfig(input_dim=64, latent_dim=16)
model = AutoencoderForReconstruction(cfg)

# 2) Dummy dataset (replace with your own)
class ToyAEDataset(Dataset):
    def __init__(self, n=1024, d=64):
        self.x = torch.randn(n, d)
    def __len__(self):
        return self.x.size(0)
    def __getitem__(self, idx):
        xi = self.x[idx]
        return {"input_values": xi, "labels": xi}

train_ds = ToyAEDataset()

# 3) TrainingArguments
args = TrainingArguments(
    output_dir="./ae-trainer",
    per_device_train_batch_size=64,
    learning_rate=1e-3,
    num_train_epochs=3,
    logging_steps=50,
    save_steps=200,
    report_to=[],  # disable wandb if not configured
)

# 4) Trainer
trainer = Trainer(
    model=model,
    args=args,
    train_dataset=train_ds,
)

# 5) Train
trainer.train()

# 6) Use the model
x = torch.randn(4, 64)
out = model(input_values=x, return_dict=True)
print(out.last_hidden_state.shape, out.reconstructed.shape)

Notes:

  • The dataset must yield dicts with "input_values" and optionally "labels"; if labels are missing, the model uses input as the target.
  • For sequence inputs, shape is (B, T, D). For simple vectors, (B, D).
  • Set cfg.reconstruction_loss to e.g. "bce" to switch the internal loss (the decoder head applies sigmoid when BCE is used).
  • For VAE/beta-VAE, use VariationalAutoencoderConfig/BetaVariationalAutoencoderConfig.

Example using AutoencoderConfig directly

Below shows how to define a configuration purely with block dicts using AutoencoderConfig, without the template classes.

from configuration_autoencoder import AutoencoderConfig
from modeling_autoencoder import AutoencoderModel
import torch

# Encoder: Linear -> Attention -> Linear
enc = [
    {"type": "linear", "input_dim": 128, "output_dim": 128, "activation": "relu", "normalization": "batch", "dropout_rate": 0.1},
    {"type": "attention", "input_dim": 128, "num_heads": 4, "ffn_dim": 512, "dropout_rate": 0.1},
    {"type": "linear", "input_dim": 128, "output_dim": 64, "activation": "relu", "normalization": "batch"},
]

# Decoder: Linear -> Linear (final identity)
dec = [
    {"type": "linear", "input_dim": 32, "output_dim": 64, "activation": "relu", "normalization": "batch"},
    {"type": "linear", "input_dim": 64, "output_dim": 128, "activation": "identity", "normalization": "none"},
]

cfg = AutoencoderConfig(
    input_dim=128,
    latent_dim=32,
    encoder_blocks=enc,
    decoder_blocks=dec,
    autoencoder_type="classic",
)

model = AutoencoderModel(cfg)
x = torch.randn(4, 128)
out = model(x, return_dict=True)
print(out.last_hidden_state.shape, out.reconstructed.shape)

For a variational model, set autoencoder_type="variational" and the model will internally use a VariationalBlock for mu/logvar and sampling.

Learnable preprocessing

Enable learnable preprocessing and its inverse with the PreprocessedAutoencoderConfig class or via flags.

from template import PreprocessedAutoencoderConfig
cfg = PreprocessedAutoencoderConfig(input_dim=64, latent_dim=32, preprocessing_type="neural_scaler")

Supported preprocessing_type values include: "neural_scaler", "normalizing_flow", "minmax_scaler", "robust_scaler", "yeo_johnson".

Saving and loading

from modeling_autoencoder import AutoencoderForReconstruction

# Save
model.save_pretrained("./my_ae")
# Load
reloaded = AutoencoderForReconstruction.from_pretrained("./my_ae")

Reference

Core modules:

  • configuration_autoencoder.AutoencoderConfig
  • modeling_autoencoder.AutoencoderModel, AutoencoderForReconstruction
  • blocks: BlockFactory, BlockSequence, Linear/Attention/Recurrent/Convolutional/Variational blocks
  • preprocessing: PreprocessingBlock (learnable preprocessing wrapper)
  • template: class-based presets listed above

License

Apache-2.0 (see LICENSE)

Downloads last month
50
Safetensors
Model size
6.38k params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support