NeuralODEForImageGeneration
ImageGenerationModelNeuralODEForImageGeneration(config: NeuralODEConfig)Neural ODE flow with a training loss and .generate().
forward(x) returns a NormalizingFlowOutput whose loss
is the mean negative log-likelihood in bits per dimension, the
scale-free form that keeps the gradient magnitude independent of how
wide the data is. generate(n_samples) draws
and integrates the field backwards to t = 0.
Parameters
configNeuralODEConfigAttributes
neural_odeNeuralODEModelencode / decode / log_prob /
bits_per_dim.Notes
Reference: Chen, Rubanova, Bettencourt, and Duvenaud, "Neural
Ordinary Differential Equations", NeurIPS, 2018 (arXiv:1806.07366).
The paper's own continuous-flow experiments are two-dimensional
density matching rather than images; sampling at image scale is what
the Hutchinson trace of Grathwohl et al. (ICLR 2019) makes affordable,
and is what trace_method selects by default above
exact_trace_max_dim.
Examples
>>> import lucid
>>> from lucid.models.generative.neural_ode import (
... NeuralODEConfig, NeuralODEForImageGeneration,
... )
>>> cfg = NeuralODEConfig(sample_size=2, in_channels=1, out_channels=1,
... hidden_dim=8, num_blocks=1)
>>> model = NeuralODEForImageGeneration(cfg).eval()
>>> out = model(lucid.rand((2, 1, 2, 2)))
>>> out.loss.shape # scalar bits/dim
()
>>> model.generate(n_samples=3).samples.shape
(3, 1, 2, 2)Used by 2
Constructors
1Properties
1Instance methods
2forward(x: Tensor)Run the flow and attach the training loss.
Parameters
(B, C, H, W) data samples.Returns
NormalizingFlowOutputThe wrapped model's latent / log_det_jacobian /
log_prob, plus loss: the mean negative log-likelihood
in bits per dimension.
Notes
Bits/dim rather than nats so the gradient magnitude does not scale with the width of the data — the same quantity the likelihood literature reports.
generate(n_samples: int = 1, temperature: float = 1.0, device: str | None = None)Sample by integrating a prior draw back to t = 0.
Parameters
n_samplesint= 1temperaturefloat= 1.01 it
trades diversity for typicality — a standard trick for flows,
not part of the paper.devicestr= NoneReturns
GenerationOutputsamples of shape (n_samples, C, H, W).
Notes
Costs one solve, not one per step: the reverse direction carries no density term, so it is the cheaper of the two passes.
Examples
>>> import lucid
>>> from lucid.models.generative.neural_ode import (
... NeuralODEConfig, NeuralODEForImageGeneration,
... )
>>> cfg = NeuralODEConfig(sample_size=2, in_channels=1, out_channels=1,
... hidden_dim=8, num_blocks=1)
>>> model = NeuralODEForImageGeneration(cfg).eval()
>>> model.generate(n_samples=3).samples.shape
(3, 1, 2, 2)
>>> lucid.manual_seed(0)
>>> cool = model.generate(n_samples=2, temperature=0.5).samples
>>> lucid.manual_seed(0)
>>> z = lucid.randn((2, 4)) # the same standard-normal prior draw
>>> bool(lucid.allclose(cool, model.neural_ode.decode(z * 0.5)))
True