Note
New to DeepInverse? Get started with the basics with the 5 minute quickstart tutorial..
Uncertainty quantification with PnP-ULA.#
This code shows you how to use sampling algorithms to quantify uncertainty of a reconstruction from incomplete and noisy measurements.
ULA obtains samples by running the following iteration:
where \(z_k \sim \mathcal{N}(0, I)\) is a Gaussian random variable, \(\eta\) is the step size and \(\alpha\) is a parameter controlling the regularization.
The PnP-ULA method is described in the paper Laumont et al.[1].
import deepinv as dinv
from deepinv.utils.plotting import plot
import torch
from deepinv.utils import load_example
Load image from the internet#
This example uses an image of Messi.
device = dinv.utils.get_device()
x = load_example("messi.jpg", img_size=32).to(device)
Selected GPU 0 with 6547.625 MiB free memory
Define forward operator and noise model#
This example uses inpainting as the forward operator and Gaussian noise as the noise model.
sigma = 0.1 # noise level
physics = dinv.physics.Inpainting(mask=0.5, img_size=x.shape[1:], device=device)
physics.noise_model = dinv.physics.GaussianNoise(sigma=sigma)
# Set the global random seed from pytorch to ensure reproducibility of the example.
torch.manual_seed(0)
<torch._C.Generator object at 0x7f82f894f3d0>
Define the likelihood#
Since the noise model is Gaussian, the negative log-likelihood is the L2 loss.
# load Gaussian Likelihood
likelihood = dinv.optim.data_fidelity.L2(sigma=sigma)
Define the prior#
The score a distribution can be approximated using Tweedieβs formula via the
deepinv.optim.ScorePrior class.
This example uses a pretrained DnCNN model.
From a Bayesian point of view, the score plays the role of the gradient of the
negative log prior
The hyperparameter sigma_denoiser (\(sigma\)) controls the strength of the prior.
In this example, we use a pretrained DnCNN model using the deepinv.loss.FNEJacobianSpectralNorm loss,
which makes sure that the denoiser is firmly non-expansive (see Terris et al.[2]), and helps to
stabilize the sampling algorithm.
sigma_denoiser = 2 / 255
prior = dinv.optim.ScorePrior(
denoiser=dinv.models.DnCNN(pretrained="download_lipschitz")
).to(device)
Create the MCMC sampler#
Here we use the Unadjusted Langevin Algorithm (ULA) to sample from the posterior defined in
deepinv.sampling.ULAIterator.
The hyperparameter step_size controls the step size of the MCMC sampler,
regularization controls the strength of the prior and
iterations controls the number of iterations of the sampler.
regularization = 0.9
step_size = 0.01 * (sigma**2)
iterations = int(5e3) if torch.cuda.is_available() else 10
params = {
"step_size": step_size,
"alpha": regularization,
"sigma": sigma_denoiser,
}
f = dinv.sampling.sampling_builder(
"ULA",
prior=prior,
data_fidelity=likelihood,
max_iter=iterations,
params_algo=params,
thinning=1,
verbose=True,
)
Generate the measurement#
We apply the forward model to generate the noisy measurement.
Run sampling algorithm and plot results#
The sampling algorithm returns the posterior mean and variance. We compare the posterior mean with a simple linear reconstruction.
mean, var = f.sample(y, physics)
# compute linear inverse
x_lin = physics.A_adjoint(y)
# compute PSNR
print(f"Linear reconstruction PSNR: {dinv.metric.PSNR()(x, x_lin).item():.2f} dB")
print(f"Posterior mean PSNR: {dinv.metric.PSNR()(x, mean).item():.2f} dB")
# plot results
error = (mean - x).abs().sum(dim=1).unsqueeze(1) # per pixel average abs. error
std = var.sum(dim=1).unsqueeze(1).sqrt() # per pixel average standard dev.
imgs = [x_lin, x, mean, std / std.flatten().max(), error / error.flatten().max()]
plot(
imgs,
titles=["measurement", "ground truth", "post. mean", "post. std", "abs. error"],
)

0%| | 0/5000 [00:00<?, ?it/s]
1%|β | 66/5000 [00:00<00:07, 651.00it/s]
3%|β | 137/5000 [00:00<00:07, 681.85it/s]
4%|β | 221/5000 [00:00<00:06, 752.16it/s]
6%|β | 305/5000 [00:00<00:05, 786.57it/s]
8%|β | 389/5000 [00:00<00:05, 805.35it/s]
9%|β | 473/5000 [00:00<00:05, 816.73it/s]
11%|β | 557/5000 [00:00<00:05, 821.39it/s]
13%|ββ | 641/5000 [00:00<00:05, 826.42it/s]
14%|ββ | 725/5000 [00:00<00:05, 830.38it/s]
16%|ββ | 809/5000 [00:01<00:05, 832.59it/s]
18%|ββ | 893/5000 [00:01<00:04, 827.77it/s]
20%|ββ | 976/5000 [00:01<00:04, 810.69it/s]
21%|ββ | 1058/5000 [00:01<00:04, 795.58it/s]
23%|βββ | 1138/5000 [00:01<00:04, 789.93it/s]
24%|βββ | 1218/5000 [00:01<00:04, 791.93it/s]
26%|βββ | 1298/5000 [00:01<00:04, 793.62it/s]
28%|βββ | 1378/5000 [00:01<00:04, 795.11it/s]
29%|βββ | 1458/5000 [00:01<00:04, 795.44it/s]
31%|βββ | 1538/5000 [00:01<00:04, 796.36it/s]
32%|ββββ | 1618/5000 [00:02<00:04, 795.94it/s]
34%|ββββ | 1698/5000 [00:02<00:04, 795.59it/s]
36%|ββββ | 1778/5000 [00:02<00:04, 795.83it/s]
37%|ββββ | 1858/5000 [00:02<00:03, 794.85it/s]
39%|ββββ | 1938/5000 [00:02<00:03, 795.00it/s]
40%|ββββ | 2018/5000 [00:02<00:03, 796.11it/s]
42%|βββββ | 2098/5000 [00:02<00:03, 795.89it/s]
44%|βββββ | 2178/5000 [00:02<00:03, 793.40it/s]
45%|βββββ | 2258/5000 [00:02<00:03, 794.27it/s]
47%|βββββ | 2338/5000 [00:02<00:03, 794.55it/s]
48%|βββββ | 2418/5000 [00:03<00:03, 793.93it/s]
50%|βββββ | 2498/5000 [00:03<00:03, 794.90it/s]
52%|ββββββ | 2578/5000 [00:03<00:03, 795.67it/s]
53%|ββββββ | 2658/5000 [00:03<00:02, 792.84it/s]
55%|ββββββ | 2738/5000 [00:03<00:02, 779.31it/s]
56%|ββββββ | 2816/5000 [00:03<00:02, 769.67it/s]
58%|ββββββ | 2894/5000 [00:03<00:02, 768.38it/s]
59%|ββββββ | 2974/5000 [00:03<00:02, 776.95it/s]
61%|ββββββ | 3054/5000 [00:03<00:02, 781.40it/s]
63%|βββββββ | 3134/5000 [00:03<00:02, 786.64it/s]
64%|βββββββ | 3214/5000 [00:04<00:02, 790.25it/s]
66%|βββββββ | 3294/5000 [00:04<00:02, 791.24it/s]
67%|βββββββ | 3374/5000 [00:04<00:02, 793.48it/s]
69%|βββββββ | 3454/5000 [00:04<00:01, 790.85it/s]
71%|βββββββ | 3534/5000 [00:04<00:01, 785.50it/s]
72%|ββββββββ | 3614/5000 [00:04<00:01, 787.58it/s]
74%|ββββββββ | 3694/5000 [00:04<00:01, 788.37it/s]
75%|ββββββββ | 3774/5000 [00:04<00:01, 791.08it/s]
77%|ββββββββ | 3855/5000 [00:04<00:01, 793.77it/s]
79%|ββββββββ | 3935/5000 [00:04<00:01, 795.16it/s]
80%|ββββββββ | 4015/5000 [00:05<00:01, 795.88it/s]
82%|βββββββββ | 4095/5000 [00:05<00:01, 796.15it/s]
84%|βββββββββ | 4175/5000 [00:05<00:01, 796.92it/s]
85%|βββββββββ | 4255/5000 [00:05<00:00, 795.19it/s]
87%|βββββββββ | 4335/5000 [00:05<00:00, 796.45it/s]
88%|βββββββββ | 4415/5000 [00:05<00:00, 796.85it/s]
90%|βββββββββ | 4495/5000 [00:05<00:00, 785.79it/s]
91%|ββββββββββ| 4574/5000 [00:05<00:00, 773.60it/s]
93%|ββββββββββ| 4652/5000 [00:05<00:00, 769.05it/s]
95%|ββββββββββ| 4731/5000 [00:05<00:00, 773.50it/s]
96%|ββββββββββ| 4811/5000 [00:06<00:00, 781.10it/s]
98%|ββββββββββ| 4892/5000 [00:06<00:00, 786.77it/s]
99%|ββββββββββ| 4972/5000 [00:06<00:00, 789.76it/s]
100%|ββββββββββ| 5000/5000 [00:06<00:00, 791.62it/s]
Iteration 4999, current converge crit. = 1.42E-05, objective = 1.00E-03
Iteration 4999, current converge crit. = 3.42E-04, objective = 1.00E-03
Linear reconstruction PSNR: 8.55 dB
Posterior mean PSNR: 22.31 dB
- References:
Total running time of the script: (0 minutes 6.487 seconds)