Diffusion Noise Models¶
This page describes the diffusion noise model available in synference. In contrast to the empirical noise models discussed in the previous sections, which simply model per-band uncertainties as a function of magnitude using binned interpolation, the diffusion noise model is a generative model that learns to the full latent distribution of noise in the data. This allows it to capture more complex noise properties, such as correlations between bands, and to generate more realistic noise
realizations.
This noise model is based on the diffusion probabilistic model framework, which has been successfully applied to a wide range of generative modeling tasks in machine learning. The basic idea is to model the noise as a stochastic process that gradually transforms a simple initial distribution (e.g., Gaussian noise) into the complex noise distribution observed in the data. By learning this transformation, the model can generate realistic noise samples that can be added to synthetic photometry to better match the properties of real observations.
This is implemented as the ScoreBasedUncertaintyModel, which learns the conditional uncertainty distribution p(σ|m), where σ is the uncertainty and m is the magnitude. It lives in the standalone syntillate package, which Synference installs as a dependency and re-exports from synference.noise_models, so it can be used and serialized alongside Synference’s other uncertainty models. The model is trained on a dataset of real
photometric measurements, where the input is the magnitude and the target is the corresponding (log-scaled) uncertainty. Once trained, the model can be used to generate noise samples for synthetic photometry by sampling from the learned distribution.
We will demonstate this on the standard COSMOSO2020 ‘Farmer’ catalog (Weaver et al. 2020). If you want to train the noise model yourself, you will have to download the full catalog (~3 GB) from here.
[1]:
from syntillate import ScoreBasedUncertaintyModel
?ScoreBasedUncertaintyModel
Training the Noise Model¶
The first part is just loading and cleaning the COSMOS2020 catalog, which is fairly standard. We filter low signal to noise sources which are faint in IRAC Ch. 1. As we are interested in learning the full conditional distribution of noise across all the filters, we also remove sources with missing photometry in any of the filters.
```python
from astropy.table import Table import numpy as np
table = Table.read(‘COSMOS2020_FARMER_R1_v2.2_p3.fits’, memmap=True)
bands = [‘CFHT_u’, ‘HSC_g’, ‘HSC_r’, ‘HSC_i’, ‘HSC_z’, ‘HSC_y’, ‘UVISTA_Y’, ‘UVISTA_J’, ‘UVISTA_H’, ‘UVISTA_Ks’, ‘IRAC_CH1’, ‘IRAC_CH2’]
snr_filter = table[‘IRAC_CH1_MAG’] < 26 table = table[snr_filter]
for band in bands: table = table[np.isfinite(table[band + ‘_MAG’])]
We then construct our training dataset, which consists of the magnitudes and uncertainties for each band.
mag_array = np.array([table[band + '_MAG'] for band in bands]).T
flux_error_array = np.array([table[band + '_FLUXERR'] for band in bands]).T
Next, we can train the ScoreBasedUncertaintyModel on this dataset. This will learn the conditional distribution of uncertainties given magnitudes for each band. We will leave the model architecture as it’s default, which is a simple MLP with 5 layers and a hidden dimension of 256. The training process can take some time, especially if you are using a CPU, so be patient!
You can adjust the number of epochs and batch size as needed –> larger batch sizes will speed up training but require more memory, while more epochs will allow the model to learn better but will take longer.
from syntillate import ScoreBasedUncertaintyModel
noise_model = ScoreBasedUncertaintyModel(filter_names=bands)
# COSMOS2020 FLUXERR columns are in uJy; the model reports sigma back in
# the same units (see noise_model.sigma_units).
noise_model.fit(
mag_array,
flux_error_array,
flux_uncertainty_units='uJy',
n_epochs=200,
batch_size=1024,
)
Saving the Model¶
We can save the trained model to disk for later use - the model can be serialized directly into a custom HDF5 format, and re-loaded later without needing to re-train, or rely on unstable dependencies like pickle or torch.save.
import h5py
with h5py.File('COSMOS_noise_model.h5', 'w') as f:
noise_model.serialize_to_hdf5(f.create_group('noise_model'))
Loading the Model¶
We can load in the saved model from disk, just to prove it works! Here we will switch to our pre-trained model which you can get by running synference-download, but feel free to load in your own trained model if you have one.
[2]:
import h5py
with h5py.File("COSMOS_noise_model.h5", "r") as f:
noise_model = ScoreBasedUncertaintyModel._from_hdf5_group(f["noise_model"])
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[2], line 3
1 import h5py
----> 3 with h5py.File("COSMOS_noise_model.h5", "r") as f:
4 noise_model = ScoreBasedUncertaintyModel._from_hdf5_group(f["noise_model"])
File /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/h5py/_hl/files.py:555, in File.__init__(self, name, mode, driver, libver, userblock_size, swmr, rdcc_nslots, rdcc_nbytes, rdcc_w0, track_order, fs_strategy, fs_persist, fs_threshold, fs_page_size, page_buf_size, min_meta_keep, min_raw_keep, locking, alignment_threshold, alignment_interval, meta_block_size, track_times, **kwds)
546 fapl = make_fapl(driver, libver, rdcc_nslots, rdcc_nbytes, rdcc_w0,
547 locking, page_buf_size, min_meta_keep, min_raw_keep,
548 alignment_threshold=alignment_threshold,
549 alignment_interval=alignment_interval,
550 meta_block_size=meta_block_size,
551 **kwds)
552 fcpl = make_fcpl(track_order=track_order, track_times=track_times,
553 fs_strategy=fs_strategy, fs_persist=fs_persist,
554 fs_threshold=fs_threshold, fs_page_size=fs_page_size)
--> 555 fid = make_fid(name, mode, userblock_size, fapl, fcpl, swmr=swmr)
557 if isinstance(libver, tuple):
558 self._libver = libver
File /opt/hostedtoolcache/Python/3.10.20/x64/lib/python3.10/site-packages/h5py/_hl/files.py:232, in make_fid(name, mode, userblock_size, fapl, fcpl, swmr)
230 if swmr:
231 flags |= h5f.ACC_SWMR_READ
--> 232 fid = h5f.open(name, flags, fapl=fapl)
233 elif mode == 'r+':
234 fid = h5f.open(name, h5f.ACC_RDWR, fapl=fapl)
File h5py/_objects.pyx:54, in h5py._objects.with_phil.wrapper()
File h5py/_objects.pyx:55, in h5py._objects.with_phil.wrapper()
File h5py/h5f.pyx:106, in h5py.h5f.open()
FileNotFoundError: [Errno 2] Unable to synchronously open file (unable to open file: name = 'COSMOS_noise_model.h5', errno = 2, error message = 'No such file or directory', flags = 0, o_flags = 0)