Spaces:
Running on Zero
Running on Zero
| import torch | |
| import torch.nn as nn | |
| class ScalarQuantizationLayer(nn.Module): | |
| def __init__(self, in_dim, out_dim, latent_dim: int = 64, scale: int = 9): | |
| super().__init__() | |
| self.in_dim = in_dim | |
| self.out_dim = out_dim | |
| self.latent_dim = latent_dim | |
| self.scale = scale | |
| self.in_proj = nn.Linear(in_dim, latent_dim) | |
| self.out_proj = nn.Linear(latent_dim, out_dim) | |
| def forward(self, hidden, do_sample: bool = False, fsq_temperature: float = 1.0): | |
| """Forward pass with optional stochastic rounding. | |
| Args: | |
| hidden: Input tensor of shape (..., in_dim). | |
| do_sample: If True, use stochastic (probabilistic) rounding instead | |
| of deterministic ``torch.round``. Only effective during eval. | |
| fsq_temperature: Controls randomness of stochastic rounding. | |
| * 1.0 β raw probability (fractional part as-is) | |
| * < 1.0 β more deterministic (sharper, closer to greedy) | |
| * > 1.0 β more random (flatter, more diversity) | |
| """ | |
| hidden = self.in_proj(hidden) | |
| hidden = torch.tanh(hidden) | |
| if self.training: | |
| quantized = torch.round(hidden * self.scale) / self.scale | |
| hidden = hidden + (quantized - hidden).detach() | |
| else: | |
| if do_sample and fsq_temperature > 0.0: | |
| hidden = self._stochastic_round(hidden, fsq_temperature) | |
| else: | |
| hidden = torch.round(hidden * self.scale) / self.scale | |
| return self.out_proj(hidden) | |
| def _stochastic_round(self, hidden: torch.Tensor, temperature: float) -> torch.Tensor: | |
| """Stochastic rounding with optional temperature scaling. | |
| For each scalar value ``x = hidden * scale``, the probability of | |
| rounding *up* is the fractional part ``Ξ = x - floor(x)``. When | |
| ``temperature != 1.0``, we rescale the corresponding logit | |
| ``log(Ξ / (1-Ξ)) / T`` to sharpen or flatten the distribution. | |
| """ | |
| scaled = hidden * self.scale | |
| floor_val = torch.floor(scaled) | |
| frac = scaled - floor_val # β [0, 1) | |
| if temperature != 1.0: | |
| # Logit-based temperature scaling | |
| eps = 1e-7 | |
| frac_clamped = frac.clamp(eps, 1.0 - eps) | |
| logit = torch.log(frac_clamped / (1.0 - frac_clamped)) | |
| prob_ceil = torch.sigmoid(logit / temperature) | |
| else: | |
| prob_ceil = frac | |
| # Bernoulli sample: 1 β round up, 0 β round down | |
| ceil_mask = torch.bernoulli(prob_ceil) | |
| quantized = (floor_val + ceil_mask) / self.scale | |
| return quantized |