Skip to content

algorithms

Implementation of various unsupervised and self-supervised denoising methods.

Classes:

  • DIP

    Deep image prior.

  • DataScaleBias

    Data scale and bias.

  • Denoiser

    Denoising images.

  • N2N

    Self-supervised denoising from pairs of images.

  • N2V

    Self-supervised denoising from single images.

Functions:

DIP

DIP(
    model: int | str | NetworkParams | Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-05,
    device: str = "cuda" if is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
)

Bases: Denoiser

Deep image prior.

Parameters:

  • model (str | NetworkParams | Module | Mapping | None) –

    Type of neural network to use or a specific network (or state) to use

  • data_scale_bias (DataScaleBias | None, default: None ) –

    Scale and bias of the input data, by default None

  • reg_val (float | None, default: 1e-05 ) –

    Regularization value, by default 1e-5

  • device (str, default: 'cuda' if is_available() else 'cpu' ) –

    Device to use, by default "cuda" if cuda is available, otherwise "cpu"

  • save_epochs_dir (str | None, default: None ) –

    Directory where to save network states at each epoch. If None disabled, by default None

  • verbose (bool, default: True ) –

    Whether to produce verbose output, by default True

Methods:

Source code in src/autoden/algorithms.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
def __init__(
    self,
    model: int | str | NetworkParams | pt.nn.Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-5,
    device: str = "cuda" if pt.cuda.is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
) -> None:
    """Initialize the noise2noise method.

    Parameters
    ----------
    model : str | NetworkParams | pt.nn.Module | Mapping | None
        Type of neural network to use or a specific network (or state) to use
    data_scale_bias : DataScaleBias | None, optional
        Scale and bias of the input data, by default None
    reg_val : float | None, optional
        Regularization value, by default 1e-5
    device : str, optional
        Device to use, by default "cuda" if cuda is available, otherwise "cpu"
    save_epochs_dir : str | None, optional
        Directory where to save network states at each epoch.
        If None disabled, by default None
    verbose : bool, optional
        Whether to produce verbose output, by default True
    """
    if isinstance(model, int):
        if self.save_epochs_dir is None:
            raise ValueError("Directory for saving epochs not specified")

        model = load_model_state(self.save_epochs_dir, epoch_num=model)

    if isinstance(model, (str, NetworkParams, Mapping, pt.nn.Module)):
        self.model = create_network(model, device=device)
    else:
        raise ValueError(f"Invalid model {type(model)}")
    if verbose:
        get_num_parameters(self.model, verbose=True)

    self.data_sb = data_scale_bias

    self.reg_val = reg_val
    self.device = device
    self.save_epochs_dir = save_epochs_dir
    self.verbose = verbose

infer

infer(inp: NDArray) -> NDArray

Inference, given an initial stack of images.

Parameters:

  • inp (NDArray) –

    The input stack of images

Returns:

  • NDArray

    The denoised stack of images

Source code in src/autoden/algorithms.py
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
def infer(self, inp: NDArray) -> NDArray:
    """Inference, given an initial stack of images.

    Parameters
    ----------
    inp : NDArray
        The input stack of images

    Returns
    -------
    NDArray
        The denoised stack of images
    """
    # Rescale input
    if self.data_sb is not None:
        inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp

    inp_t = _single_channel_imgs_to_tensor(inp, device=self.device)

    self.model.eval()
    with pt.inference_mode():
        out_t: pt.Tensor = self.model(inp_t)
        output = out_t.to("cpu").numpy().reshape(inp.shape)

    # Rescale output
    if self.data_sb is not None:
        output = (output + self.data_sb.bias_out) / self.data_sb.scale_out

    return output

train_supervised

train_supervised(
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
)

Supervised training.

Parameters:

  • inp (NDArray) –

    The input images

  • tgt (NDArray) –

    The target images

  • epochs (int) –

    Number of training epochs

  • tst_inds (Sequence[int] | NDArray) –

    The validation set indices

  • algo (str, default: 'adam' ) –

    Learning algorithm to use, by default "adam"

Source code in src/autoden/algorithms.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def train_supervised(
    self,
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
):
    """Supervised training.

    Parameters
    ----------
    inp : NDArray
        The input images
    tgt : NDArray
        The target images
    epochs : int
        Number of training epochs
    tst_inds : Sequence[int] | NDArray
        The validation set indices
    algo : str, optional
        Learning algorithm to use, by default "adam"
    """
    num_imgs = inp.shape[0]
    tst_inds = np.array(tst_inds, dtype=int)
    if np.any(tst_inds < 0) or np.any(tst_inds >= num_imgs):
        raise ValueError(
            f"Each cross-validation index should be greater or equal than 0, and less than the number of images {num_imgs}"
        )
    trn_inds = np.delete(np.arange(num_imgs), obj=tst_inds)

    if tgt.ndim == (inp.ndim - 1):
        tgt = np.tile(tgt[None, ...], [num_imgs, *np.ones_like(tgt.shape)])

    if self.data_sb is None:
        self.data_sb = compute_scaling_supervised(inp, tgt)

    # Rescale the datasets
    inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp
    tgt = tgt * self.data_sb.scale_tgt - self.data_sb.bias_tgt

    # Create datasets
    dset_trn = (inp[trn_inds], tgt[trn_inds])
    dset_tst = (inp[tst_inds], tgt[tst_inds])

    reg = self._get_regularization()
    losses = self._train_selfsimilar(dset_trn, dset_tst, epochs=epochs, algo=algo, regularizer=reg)

    if self.verbose:
        self._plot_loss_curves(losses, f"Supervised {algo.upper()}")

train_unsupervised

train_unsupervised(
    tgt: NDArray,
    epochs: int,
    inp: NDArray | None = None,
    num_tst_ratio: float = 0.2,
    algo: str = "adam",
) -> NDArray

Train the model in an unsupervised manner.

Parameters:

  • tgt (NDArray) –

    The target image to be denoised.

  • epochs (int) –

    The number of training epochs.

  • inp (NDArray | None, default: None ) –

    The input image. If None, a random image will be generated. Default is None.

  • num_tst_ratio (float, default: 0.2 ) –

    The ratio of the test set size to the total dataset size. Default is 0.2.

  • algo (str, default: 'adam' ) –

    The optimization algorithm to use. Default is "adam".

Returns:

  • NDArray

    The denoised input image.

Notes

This method trains the model using the deep image prior approach in an unsupervised manner. It uses a random initialization for the input image if not provided and applies a scaling and bias transformation to the input and target images. It then splits the data into training and test sets based on the provided ratio and trains the model using the specified optimization algorithm.

Source code in src/autoden/algorithms.py
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
def train_unsupervised(
    self, tgt: NDArray, epochs: int, inp: NDArray | None = None, num_tst_ratio: float = 0.2, algo: str = "adam"
) -> NDArray:
    """
    Train the model in an unsupervised manner.

    Parameters
    ----------
    tgt : NDArray
        The target image to be denoised.
    epochs : int
        The number of training epochs.
    inp : NDArray | None, optional
        The input image. If None, a random image will be generated.
        Default is None.
    num_tst_ratio : float, optional
        The ratio of the test set size to the total dataset size.
        Default is 0.2.
    algo : str, optional
        The optimization algorithm to use. Default is "adam".

    Returns
    -------
    NDArray
        The denoised input image.

    Notes
    -----
    This method trains the model using the deep image prior approach in an unsupervised manner.
    It uses a random initialization for the input image if not provided and applies a scaling and bias
    transformation to the input and target images. It then splits the data into training and test sets
    based on the provided ratio and trains the model using the specified optimization algorithm.
    """
    if inp is None:
        inp = np.random.normal(size=tgt.shape[-2:], scale=0.25).astype(tgt.dtype)

    if self.data_sb is None:
        self.data_sb = compute_scaling_supervised(inp, tgt)

    # Rescale the datasets
    tmp_inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp
    tmp_tgt = tgt * self.data_sb.scale_tgt - self.data_sb.bias_tgt

    mask_trn = np.ones_like(tgt, dtype=bool)
    rnd_inds = np.random.random_integers(low=0, high=mask_trn.size - 1, size=int(mask_trn.size * num_tst_ratio))
    mask_trn[np.unravel_index(rnd_inds, shape=mask_trn.shape)] = False

    reg = self._get_regularization()
    losses = self._train_pixelmask_small(tmp_inp, tmp_tgt, mask_trn, epochs=epochs, algo=algo, regularizer=reg)

    if self.verbose:
        self._plot_loss_curves(losses, f"Unsupervised {self.__class__.__name__} {algo.upper()}")

    return inp

DataScaleBias dataclass

DataScaleBias(
    scale_inp: float | NDArray = 1.0,
    scale_out: float | NDArray = 1.0,
    scale_tgt: float | NDArray = 1.0,
    bias_inp: float | NDArray = 0.0,
    bias_out: float | NDArray = 0.0,
    bias_tgt: float | NDArray = 0.0,
)

Data scale and bias.

Denoiser

Denoiser(
    model: int | str | NetworkParams | Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-05,
    device: str = "cuda" if is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
)

Denoising images.

Parameters:

  • model (str | NetworkParams | Module | Mapping | None) –

    Type of neural network to use or a specific network (or state) to use

  • data_scale_bias (DataScaleBias | None, default: None ) –

    Scale and bias of the input data, by default None

  • reg_val (float | None, default: 1e-05 ) –

    Regularization value, by default 1e-5

  • device (str, default: 'cuda' if is_available() else 'cpu' ) –

    Device to use, by default "cuda" if cuda is available, otherwise "cpu"

  • save_epochs_dir (str | None, default: None ) –

    Directory where to save network states at each epoch. If None disabled, by default None

  • verbose (bool, default: True ) –

    Whether to produce verbose output, by default True

Methods:

Source code in src/autoden/algorithms.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
def __init__(
    self,
    model: int | str | NetworkParams | pt.nn.Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-5,
    device: str = "cuda" if pt.cuda.is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
) -> None:
    """Initialize the noise2noise method.

    Parameters
    ----------
    model : str | NetworkParams | pt.nn.Module | Mapping | None
        Type of neural network to use or a specific network (or state) to use
    data_scale_bias : DataScaleBias | None, optional
        Scale and bias of the input data, by default None
    reg_val : float | None, optional
        Regularization value, by default 1e-5
    device : str, optional
        Device to use, by default "cuda" if cuda is available, otherwise "cpu"
    save_epochs_dir : str | None, optional
        Directory where to save network states at each epoch.
        If None disabled, by default None
    verbose : bool, optional
        Whether to produce verbose output, by default True
    """
    if isinstance(model, int):
        if self.save_epochs_dir is None:
            raise ValueError("Directory for saving epochs not specified")

        model = load_model_state(self.save_epochs_dir, epoch_num=model)

    if isinstance(model, (str, NetworkParams, Mapping, pt.nn.Module)):
        self.model = create_network(model, device=device)
    else:
        raise ValueError(f"Invalid model {type(model)}")
    if verbose:
        get_num_parameters(self.model, verbose=True)

    self.data_sb = data_scale_bias

    self.reg_val = reg_val
    self.device = device
    self.save_epochs_dir = save_epochs_dir
    self.verbose = verbose

infer

infer(inp: NDArray) -> NDArray

Inference, given an initial stack of images.

Parameters:

  • inp (NDArray) –

    The input stack of images

Returns:

  • NDArray

    The denoised stack of images

Source code in src/autoden/algorithms.py
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
def infer(self, inp: NDArray) -> NDArray:
    """Inference, given an initial stack of images.

    Parameters
    ----------
    inp : NDArray
        The input stack of images

    Returns
    -------
    NDArray
        The denoised stack of images
    """
    # Rescale input
    if self.data_sb is not None:
        inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp

    inp_t = _single_channel_imgs_to_tensor(inp, device=self.device)

    self.model.eval()
    with pt.inference_mode():
        out_t: pt.Tensor = self.model(inp_t)
        output = out_t.to("cpu").numpy().reshape(inp.shape)

    # Rescale output
    if self.data_sb is not None:
        output = (output + self.data_sb.bias_out) / self.data_sb.scale_out

    return output

train_supervised

train_supervised(
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
)

Supervised training.

Parameters:

  • inp (NDArray) –

    The input images

  • tgt (NDArray) –

    The target images

  • epochs (int) –

    Number of training epochs

  • tst_inds (Sequence[int] | NDArray) –

    The validation set indices

  • algo (str, default: 'adam' ) –

    Learning algorithm to use, by default "adam"

Source code in src/autoden/algorithms.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def train_supervised(
    self,
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
):
    """Supervised training.

    Parameters
    ----------
    inp : NDArray
        The input images
    tgt : NDArray
        The target images
    epochs : int
        Number of training epochs
    tst_inds : Sequence[int] | NDArray
        The validation set indices
    algo : str, optional
        Learning algorithm to use, by default "adam"
    """
    num_imgs = inp.shape[0]
    tst_inds = np.array(tst_inds, dtype=int)
    if np.any(tst_inds < 0) or np.any(tst_inds >= num_imgs):
        raise ValueError(
            f"Each cross-validation index should be greater or equal than 0, and less than the number of images {num_imgs}"
        )
    trn_inds = np.delete(np.arange(num_imgs), obj=tst_inds)

    if tgt.ndim == (inp.ndim - 1):
        tgt = np.tile(tgt[None, ...], [num_imgs, *np.ones_like(tgt.shape)])

    if self.data_sb is None:
        self.data_sb = compute_scaling_supervised(inp, tgt)

    # Rescale the datasets
    inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp
    tgt = tgt * self.data_sb.scale_tgt - self.data_sb.bias_tgt

    # Create datasets
    dset_trn = (inp[trn_inds], tgt[trn_inds])
    dset_tst = (inp[tst_inds], tgt[tst_inds])

    reg = self._get_regularization()
    losses = self._train_selfsimilar(dset_trn, dset_tst, epochs=epochs, algo=algo, regularizer=reg)

    if self.verbose:
        self._plot_loss_curves(losses, f"Supervised {algo.upper()}")

N2N

N2N(
    model: int | str | NetworkParams | Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-05,
    device: str = "cuda" if is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
)

Bases: Denoiser

Self-supervised denoising from pairs of images.

Parameters:

  • model (str | NetworkParams | Module | Mapping | None) –

    Type of neural network to use or a specific network (or state) to use

  • data_scale_bias (DataScaleBias | None, default: None ) –

    Scale and bias of the input data, by default None

  • reg_val (float | None, default: 1e-05 ) –

    Regularization value, by default 1e-5

  • device (str, default: 'cuda' if is_available() else 'cpu' ) –

    Device to use, by default "cuda" if cuda is available, otherwise "cpu"

  • save_epochs_dir (str | None, default: None ) –

    Directory where to save network states at each epoch. If None disabled, by default None

  • verbose (bool, default: True ) –

    Whether to produce verbose output, by default True

Methods:

Source code in src/autoden/algorithms.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
def __init__(
    self,
    model: int | str | NetworkParams | pt.nn.Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-5,
    device: str = "cuda" if pt.cuda.is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
) -> None:
    """Initialize the noise2noise method.

    Parameters
    ----------
    model : str | NetworkParams | pt.nn.Module | Mapping | None
        Type of neural network to use or a specific network (or state) to use
    data_scale_bias : DataScaleBias | None, optional
        Scale and bias of the input data, by default None
    reg_val : float | None, optional
        Regularization value, by default 1e-5
    device : str, optional
        Device to use, by default "cuda" if cuda is available, otherwise "cpu"
    save_epochs_dir : str | None, optional
        Directory where to save network states at each epoch.
        If None disabled, by default None
    verbose : bool, optional
        Whether to produce verbose output, by default True
    """
    if isinstance(model, int):
        if self.save_epochs_dir is None:
            raise ValueError("Directory for saving epochs not specified")

        model = load_model_state(self.save_epochs_dir, epoch_num=model)

    if isinstance(model, (str, NetworkParams, Mapping, pt.nn.Module)):
        self.model = create_network(model, device=device)
    else:
        raise ValueError(f"Invalid model {type(model)}")
    if verbose:
        get_num_parameters(self.model, verbose=True)

    self.data_sb = data_scale_bias

    self.reg_val = reg_val
    self.device = device
    self.save_epochs_dir = save_epochs_dir
    self.verbose = verbose

infer

infer(inp: NDArray) -> NDArray

Inference, given an initial stack of images.

Parameters:

  • inp (NDArray) –

    The input stack of images

Returns:

  • NDArray

    The denoised stack of images

Source code in src/autoden/algorithms.py
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
def infer(self, inp: NDArray) -> NDArray:
    """Inference, given an initial stack of images.

    Parameters
    ----------
    inp : NDArray
        The input stack of images

    Returns
    -------
    NDArray
        The denoised stack of images
    """
    # Rescale input
    if self.data_sb is not None:
        inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp

    inp_t = _single_channel_imgs_to_tensor(inp, device=self.device)

    self.model.eval()
    with pt.inference_mode():
        out_t: pt.Tensor = self.model(inp_t)
        output = out_t.to("cpu").numpy().reshape(inp.shape)

    # Rescale output
    if self.data_sb is not None:
        output = (output + self.data_sb.bias_out) / self.data_sb.scale_out

    return output

train_selfsupervised

train_selfsupervised(
    inp: NDArray,
    epochs: int,
    num_tst_ratio: float = 0.2,
    strategy: str = "1:X",
    algo: str = "adam",
    lower_limit: float | NDArray | None = None,
) -> None

Train the denoiser using the Noise2Noise self-supervised approach.

Parameters:

  • inp (NDArray) –

    The input data to be used for training. This should be a NumPy array of shape (N, H, W), where N is the number of samples, and H and W are the height and width of each sample, respectively.

  • epochs (int) –

    The number of epochs to train the model.

  • num_tst_ratio (float, default: 0.2 ) –

    The ratio of the input data to be used for testing. The remaining data will be used for training. Default is 0.2.

  • strategy (str, default: '1:X' ) –

    The strategy to be used for creating input-target pairs. The available strategies are: - "1:X": Use the mean of the remaining samples as the target for each sample. - "X:1": Use the mean of the remaining samples as the input for each sample. Default is "1:X".

  • algo (str, default: 'adam' ) –

    The optimization algorithm to be used for training. The available algorithms are: - "adam": Adam optimizer. Default is "adam".

  • lower_limit (float | NDArray | None, default: None ) –

    The lower limit for the input data. If provided, the input data will be clipped to this limit. Default is None.

Notes

This method uses the Noise2Noise self-supervised approach to train the denoiser. The input data is used to generate target data based on the specified strategy. The training process involves creating pairs of input and target data and then training the model to minimize the difference between the predicted and target data.

Source code in src/autoden/algorithms.py
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
def train_selfsupervised(
    self,
    inp: NDArray,
    epochs: int,
    num_tst_ratio: float = 0.2,
    strategy: str = "1:X",
    algo: str = "adam",
    lower_limit: float | NDArray | None = None,
) -> None:
    """
    Train the denoiser using the Noise2Noise self-supervised approach.

    Parameters
    ----------
    inp : NDArray
        The input data to be used for training. This should be a NumPy array of shape (N, H, W), where N is the
        number of samples, and H and W are the height and width of each sample, respectively.
    epochs : int
        The number of epochs to train the model.
    num_tst_ratio : float, optional
        The ratio of the input data to be used for testing. The remaining data will be used for training.
        Default is 0.2.
    strategy : str, optional
        The strategy to be used for creating input-target pairs. The available strategies are:
        - "1:X": Use the mean of the remaining samples as the target for each sample.
        - "X:1": Use the mean of the remaining samples as the input for each sample.
        Default is "1:X".
    algo : str, optional
        The optimization algorithm to be used for training. The available algorithms are:
        - "adam": Adam optimizer.
        Default is "adam".
    lower_limit : float | NDArray | None, optional
        The lower limit for the input data. If provided, the input data will be clipped to this limit.
        Default is None.

    Notes
    -----
    This method uses the Noise2Noise self-supervised approach to train the denoiser. The input data is used to
    generate target data based on the specified strategy. The training process involves creating pairs of input
    and target data and then training the model to minimize the difference between the predicted and target data.
    """
    if self.data_sb is None:
        self.data_sb = compute_scaling_selfsupervised(inp)

    # Rescale the datasets
    inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp

    mask_trn = np.ones_like(inp, dtype=bool)
    rnd_inds = np.random.random_integers(low=0, high=mask_trn.size - 1, size=int(mask_trn.size * num_tst_ratio))
    mask_trn[np.unravel_index(rnd_inds, shape=mask_trn.shape)] = False

    inp_x = np.stack([np.delete(inp, obj=ii, axis=0).mean(axis=0) for ii in range(len(inp))], axis=0)
    if strategy.upper() == "1:X":
        tmp_inp = inp
        tmp_tgt = inp_x
    elif strategy.upper() == "X:1":
        tmp_inp = inp_x
        tmp_tgt = inp
    else:
        raise ValueError(f"Strategy {strategy} not implemented. Please choose one of: ['1:X', 'X:1']")

    tmp_inp = tmp_inp.astype(np.float32)
    tmp_tgt = tmp_tgt.astype(np.float32)

    reg = self._get_regularization()
    losses = self._train_pixelmask_small(
        tmp_inp, tmp_tgt, mask_trn, epochs=epochs, algo=algo, regularizer=reg, lower_limit=lower_limit
    )

    if self.verbose:
        self._plot_loss_curves(losses, f"Self-supervised {self.__class__.__name__} {algo.upper()}")

train_supervised

train_supervised(
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
)

Supervised training.

Parameters:

  • inp (NDArray) –

    The input images

  • tgt (NDArray) –

    The target images

  • epochs (int) –

    Number of training epochs

  • tst_inds (Sequence[int] | NDArray) –

    The validation set indices

  • algo (str, default: 'adam' ) –

    Learning algorithm to use, by default "adam"

Source code in src/autoden/algorithms.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def train_supervised(
    self,
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
):
    """Supervised training.

    Parameters
    ----------
    inp : NDArray
        The input images
    tgt : NDArray
        The target images
    epochs : int
        Number of training epochs
    tst_inds : Sequence[int] | NDArray
        The validation set indices
    algo : str, optional
        Learning algorithm to use, by default "adam"
    """
    num_imgs = inp.shape[0]
    tst_inds = np.array(tst_inds, dtype=int)
    if np.any(tst_inds < 0) or np.any(tst_inds >= num_imgs):
        raise ValueError(
            f"Each cross-validation index should be greater or equal than 0, and less than the number of images {num_imgs}"
        )
    trn_inds = np.delete(np.arange(num_imgs), obj=tst_inds)

    if tgt.ndim == (inp.ndim - 1):
        tgt = np.tile(tgt[None, ...], [num_imgs, *np.ones_like(tgt.shape)])

    if self.data_sb is None:
        self.data_sb = compute_scaling_supervised(inp, tgt)

    # Rescale the datasets
    inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp
    tgt = tgt * self.data_sb.scale_tgt - self.data_sb.bias_tgt

    # Create datasets
    dset_trn = (inp[trn_inds], tgt[trn_inds])
    dset_tst = (inp[tst_inds], tgt[tst_inds])

    reg = self._get_regularization()
    losses = self._train_selfsimilar(dset_trn, dset_tst, epochs=epochs, algo=algo, regularizer=reg)

    if self.verbose:
        self._plot_loss_curves(losses, f"Supervised {algo.upper()}")

N2V

N2V(
    model: int | str | NetworkParams | Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-05,
    device: str = "cuda" if is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
)

Bases: Denoiser

Self-supervised denoising from single images.

Parameters:

  • model (str | NetworkParams | Module | Mapping | None) –

    Type of neural network to use or a specific network (or state) to use

  • data_scale_bias (DataScaleBias | None, default: None ) –

    Scale and bias of the input data, by default None

  • reg_val (float | None, default: 1e-05 ) –

    Regularization value, by default 1e-5

  • device (str, default: 'cuda' if is_available() else 'cpu' ) –

    Device to use, by default "cuda" if cuda is available, otherwise "cpu"

  • save_epochs_dir (str | None, default: None ) –

    Directory where to save network states at each epoch. If None disabled, by default None

  • verbose (bool, default: True ) –

    Whether to produce verbose output, by default True

Methods:

Source code in src/autoden/algorithms.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
def __init__(
    self,
    model: int | str | NetworkParams | pt.nn.Module | Mapping,
    data_scale_bias: DataScaleBias | None = None,
    reg_val: float | LossRegularizer | None = 1e-5,
    device: str = "cuda" if pt.cuda.is_available() else "cpu",
    save_epochs_dir: str | None = None,
    verbose: bool = True,
) -> None:
    """Initialize the noise2noise method.

    Parameters
    ----------
    model : str | NetworkParams | pt.nn.Module | Mapping | None
        Type of neural network to use or a specific network (or state) to use
    data_scale_bias : DataScaleBias | None, optional
        Scale and bias of the input data, by default None
    reg_val : float | None, optional
        Regularization value, by default 1e-5
    device : str, optional
        Device to use, by default "cuda" if cuda is available, otherwise "cpu"
    save_epochs_dir : str | None, optional
        Directory where to save network states at each epoch.
        If None disabled, by default None
    verbose : bool, optional
        Whether to produce verbose output, by default True
    """
    if isinstance(model, int):
        if self.save_epochs_dir is None:
            raise ValueError("Directory for saving epochs not specified")

        model = load_model_state(self.save_epochs_dir, epoch_num=model)

    if isinstance(model, (str, NetworkParams, Mapping, pt.nn.Module)):
        self.model = create_network(model, device=device)
    else:
        raise ValueError(f"Invalid model {type(model)}")
    if verbose:
        get_num_parameters(self.model, verbose=True)

    self.data_sb = data_scale_bias

    self.reg_val = reg_val
    self.device = device
    self.save_epochs_dir = save_epochs_dir
    self.verbose = verbose

infer

infer(inp: NDArray) -> NDArray

Inference, given an initial stack of images.

Parameters:

  • inp (NDArray) –

    The input stack of images

Returns:

  • NDArray

    The denoised stack of images

Source code in src/autoden/algorithms.py
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
def infer(self, inp: NDArray) -> NDArray:
    """Inference, given an initial stack of images.

    Parameters
    ----------
    inp : NDArray
        The input stack of images

    Returns
    -------
    NDArray
        The denoised stack of images
    """
    # Rescale input
    if self.data_sb is not None:
        inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp

    inp_t = _single_channel_imgs_to_tensor(inp, device=self.device)

    self.model.eval()
    with pt.inference_mode():
        out_t: pt.Tensor = self.model(inp_t)
        output = out_t.to("cpu").numpy().reshape(inp.shape)

    # Rescale output
    if self.data_sb is not None:
        output = (output + self.data_sb.bias_out) / self.data_sb.scale_out

    return output

train_selfsupervised

train_selfsupervised(
    inp: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    mask_shape: int | Sequence[int] | NDArray = 1,
    ratio_blind_spot: float = 0.015,
    algo: str = "adam",
)

Self-supervised training.

Parameters:

  • inp (NDArray) –

    The input images, which will also be targets

  • epochs (int) –

    Number of training epochs

  • tst_inds (Sequence[int] | NDArray) –

    The validation set indices

  • mask_shape (int | Sequence[int] | NDArray, default: 1 ) –

    Shape of the blind spot mask, by default 1.

  • algo (str, default: 'adam' ) –

    Learning algorithm to use, by default "adam"

Source code in src/autoden/algorithms.py
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
def train_selfsupervised(
    self,
    inp: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    mask_shape: int | Sequence[int] | NDArray = 1,
    ratio_blind_spot: float = 0.015,
    algo: str = "adam",
):
    """Self-supervised training.

    Parameters
    ----------
    inp : NDArray
        The input images, which will also be targets
    epochs : int
        Number of training epochs
    tst_inds : Sequence[int] | NDArray
        The validation set indices
    mask_shape : int | Sequence[int] | NDArray
        Shape of the blind spot mask, by default 1.
    algo : str, optional
        Learning algorithm to use, by default "adam"
    """
    num_imgs = inp.shape[0]
    tst_inds = np.array(tst_inds, dtype=int)
    if np.any(tst_inds < 0) or np.any(tst_inds >= num_imgs):
        raise ValueError(
            f"Each cross-validation index should be greater or equal than 0, and less than the number of images {num_imgs}"
        )
    trn_inds = np.delete(np.arange(num_imgs), obj=tst_inds)

    if self.data_sb is None:
        self.data_sb = compute_scaling_selfsupervised(inp)

    # Rescale the datasets
    inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp

    inp_trn = inp[trn_inds]
    inp_tst = inp[tst_inds]

    reg = self._get_regularization()
    losses = self._train_n2v_pixelmask_small(
        inp_trn,
        inp_tst,
        epochs=epochs,
        mask_shape=mask_shape,
        ratio_blind_spot=ratio_blind_spot,
        algo=algo,
        regularizer=reg,
    )

    self._plot_loss_curves(losses, f"Self-supervised {self.__class__.__name__} {algo.upper()}")

train_supervised

train_supervised(
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
)

Supervised training.

Parameters:

  • inp (NDArray) –

    The input images

  • tgt (NDArray) –

    The target images

  • epochs (int) –

    Number of training epochs

  • tst_inds (Sequence[int] | NDArray) –

    The validation set indices

  • algo (str, default: 'adam' ) –

    Learning algorithm to use, by default "adam"

Source code in src/autoden/algorithms.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
def train_supervised(
    self,
    inp: NDArray,
    tgt: NDArray,
    epochs: int,
    tst_inds: Sequence[int] | NDArray,
    algo: str = "adam",
):
    """Supervised training.

    Parameters
    ----------
    inp : NDArray
        The input images
    tgt : NDArray
        The target images
    epochs : int
        Number of training epochs
    tst_inds : Sequence[int] | NDArray
        The validation set indices
    algo : str, optional
        Learning algorithm to use, by default "adam"
    """
    num_imgs = inp.shape[0]
    tst_inds = np.array(tst_inds, dtype=int)
    if np.any(tst_inds < 0) or np.any(tst_inds >= num_imgs):
        raise ValueError(
            f"Each cross-validation index should be greater or equal than 0, and less than the number of images {num_imgs}"
        )
    trn_inds = np.delete(np.arange(num_imgs), obj=tst_inds)

    if tgt.ndim == (inp.ndim - 1):
        tgt = np.tile(tgt[None, ...], [num_imgs, *np.ones_like(tgt.shape)])

    if self.data_sb is None:
        self.data_sb = compute_scaling_supervised(inp, tgt)

    # Rescale the datasets
    inp = inp * self.data_sb.scale_inp - self.data_sb.bias_inp
    tgt = tgt * self.data_sb.scale_tgt - self.data_sb.bias_tgt

    # Create datasets
    dset_trn = (inp[trn_inds], tgt[trn_inds])
    dset_tst = (inp[tst_inds], tgt[tst_inds])

    reg = self._get_regularization()
    losses = self._train_selfsimilar(dset_trn, dset_tst, epochs=epochs, algo=algo, regularizer=reg)

    if self.verbose:
        self._plot_loss_curves(losses, f"Supervised {algo.upper()}")

compute_scaling_selfsupervised

compute_scaling_selfsupervised(
    inp: NDArray,
) -> DataScaleBias

Compute input data scaling and bias for self-supervised learning.

Parameters:

  • inp (NDArray) –

    Input data.

Returns:

  • DataScaleBias

    An instance of DataScaleBias containing the computed scaling and bias values.

Source code in src/autoden/algorithms.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def compute_scaling_selfsupervised(inp: NDArray) -> DataScaleBias:
    """
    Compute input data scaling and bias for self-supervised learning.

    Parameters
    ----------
    inp : NDArray
        Input data.

    Returns
    -------
    DataScaleBias
        An instance of DataScaleBias containing the computed scaling and bias values.
    """
    range_vals_inp = _get_normalization(inp, percentile=0.001)

    sb = DataScaleBias()
    sb.scale_inp = 1 / (range_vals_inp[1] - range_vals_inp[0])
    sb.scale_out = sb.scale_tgt = sb.scale_inp

    sb.bias_inp = range_vals_inp[2] * sb.scale_inp
    sb.bias_out = sb.bias_tgt = sb.bias_inp

    return sb

compute_scaling_supervised

compute_scaling_supervised(
    inp: NDArray, tgt: NDArray
) -> DataScaleBias

Compute input and target data scaling and bias for supervised learning.

Parameters:

  • inp (NDArray) –

    Input data.

  • tgt (NDArray) –

    Target data.

Returns:

  • DataScaleBias

    An instance of DataScaleBias containing the computed scaling and bias values.

Source code in src/autoden/algorithms.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def compute_scaling_supervised(inp: NDArray, tgt: NDArray) -> DataScaleBias:
    """
    Compute input and target data scaling and bias for supervised learning.

    Parameters
    ----------
    inp : NDArray
        Input data.
    tgt : NDArray
        Target data.

    Returns
    -------
    DataScaleBias
        An instance of DataScaleBias containing the computed scaling and bias values.
    """
    range_vals_inp = _get_normalization(inp, percentile=0.001)
    range_vals_tgt = _get_normalization(tgt, percentile=0.001)

    sb = DataScaleBias()
    sb.scale_inp = 1 / (range_vals_inp[1] - range_vals_inp[0])
    sb.scale_tgt = 1 / (range_vals_tgt[1] - range_vals_tgt[0])
    sb.scale_out = sb.scale_tgt

    sb.bias_inp = range_vals_inp[2] * sb.scale_inp
    sb.bias_tgt = range_vals_tgt[2] * sb.scale_tgt
    sb.bias_out = sb.bias_tgt

    return sb