Configuration Guide
Master Lighter's configuration system in 15 minutes.
Lighter uses Sparkwheel for configuration - a powerful YAML-based system with references, expressions, and object instantiation.
The 5 Essential Symbols
You only need to understand 5 symbols to use Lighter effectively:
1. _target_: Create Objects
Instantiate any Python class from YAML:
Equivalent Python:
Works with any Python class - PyTorch, third-party libraries, or your own code.
Using _args_ for positional arguments:
When you need to pass positional arguments instead of keyword arguments:
model:
_target_: torch.nn.Sequential
_args_:
- _target_: torch.nn.Linear
in_features: 784
out_features: 128
- _target_: torch.nn.ReLU
Equivalent Python:
The _args_ list contains positional arguments passed to the target class. Each item can have its own _target_ for nested instantiation.
Using _mode_ to control instantiation:
Control how _target_ instantiates objects:
model:
# Factory function that returns a model
_target_: project.model_factory.create_model
_mode_: callable # Returns a partial function
model_name: resnet50
num_classes: 10
Available modes:
"default"(default): Normal instantiation -Component(*args, **kwargs)"callable": Returns a partial function -functools.partial(Component, *args, **kwargs)"debug": Runs in debugger -pdb.runcall(Component, *args, **kwargs)
When to use callable mode:
Use _mode_: callable when you need a factory function or lazy instantiation:
data:
train_dataloader:
_target_: torch.utils.data.DataLoader
collate_fn:
_target_: project.collate.custom_collate
_mode_: callable # DataLoader needs the function, not the result
padding_value: 0
Equivalent Python:
from functools import partial
collate_fn = partial(custom_collate, padding_value=0)
dataloader = DataLoader(..., collate_fn=collate_fn)
When to use debug mode:
Use _mode_: debug to debug instantiation issues by entering the debugger when the component is created:
model:
network:
_target_: project.model.ComplexModel
_mode_: debug # Will enter pdb when instantiating
num_layers: 12
hidden_size: 768
This is equivalent to:
Useful when you need to step through the __init__ method to diagnose instantiation errors.
Using _disabled_ to skip instantiation:
Skip instantiation of a component without removing it from config:
trainer:
callbacks:
- _target_: pytorch_lightning.callbacks.EarlyStopping
monitor: val_loss
patience: 3
- _target_: pytorch_lightning.callbacks.ModelCheckpoint
_disabled_: true # This callback is removed from the list
save_top_k: 3
system:
scheduler:
_target_: torch.optim.lr_scheduler.CosineAnnealingLR
_disabled_: true # Disable while debugging optimizer issues
optimizer: "@system::optimizer"
T_max: 100
When _disabled_: true:
- Inline in lists/dicts: Disabled components are removed from the parent structure
- Direct resolution or
@references: ReturnsNone
The config is preserved—re-enable by setting _disabled_: false or removing the key.
For complete details (string values, expressions, use cases), see the Sparkwheel documentation.
2. @: Resolved References (Lazy)
Reference values that are resolved lazily when needed:
model:
network:
_target_: torchvision.models.resnet18
num_classes: 10
optimizer:
_target_: torch.optim.Adam
params: "$@model::network.parameters()" # Resolved lazily
lr: 0.001
What @ does:
- Resolves lazily (when you call resolve(), not when loading config)
- Returns final computed values after instantiation and evaluation
- Gets the actual Python object, so you can call methods on it
3. %: Raw References (Eager)
Copy raw YAML content that is processed eagerly during config merge:
model:
train_metrics:
- _target_: torchmetrics.Accuracy
task: multiclass
num_classes: 10
val_metrics: "%model::train_metrics" # Copies raw YAML
What % does:
- Processes eagerly (during config loading, before instantiation)
- Copies unprocessed YAML definition
- Creates a new instance when later resolved (not shared!)
Critical: Use % for Metrics, Not @
Metrics accumulate state. Using @ shares the same instance between train and val:
# ❌ WRONG - Shares the same metric instance
val_metrics: "@model::train_metrics"
# ✅ CORRECT - Copies config, creates separate instance
val_metrics: "%model::train_metrics"
Why this matters: % copies the raw YAML template, so when each is resolved, you get separate instances. @ would resolve once and share that same object.
4. $: Evaluate Python Expressions
Run Python code in your configs:
# Simple math
lr: "$0.001 * 2" # = 0.002
# Call methods
optimizer:
params: "$@model::network.parameters()"
# Conditionals
batch_size: "$64 if %vars::large_batch else 32"
# List comprehensions
layer_sizes: "$[64 * (2**i) for i in range(4)]" # [64, 128, 256, 512]
# Type conversions
warmup_steps: "$int(%vars::total_steps * 0.1)"
5. ::: Navigate Config Paths
Access nested values using :: separator:
Use in CLI overrides:
The Critical Rule: :: vs .
::navigates config structure.accesses Python attributes/methods
# ❌ WRONG
params: "$@model::network::parameters()" # :: for Python method
# ✅ CORRECT
params: "$@model::network.parameters()" # . for Python method
Common Patterns
Pattern 1: Network → Optimizer
model:
network:
_target_: torchvision.models.resnet50
num_classes: 10
optimizer:
_target_: torch.optim.Adam
params: "$@model::network.parameters()" # Pass network params
lr: 0.001
Pattern 2: Optimizer → Scheduler
model:
optimizer:
_target_: torch.optim.Adam
params: "$@model::network.parameters()"
lr: 0.001
scheduler:
_target_: torch.optim.lr_scheduler.CosineAnnealingLR
optimizer: "@model::optimizer" # Pass optimizer object
T_max: 100
Pattern 3: Reusing Metrics
model:
train_metrics:
- _target_: torchmetrics.Accuracy
task: multiclass
num_classes: 10
- _target_: torchmetrics.F1Score
task: multiclass
num_classes: 10
val_metrics: "%model::train_metrics" # Reuse config
test_metrics: "%model::train_metrics"
Pattern 4: Shared Variables
vars:
num_classes: 10
base_lr: 0.001
batch_size: 32
model:
network:
_target_: torchvision.models.resnet18
num_classes: "%vars::num_classes"
optimizer:
lr: "%vars::base_lr"
data:
train_dataloader:
batch_size: "%vars::batch_size"
Pattern 5: Differential Learning Rates
model:
optimizer:
_target_: torch.optim.SGD
params:
- params: "$@model::network.backbone.parameters()"
lr: 0.0001 # Low LR for pretrained backbone
- params: "$@model::network.head.parameters()"
lr: 0.01 # High LR for new head
momentum: 0.9
Config Structure
Every Lighter config has three main sections:
trainer: # PyTorch Lightning Trainer
_target_: pytorch_lightning.Trainer
max_epochs: 10
accelerator: auto
devices: 1
model: # LightningModule or LighterModule
_target_: your.Module
# ... module arguments ...
data: # LighterDataModule or custom LightningDataModule
_target_: lighter.LighterDataModule
train_dataloader: ...
val_dataloader: ...
Optional Sections
_requires_: # Import Python modules
- "$import torch"
- "$from datetime import datetime"
vars: # Reusable variables
num_classes: 10
lr: 0.001
args: # Stage-specific arguments
fit:
ckpt_path: null
test:
ckpt_path: "checkpoints/best.ckpt"
CLI Overrides
Override any config value from command line:
# Single override
lighter fit config.yaml trainer::max_epochs=100
# Nested values
lighter fit config.yaml model::optimizer::lr=0.001
# Multiple overrides
lighter fit config.yaml \
trainer::max_epochs=100 \
model::optimizer::lr=0.001 \
data::train_dataloader::batch_size=64
Merging Configs
Combine multiple YAML files:
Default Behavior: Merge
Configs merge automatically:
# base.yaml
trainer:
max_epochs: 10
accelerator: auto
# experiment.yaml
trainer:
max_epochs: 100 # Overrides
devices: 4 # Adds
Result: max_epochs=100, accelerator=auto, devices=4
Replace with =
Replace instead of merge:
# experiment.yaml
trainer:
=callbacks: # Replace entire callbacks list
- _target_: pytorch_lightning.callbacks.EarlyStopping
Delete with ~
Remove keys:
# Delete entire key
trainer:
~callbacks: null
# Delete list items by index
trainer:
~callbacks: [1, 3] # Remove items at indices 1 and 3
# Delete dict keys
data:
~test_dataloader: null
Common Pitfalls
❌ Wrong: Using @ for Metrics
✅ Correct: Using % for Metrics
❌ Wrong: Using :: for Python Attributes
✅ Correct: Using . for Python Attributes
❌ Wrong: Missing $ for Expressions
✅ Correct: Using $ for Expressions
Advanced: Conditional Config
vars:
use_pretrained: true
model:
network:
_target_: torchvision.models.resnet18
weights: "$'IMAGENET1K_V2' if %vars::use_pretrained else None"
num_classes: 10
Advanced: Dynamic Imports
_requires_:
- "$import datetime"
- "$from pathlib import Path"
trainer:
logger:
name: "$datetime.datetime.now().strftime('%Y%m%d_%H%M%S')"
Complete Example
_requires_:
- "$import torch"
vars:
num_classes: 10
base_lr: 0.001
max_epochs: 100
trainer:
_target_: pytorch_lightning.Trainer
max_epochs: "%vars::max_epochs"
accelerator: auto
callbacks:
- _target_: pytorch_lightning.callbacks.ModelCheckpoint
monitor: val_loss
mode: min
save_top_k: 3
model:
_target_: lighter.LighterModule
network:
_target_: torchvision.models.resnet18
num_classes: "%vars::num_classes"
criterion:
_target_: torch.nn.CrossEntropyLoss
optimizer:
_target_: torch.optim.Adam
params: "$@model::network.parameters()"
lr: "%vars::base_lr"
scheduler:
_target_: torch.optim.lr_scheduler.CosineAnnealingLR
optimizer: "@model::optimizer"
T_max: "%vars::max_epochs"
train_metrics:
- _target_: torchmetrics.Accuracy
task: multiclass
num_classes: "%vars::num_classes"
val_metrics: "%model::train_metrics"
data:
_target_: lighter.LighterDataModule
train_dataloader:
_target_: torch.utils.data.DataLoader
batch_size: 32
shuffle: true
dataset:
_target_: torchvision.datasets.CIFAR10
root: ./data
train: true
download: true
Quick Reference
| Symbol | Use | Example |
|---|---|---|
_target_ |
Instantiate class | _target_: torch.nn.Linear |
_args_ |
Positional arguments | _args_: [arg1, arg2] |
_mode_ |
Instantiation mode | _mode_: callable |
_disabled_ |
Skip instantiation (removed from parent) | _disabled_: true |
@ |
Resolved reference | @model::optimizer |
% |
Raw reference | %model::train_metrics |
$ |
Python expression | $0.001 * 2 |
:: |
Config path | model::optimizer::lr |
. |
Python attribute | @model::network.parameters() |
= |
Replace operator | =callbacks: |
~ |
Delete operator | ~callbacks: [0, 2] |
Next Steps
- Custom Code Guide - Use your own models/datasets
- Training Guide - Run experiments
- Sparkwheel Docs - Complete reference