Troubleshooting¶
The problems that come up first, and what to do about them.
Coordinates and targets¶
The fit is poor or the loss does not move
Coordinates must lie in \([-1, 1]\) on every axis. The coordinate datasets generate them that way, and FUTON's bases and the hash and feature grids are all defined on that domain. Do not pre-normalize to \([0, 1]\). Targets from the datasets are in \([-1, 1]\) too (occupancy in \(\{-1, 1\}\)), which is why the benchmark models end in output_activation=torch.tanh and why the default loss reports PSNR for that range.
ValueError: radius must be >= 1 and num_components >= 2 * radius
A local basis (triangle, lanczos) needs at least 2 * radius components per axis: 2 for the triangle, 6 for Lanczos-3. With num_components=[H // 2, W // 2] this is never an issue for real images; it is for tiny test inputs.
grid_size on a dataset and subsample together
ImageCoordinateDataset(image, grid_size=...) evaluates a model on another grid than the image's, for example a finer one, and cannot subsample; it is for evaluation.
Memory¶
CUDA out of memory during evaluation
Pass chunk_size to inro.train, inro.evaluate or inro.chunked_inference; the occupancy benchmark evaluates \(256^3\) volumes with chunk_size=262144. In inro.nerf.train, lower num_rays or max_samples_per_ray; in inro.nerf.evaluate and render_image, pass chunk_size (rays per pass).
CUDA out of memory during training
Draw fewer coordinates per step with subsample (a fraction) or max_samples (a count); the benchmarks train on the whole image and on 262,144 voxels per step.
Backends¶
NerfAcc: No CUDA toolkit found. NerfAcc will be disabled.
nerfacc builds its CUDA extension on first use and needs nvcc for that. Without it, inro.nerf.create_renderer() selects the PyTorch renderer, which produces the same renders more slowly; training still works. Install a CUDA toolkit matching your PyTorch build to use nerfacc.
Data and extras¶
ModuleNotFoundError: trimesh (or mcubes, open3d)
Meshes as occupancy volumes, mesh export and offscreen rendering need the 3d extra: pip install -e ".[3d]". Point clouds in .xyz format load without it.
No .png from OccupancyCoordinateDataset.save
It renders offscreen with Open3D, which needs EGL and a GPU driver but no display. Where the renderer cannot start, save warns and writes the mesh alone.
LPIPS downloads weights on first use
inro.lpips loads the VGG (or AlexNet) backbone through torchmetrics, which fetches the weights once. On a machine without internet access, run one evaluation on a connected one first, with the same cache directory.
Experiments¶
A run is skipped with \"holds a run of a different setup\"
Runs are keyed by model name inside the log directory. After changing a model's entry in a config, pass --overwrite to rerun it in place, or give the variant its own name or --log-dir.
A model diverges
Learning rates in the configs come from the grid {3e-1, 1e-1, 3e-2, 1e-2, 3e-3, 1e-3, 3e-4, 1e-4}, each the best of the grid on two signals of the task, as each config's header says. Sine networks (SIREN, FINER) are the most sensitive; FUTON trains at 1e-2 to 1e-1 across tasks.
Training times differ from the tables
Times vary with the machine and its load; the tables take every cost from the benchmark runs themselves, each the median over a task's signals, as the reproduction page explains.
Models¶
What does hidden_layers count?
Hidden layers. A network with hidden_layers=h has h + 1 weight layers (MFN: h Gabor filters and h linear layers). The configs state the counts as the constructors expect them.
Loading an MLP checkpoint
MLP.layers contains only weight layers, so a network with hidden_layers=h has keys layers.0 to layers.h; a shared activation with parameters (for example nn.PReLU) lives under activation.*.