| |
| |
|
|
| import torch |
|
|
| from ...common.diffusion import corruption as sde_lib |
| from ...common.utils.data_utils import compute_lattice_polar_decomposition |
| from ...diffusion.corruption.corruption import Corruption, maybe_expand |
| from ...diffusion.data.batched_data import BatchedData |
| from ...diffusion.sampling import predictors_correctors as pc |
| from ...diffusion.sampling.predictors import AncestralSamplingPredictor |
|
|
| SampleAndMean = tuple[torch.Tensor, torch.Tensor] |
|
|
|
|
| class LatticeAncestralSamplingPredictor(AncestralSamplingPredictor): |
| @classmethod |
| def is_compatible(cls, corruption: Corruption) -> bool: |
| _super = super() |
| assert hasattr(_super, "is_compatible") |
| return _super.is_compatible(corruption) or isinstance(corruption, sde_lib.LatticeVPSDE) |
|
|
| def update_given_score( |
| self, |
| *, |
| x: torch.Tensor, |
| t: torch.Tensor, |
| dt: torch.Tensor, |
| batch_idx: torch.LongTensor, |
| score: torch.Tensor, |
| batch: BatchedData | None, |
| ) -> SampleAndMean: |
| x_coeff, score_coeff, std = self._get_coeffs( |
| x=x, |
| t=t, |
| dt=dt, |
| batch_idx=batch_idx, |
| batch=batch, |
| ) |
| |
| |
| |
| mean_coeff = 1 - x_coeff |
| |
| z = sde_lib.make_noise_symmetric_preserve_variance(torch.randn_like(x_coeff)) |
| assert hasattr(self.corruption, "get_limit_mean") |
| mean = ( |
| x_coeff * x |
| + score_coeff * score |
| + mean_coeff * self.corruption.get_limit_mean(x=x, batch=batch) |
| ) |
| sample = mean + std * z |
| return sample, mean |
|
|
|
|
| |
| class LatticeLangevinDiffCorrector(pc.LangevinCorrector): |
| @classmethod |
| def is_compatible(cls, corruption: Corruption) -> bool: |
| _super = super() |
| assert hasattr(_super, "is_compatible") |
| return _super.is_compatible(corruption) or isinstance(corruption, sde_lib.LatticeVPSDE) |
|
|
| def step_given_score( |
| self, |
| *, |
| x: torch.Tensor, |
| batch_idx: torch.LongTensor | None, |
| score: torch.Tensor, |
| t: torch.Tensor, |
| dt: torch.Tensor, |
| ) -> SampleAndMean: |
| assert isinstance(self.corruption, sde_lib.LatticeVPSDE) |
| alpha = self.get_alpha(t, dt=dt) |
| snr = self.snr |
| noise = torch.randn_like(x) |
| noise = sde_lib.make_noise_symmetric_preserve_variance(noise) |
|
|
| |
| grad_norm_square = torch.square(score).reshape(score.shape[0], -1).sum(dim=1) |
| noise_norm_square = torch.square(noise).reshape(noise.shape[0], -1).sum(dim=1) |
| |
| grad_norm = grad_norm_square.sqrt().mean() |
| noise_norm = noise_norm_square.sqrt().mean() |
|
|
| |
| |
| |
| step_size = (snr * noise_norm / grad_norm) ** 2 * 2 * alpha |
| step_size = torch.minimum(step_size, self.max_step_size) |
| step_size[grad_norm == 0, :] = self.max_step_size |
| step_size = maybe_expand(step_size, batch_idx, score) |
| mean = x + step_size * score |
| x = mean + torch.sqrt(step_size * 2) * noise |
|
|
| x = compute_lattice_polar_decomposition(x) |
| mean = compute_lattice_polar_decomposition(mean) |
| return x, mean |
|
|