Download model/common/diffusion/predictors_correctors.py from OneScience-Group/MatterGen: direct link, hf CLI and curl.
- Browser
- Download file 3.89 kB
-
https://huggingface.co/OneScience-Group/MatterGen/resolve/main/model/common/diffusion/predictors_correctors.py
- Command line
-
hf download hf://OneScience-Group/MatterGen/model/common/diffusion/predictors_correctors.py
-
curl -L -o predictors_correctors.py https://huggingface.co/OneScience-Group/MatterGen/resolve/main/model/common/diffusion/predictors_correctors.py
3.89 kB
| # Copyright (c) Microsoft Corporation. | |
| # Licensed under the MIT License. | |
| 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): | |
| 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 = (x + score * beta**2 - limit_mean)/(1-beta) + limit_mean | |
| # <=> mean = x / (1-beta) + score * beta**2 / (1-beta) + limit_mean * (1 - 1/(1-beta)) | |
| # => mean_coeff = 1 - x_coeff = 1 - 1/(1-beta) | |
| mean_coeff = 1 - x_coeff | |
| # Sample random noise. | |
| z = sde_lib.make_noise_symmetric_preserve_variance(torch.randn_like(x_coeff)) | |
| assert hasattr(self.corruption, "get_limit_mean") # mypy | |
| 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 | |
| # create a langevin corrector that accepts LatticeVPSDE | |
| class LatticeLangevinDiffCorrector(pc.LangevinCorrector): | |
| 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) | |
| # [batch_size, ] or [num_atoms, ] if batch_idx is not None | |
| 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) | |
| # Average over items, leading to scalars. | |
| grad_norm = grad_norm_square.sqrt().mean() | |
| noise_norm = noise_norm_square.sqrt().mean() | |
| # If gradient is zero (i.e., we are sampling from an improper distribution that's flat over the whole of R^n) | |
| # the step_size blows up. Clip step_size to avoid this. | |
| # The EGNN reports zero scores when there are no edges between nodes. | |
| 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 | |