FAQ — "How do I…?"¶
Quick answers with links into the guide. Use Ctrl+F / Cmd+F to find your question.
Getting started¶
How do I install SR-Forge?
pip install srforge after installing PyTorch — Installation.
How do I start a new project?
srforge init scaffolds train.py, benchmark.py, and configs — Scaffold a new project.
Can I try it without my own data?
Yes — run the bundled synthetic example: python examples/minimal_sr/train.py. No GPU, no data, runs in seconds.
Where do I start reading? Anatomy of a Training (why each piece exists), then Core Concepts (5-min glossary), then follow the guide order in Getting Started → What's next.
I'm new to deep learning — what does a training even need? Exactly what Anatomy of a Training answers: 13 universal ingredients (data, loss, optimizer, loop, …), each explained and mapped to its SR-Forge class.
Data¶
How do I load my dataset?
One folder per scene → LazyDataset. Explicit file lists → LazyConfigDataset. Anything else → write a Dataset subclass (implement __getitem__ + __len__, return Entry objects). See the decision table.
What shape should my tensors be?
Natural shapes, no batch dimension: a single image is [C, H, W]. Batching is added by collation — never add it yourself.
How do I normalize / augment my data? Add transforms — deterministic preprocessing on the dataset (cacheable), random augmentations in the model pipeline. See Where Do Transforms Run?
How do I cache expensive preprocessing?
dataset.cache("/path") or cache_dir: in YAML — Caching preprocessed entries. Wrap the cached dataset for uncached augmentations — layered caching.
How do I split images into patches? PatchedDataset (or MultiSpectralPatchedDataset for per-band resolutions).
How do I take a subset / shuffle / filter a dataset?
ds.take(100), ds.shuffle(seed=42), ds.filter(pred) — SubsetDataset.
How do I combine several datasets?
ds_a + ds_b or ConcatDataset([...]) — each dataset needs a name — ConcatDataset.
How do I handle graph data (point clouds, meshes)? Use GraphEntry — PyG batching is selected automatically.
Components & wiring¶
What is IO binding, in one sentence? A mapping from your component's parameter names to Entry field names, so the same code works with any data layout — The Big Idea, Step by Step.
How do I connect a model to my Entry fields?
model.set_io({"inputs": {param: field}, "outputs": field}) in Python, or an io: block in YAML — IO Binding → Model.
Should I write a DataTransform or an EntryTransform? Need to add/remove/rename fields or inspect the Entry? EntryTransform. Otherwise DataTransform — Decision Tree.
Why does my transform receive individual tensors instead of my dict?
Type annotations control container recursion: x: torch.Tensor recurses into dicts, x: dict passes the whole thing — How Type Annotations Control Container Handling.
How do I chain several models/transforms into one pipeline?
SequentialModel with the flow DSL: "image -> encoder -> features".
How do I train a GAN?
GANModel wraps generator + discriminator; GANTrainingRunner alternates the updates.
How do I load pretrained weights from a W&B run?
Wrap your model in load_weights_from_wandb as the _target — Loading pretrained weights.
Losses & metrics¶
How do I use multiple losses with different weights?
LossCombiner with a weight: per loss. Weight 0.0 tracks a metric without training on it.
How do I write a custom loss?
Override pointwise(x, y) returning a per-element map — masking and reduction are automatic — Extending → Loss.
How do I mask invalid pixels (clouds, borders, no-data)?
Bind y_mask to your mask field — Masking.
How do I change the loss weights at a specific epoch?
LossScheduler — a {epoch: loss} schedule.
How do I train with predicted uncertainty (heteroscedastic NLL)?
UncertaintyLoss + Regularizer — the data term and the +log_var penalty are separate, composable losses.
How do I evaluate with shift-tolerant metrics (cPSNR-style)? CorrectedLoss — wraps any base metric with the shift + brightness correction.
What does loss(entry) return?
A MetricScores object. scores.total_weighted().mean().backward() is the backprop chain.
Training¶
What does the training loop actually do each epoch? Trainers & Runners — trainer orchestrates, runners execute, hooks react.
How do I add a progress bar / logging / checkpointing?
They're hooks — add them to the hooks: list of the runner or trainer in YAML — Configuration → Hooks.
How do I write a custom hook (e.g. log something every epoch)?
Subclass Hook, decorate a method with @hooks_into("on_epoch_end") — Extending → Hook.
How do I clip gradients?
Add the GradientClip hook to the training runner's hooks: list.
How do I stop training early?
stop_condition: on the trainer (e.g. ValidationLossDidNotImprove) — Stop Conditions.
How do I resume a crashed run?
Set run_id: + resume: allow on the tracker; resume_from_checkpoint() restores everything — Resuming Training.
How do I use mixed precision / multi-GPU / gradient accumulation?
All config switches: system.mixed_precision, system.device: [0, 1], training.gradient_accumulation_steps — see the scaffold's train-cfg.yaml.
I see Observer is deprecated warnings — what do I do?
Move each observer into the matching hooks: list — the conversion is mechanical — Porting an Observer to a Hook.
Configuration (YAML)¶
What's the _target / params / io pattern?
_target picks the class, params are constructor kwargs, io is the field binding — Configuration.
What's the difference between ${path} and ${ref:path}?
${path} copies the raw config value; ${ref:path} references the already-instantiated object — Object References.
How do I override a config value from the command line?
Hydra syntax: python train.py training.batch_size=32 — CLI Overrides.
How do I use my own class in YAML?
Give its import path as _target: my_project.models.MyModel — Extending SR-Forge.
Why did I get unexpected keyword argument when adding cache_dir to my custom dataset?
Your subclass must accept all framework kwargs — add **kwargs and forward it: super().__init__(**kwargs) — Extending → Dataset.
Debugging¶
Which sample caused the error?
Set the name field on every Entry — error messages include it.
KeyError: field 'x' not found —
your IO binding maps a parameter to an Entry field that doesn't exist at that point in the pipeline. Check the binding and what fields the Entry actually has (entry.keys()). Rule: if you map it, it must exist.
KeyError: attempted to overwrite existing entry fields —
model outputs can't overwrite existing fields — pick a different outputs: name — Field Overwrite Protection.
TypeError at class definition mentioning @audit_subclasses —
your Loss/Dataset subclass drops or omits framework kwargs. Accept **kwargs and forward to super().__init__(**kwargs) — Extending → Loss.
My W&B run is empty after Ctrl-C — fixed in v0.15.0 — the interrupt handler now flushes the tracker before exiting. Update if you're on an older version.
How do I run without W&B?
tracker._target: srforge.tracking.NullTracker — NullTracker.