Poisson-Gaussian Contamination Mixture Examples¶
This guide demonstrates how to model data affected by both count (Poisson/shot) noise and continuous (Gaussian/readout) noise using PoissonGaussianContaminationMixtureLoss and EnhancedPoissonGaussianContaminationMixtureLoss.
→ API: PoissonGaussianContaminationMixtureLoss.
| # | Reference |
|---|---|
| 1 | Foi, A., Trimeche, M., Katkovnik, V., & Egiazarian, K. (2008). Practical Poisson-Gaussian noise modeling and sensor calibration in single-image photometry. IEEE Transactions on Image Processing. |
| 2 | Luisier, F., Blu, T., & Unser, M. (2011). Image denoising in mixed Poisson–Gaussian noise. IEEE Transactions on Image Processing. |
Mathematical Formulations¶
The data in this example are generated by the detector model \(Y = Z + E\) with
\(Z \sim \text{Poisson}(\lambda)\) (shot noise) and \(E \sim \mathcal{N}(0, \sigma^2)\)
(read noise). Its likelihood is the convolution
\(\sum_k \text{Pois}(k;\lambda)\,\mathcal{N}(y; k, \sigma^2)\), implemented by
PoissonGaussianLoss.
The two losses demonstrated below are two-component mixtures, not that convolution, and are biased at low counts (see the comparison).
Poisson-Gaussian Contamination Mixture Loss¶
Enhanced Poisson-Gaussian Contamination Mixture Loss¶
With \(\mu = g\lambda + b\):
where \(g\) is the gain, \(b\) the offset, \(\sigma_1^2\) a constant variance and \(\sigma_2^2\) a signal-dependent variance coefficient.
Code Example¶
Below is a complete example showing how to train a model predicting a latent rate parameter under mixed noise.
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torchregress.losses import PoissonGaussianContaminationMixtureLoss, EnhancedPoissonGaussianContaminationMixtureLoss
# Generate synthetic Poisson-Gaussian noise data
np.random.seed(42)
n_samples = 1000
sigma = 0.6
x = np.random.uniform(-1.5, 1.5, size=(n_samples, 1)).astype(np.float32)
true_rate = np.exp(0.8 * x + 1.2).astype(np.float32)
# Count shot noise + Gaussian readout noise
shot = np.random.poisson(true_rate).astype(np.float32)
readout = np.random.normal(0, sigma, size=shot.shape).astype(np.float32)
y = shot + readout
x_tensor = torch.from_numpy(x)
y_tensor = torch.from_numpy(y)
# Neural network predicting latent rate
class SignalModel(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Linear(1, 32),
nn.ReLU(),
nn.Linear(32, 1)
)
def forward(self, x):
return self.net(x)
# Train with learnable Gaussian variance
model = SignalModel()
optimizer = optim.Adam(model.parameters(), lr=0.01)
loss_fn = PoissonGaussianContaminationMixtureLoss(learn_variance=True, log_input=False)
for epoch in range(150):
rate_pred = torch.exp(model(x_tensor))
loss = loss_fn(rate_pred, y_tensor)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("Poisson-Gaussian mixture model trained successfully.")