| | import abc |
| |
|
| | import torch |
| | import numpy as np |
| |
|
| | from sgmse.util.registry import Registry |
| |
|
| |
|
| | PredictorRegistry = Registry("Predictor") |
| |
|
| |
|
| | class Predictor(abc.ABC): |
| | """The abstract class for a predictor algorithm.""" |
| |
|
| | def __init__(self, sde, score_fn, probability_flow=False): |
| | super().__init__() |
| | self.sde = sde |
| | self.rsde = sde.reverse(score_fn) |
| | self.score_fn = score_fn |
| | self.probability_flow = probability_flow |
| |
|
| | @abc.abstractmethod |
| | def update_fn(self, x, t, *args): |
| | """One update of the predictor. |
| | |
| | Args: |
| | x: A PyTorch tensor representing the current state |
| | t: A Pytorch tensor representing the current time step. |
| | *args: Possibly additional arguments, in particular `y` for OU processes |
| | |
| | Returns: |
| | x: A PyTorch tensor of the next state. |
| | x_mean: A PyTorch tensor. The next state without random noise. Useful for denoising. |
| | """ |
| | pass |
| |
|
| | def debug_update_fn(self, x, t, *args): |
| | raise NotImplementedError(f"Debug update function not implemented for predictor {self}.") |
| |
|
| |
|
| | @PredictorRegistry.register('euler_maruyama') |
| | class EulerMaruyamaPredictor(Predictor): |
| | def __init__(self, sde, score_fn, probability_flow=False): |
| | super().__init__(sde, score_fn, probability_flow=probability_flow) |
| |
|
| | def update_fn(self, x, y, t, *args): |
| | dt = -1. / self.rsde.N |
| | z = torch.randn_like(x) |
| | f, g = self.rsde.sde(x, y, t, *args) |
| | x_mean = x + f * dt |
| | x = x_mean + g[:, None, None, None] * np.sqrt(-dt) * z |
| | return x, x_mean |
| |
|
| |
|
| | @PredictorRegistry.register('reverse_diffusion') |
| | class ReverseDiffusionPredictor(Predictor): |
| | def __init__(self, sde, score_fn, probability_flow=False): |
| | super().__init__(sde, score_fn, probability_flow=probability_flow) |
| |
|
| | def update_fn(self, x, y, t, stepsize): |
| | f, g = self.rsde.discretize(x, y, t, stepsize) |
| | z = torch.randn_like(x) |
| | x_mean = x - f |
| | x = x_mean + g[:, None, None, None] * z |
| | return x, x_mean |
| |
|
| |
|
| | @PredictorRegistry.register('none') |
| | class NonePredictor(Predictor): |
| | """An empty predictor that does nothing.""" |
| |
|
| | def __init__(self, *args, **kwargs): |
| | pass |
| |
|
| | def update_fn(self, x, y, t, *args): |
| | return x, x |
| |
|