Skip to content
SR-Forge

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

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 _targetLoading 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 objectObject References.

How do I override a config value from the command line? Hydra syntax: python train.py training.batch_size=32CLI Overrides.

How do I use my own class in YAML? Give its import path as _target: my_project.models.MyModelExtending 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.NullTrackerNullTracker.