NICEForImageGeneration
ImageGenerationModelNICEForImageGeneration(config: NICEConfig)NICE with the exact maximum-likelihood loss and .generate().
Wraps NICEModel with the paper's training objective — plain
negative log-likelihood, no bound and no auxiliary term — and the
ancestral sampler. forward(x) returns a
NormalizingFlowOutput whose loss is
-log_prob.mean(); generate(n_samples) draws
and returns in a single parallel
pass.
Parameters
configNICEConfigNICEConfig.Attributes
niceNICEModelencode / decode /
log_prob.Notes
Reference: Dinh, Krueger, and Bengio, "NICE: Non-linear Independent Components Estimation", ICLR Workshop, 2015 (arXiv:1410.8516).
Training objective (maximised in the paper, minimised here):
The paper optimises this with Adam (learning rate ) for 1500 epochs and reports test log-likelihoods of 1980.50 (MNIST), 5514.71 (TFD), 11496.55 (SVHN) and 5371.78 (CIFAR-10) nats — figures that are only comparable under the paper's own preprocessing.
Examples
>>> import lucid
>>> from lucid.models.generative.nice import (
... NICEConfig, NICEForImageGeneration,
... )
>>> cfg = NICEConfig(input_dim=64, num_coupling_layers=2,
... num_hidden_layers=1, hidden_dim=16)
>>> model = NICEForImageGeneration(cfg).eval()
>>> out = model(lucid.rand((2, 64)))
>>> out.loss.shape # scalar NLL
()
>>> model.generate(n_samples=3).samples.shape
(3, 64)Used by 2
Constructors
1Instance methods
2forward(x: Tensor)generate(n_samples: int = 1, device: str | None = None)Sample n_samples vectors by inverting a prior draw.
Parameters
n_samplesint= 1devicestr= NoneReturns
GenerationOutputsamples of shape (n_samples, D), in the same
(dequantised, possibly whitened) space the model was trained
on — no squashing is applied. Reshape to the dataset's image
grid for display.
Examples
>>> import lucid
>>> from lucid.models.generative.nice import (
... NICEConfig, NICEForImageGeneration,
... )
>>> cfg = NICEConfig(input_dim=64, num_coupling_layers=2,
... num_hidden_layers=1, hidden_dim=16)
>>> model = NICEForImageGeneration(cfg).eval()
>>> samples = model.generate(n_samples=3).samples
>>> samples.shape # flat, like the training data
(3, 64)
>>> samples.reshape(3, 1, 8, 8).shape # onto an 8x8 grid for display
(3, 1, 8, 8)
>>> lucid.manual_seed(0)
>>> first = model.generate(n_samples=2).samples
>>> lucid.manual_seed(0) # the prior draw is the only randomness
>>> bool(lucid.allclose(first, model.generate(n_samples=2).samples))
True