Download src/models/dit.py from zz312/RiboSphere: direct link, hf CLI and curl.
- Browser
- Download file 11.5 kB
-
https://huggingface.co/zz312/RiboSphere/resolve/main/src/models/dit.py
- Command line
-
hf download hf://zz312/RiboSphere/src/models/dit.py
-
curl -L -o dit.py https://huggingface.co/zz312/RiboSphere/resolve/main/src/models/dit.py
11.5 kB
| """Conditional Diffusion Transformer used as the RiboSphere denoiser.""" | |
| from __future__ import annotations | |
| import math | |
| from typing import Any | |
| import torch | |
| from torch import Tensor, nn | |
| from .attention import SelfAttention | |
| from .layers import FeedForward | |
| def apply_adaptive_modulation( | |
| inputs: Tensor, | |
| shift: Tensor, | |
| scale: Tensor, | |
| ) -> Tensor: | |
| """Apply adaptive affine modulation over the feature dimension.""" | |
| return inputs * (1 + scale.unsqueeze(-2)) + shift.unsqueeze(-2) | |
| class DiffusionTransformer(nn.Module): | |
| """Conditional diffusion transformer that predicts coordinate flow.""" | |
| def __init__( | |
| self, | |
| *, | |
| num_channels: int, | |
| input_channels: int, | |
| num_layers: int, | |
| num_heads: int, | |
| conditioning_type: str = "cat", | |
| mlp_factor: int = 4, | |
| normalize_queries_and_keys: bool = False, | |
| share_adaln: bool = True, | |
| attention_backend: str = "sdpa", | |
| ) -> None: | |
| super().__init__() | |
| if min(num_channels, input_channels, num_layers, num_heads) <= 0: | |
| raise ValueError("All dimensions and layer counts must be positive.") | |
| if conditioning_type != "cat": | |
| raise ValueError("Only 'cat' conditioning is currently supported.") | |
| self.input_projection = AdaptiveInputProjection( | |
| input_channels, | |
| num_channels, | |
| ) | |
| self.share_adaln = share_adaln | |
| if share_adaln: | |
| self.shared_adaln_modulation = nn.Sequential( | |
| nn.SiLU(), | |
| nn.Linear(num_channels, num_channels * 6, bias=True), | |
| ) | |
| self.blocks = nn.ModuleList( | |
| [ | |
| DiffusionTransformerBlock( | |
| num_channels=num_channels, | |
| num_heads=num_heads, | |
| mlp_factor=mlp_factor, | |
| normalize_queries_and_keys=normalize_queries_and_keys, | |
| attention_backend=attention_backend, | |
| shared_adaln=( | |
| self.shared_adaln_modulation if share_adaln else None | |
| ), | |
| ) | |
| for _ in range(num_layers) | |
| ] | |
| ) | |
| self.timestep_embedding = SinusoidalTimestepEmbedding(num_channels) | |
| self.conditioning_type = conditioning_type | |
| self.condition_embedding = nn.Embedding(2, num_channels) | |
| self.output_projection = AdaptiveOutputProjection( | |
| num_channels, | |
| input_channels, | |
| ) | |
| def forward( | |
| self, | |
| input_states: Tensor, | |
| times: Tensor, | |
| conditioning_states: Tensor | None = None, | |
| ) -> Tensor: | |
| """Predict a vector field for ``[B, L, input_channels]`` states.""" | |
| if input_states.ndim != 3: | |
| raise ValueError("input_states must have shape [B, L, D].") | |
| if times.ndim == 0: | |
| times = times.expand(input_states.shape[0]) | |
| if times.shape != (input_states.shape[0],): | |
| raise ValueError("times must have shape [B].") | |
| if conditioning_states is None: | |
| raise ValueError("conditioning_states must be provided.") | |
| if conditioning_states.shape[:2] != input_states.shape[:2]: | |
| raise ValueError( | |
| "conditioning_states must match input batch and sequence dimensions." | |
| ) | |
| time_conditioning = self.timestep_embedding(times) | |
| hidden_states = self.input_projection( | |
| input_states, | |
| time_conditioning, | |
| ) | |
| condition_shape = conditioning_states.shape[:-1] | |
| device = conditioning_states.device | |
| condition_type_ids = torch.cat( | |
| ( | |
| torch.zeros(condition_shape, dtype=torch.long, device=device), | |
| torch.ones(condition_shape, dtype=torch.long, device=device), | |
| ), | |
| dim=-1, | |
| ) | |
| hidden_states = torch.cat( | |
| [hidden_states, conditioning_states], | |
| dim=-2, | |
| ) | |
| hidden_states = ( | |
| hidden_states + self.condition_embedding(condition_type_ids) | |
| ) | |
| for block in self.blocks: | |
| hidden_states = block(hidden_states, time_conditioning) | |
| sequence_length = input_states.size(1) | |
| hidden_states = hidden_states[:, :sequence_length, :] | |
| return self.output_projection(hidden_states, time_conditioning) | |
| class DiffusionTransformerBlock(nn.Module): | |
| """AdaLN-modulated transformer block.""" | |
| def __init__( | |
| self, | |
| *, | |
| num_channels: int, | |
| num_heads: int, | |
| mlp_factor: int, | |
| normalize_queries_and_keys: bool = False, | |
| dropout: float = 0.1, | |
| shared_adaln: nn.Module | None = None, | |
| attention_backend: str = "sdpa", | |
| ) -> None: | |
| super().__init__() | |
| self.attention_backend = attention_backend | |
| self.attention = SelfAttention( | |
| num_channels, | |
| num_heads, | |
| attention_backend=attention_backend, | |
| dropout=dropout, | |
| normalize_queries_and_keys=normalize_queries_and_keys, | |
| ) | |
| self.feed_forward = FeedForward( | |
| num_channels, | |
| num_channels * mlp_factor, | |
| num_channels, | |
| activation=nn.GELU, | |
| dropout=dropout, | |
| ) | |
| self.norm1 = nn.LayerNorm(num_channels, elementwise_affine=False) | |
| self.norm2 = nn.LayerNorm(num_channels, elementwise_affine=False) | |
| # Retained for checkpoint compatibility with the training architecture. | |
| self.norm3 = nn.LayerNorm(num_channels, elementwise_affine=False) | |
| if shared_adaln is not None: | |
| self.adaptive_norm_modulation = shared_adaln | |
| else: | |
| self.adaptive_norm_modulation = nn.Sequential( | |
| nn.SiLU(), | |
| nn.Linear(num_channels, num_channels * 6, bias=True), | |
| ) | |
| def _get_attention_options(self) -> dict[str, Any]: | |
| if self.attention_backend == "sdpa": | |
| return {"attn_mask": None} | |
| if self.attention_backend == "flex": | |
| return {"block_mask": None, "score_mod": None} | |
| raise RuntimeError( | |
| f"Unsupported attention backend: {self.attention_backend}" | |
| ) | |
| def forward( | |
| self, | |
| hidden_states: Tensor, | |
| time_conditioning: Tensor, | |
| ) -> Tensor: | |
| """Transform hidden states conditioned on diffusion time.""" | |
| adaptive_norm_parameters = self.adaptive_norm_modulation( | |
| time_conditioning | |
| ) | |
| ( | |
| attention_shift, | |
| attention_scale, | |
| attention_gate, | |
| feed_forward_shift, | |
| feed_forward_scale, | |
| feed_forward_gate, | |
| ) = adaptive_norm_parameters.chunk(6, dim=-1) | |
| hidden_states = hidden_states + attention_gate.unsqueeze( | |
| 1 | |
| ) * self.attention( | |
| apply_adaptive_modulation( | |
| self.norm1(hidden_states), | |
| attention_shift, | |
| attention_scale, | |
| ), | |
| **self._get_attention_options(), | |
| ) | |
| hidden_states = hidden_states + feed_forward_gate.unsqueeze( | |
| 1 | |
| ) * self.feed_forward( | |
| apply_adaptive_modulation( | |
| self.norm2(hidden_states), | |
| feed_forward_shift, | |
| feed_forward_scale, | |
| ) | |
| ) | |
| return hidden_states | |
| class AdaptiveInputProjection(nn.Module): | |
| """Project inputs and modulate them with a conditioning vector.""" | |
| def __init__(self, input_channels: int, output_channels: int) -> None: | |
| super().__init__() | |
| self.projection = nn.Linear( | |
| input_channels, | |
| output_channels, | |
| bias=True, | |
| ) | |
| self.norm = nn.LayerNorm( | |
| output_channels, | |
| elementwise_affine=False, | |
| eps=1e-6, | |
| ) | |
| self.adaptive_norm_modulation = nn.Sequential( | |
| nn.SiLU(), | |
| nn.Linear(output_channels, 2 * output_channels, bias=True), | |
| ) | |
| def forward(self, inputs: Tensor, conditioning: Tensor) -> Tensor: | |
| """Project ``inputs`` and apply conditioning-derived shift and scale.""" | |
| shift, scale = self.adaptive_norm_modulation(conditioning).chunk( | |
| 2, | |
| dim=-1, | |
| ) | |
| outputs = self.projection(inputs) | |
| return apply_adaptive_modulation(self.norm(outputs), shift, scale) | |
| class AdaptiveOutputProjection(nn.Module): | |
| """Final adaptive projection adopted from DiT.""" | |
| def __init__(self, model_channels: int, output_channels: int) -> None: | |
| super().__init__() | |
| self.norm = nn.LayerNorm( | |
| model_channels, | |
| elementwise_affine=False, | |
| eps=1e-6, | |
| ) | |
| self.projection = nn.Linear( | |
| model_channels, | |
| output_channels, | |
| bias=True, | |
| ) | |
| self.adaptive_norm_modulation = nn.Sequential( | |
| nn.SiLU(), | |
| nn.Linear(model_channels, 2 * model_channels, bias=True), | |
| ) | |
| def forward(self, inputs: Tensor, conditioning: Tensor) -> Tensor: | |
| """Modulate and project hidden states to the output dimension.""" | |
| shift, scale = self.adaptive_norm_modulation(conditioning).chunk( | |
| 2, | |
| dim=-1, | |
| ) | |
| outputs = apply_adaptive_modulation( | |
| self.norm(inputs), | |
| shift, | |
| scale, | |
| ) | |
| return self.projection(outputs) | |
| class SinusoidalTimestepEmbedding(nn.Module): | |
| """Embed scalar timesteps into vector representations.""" | |
| def __init__( | |
| self, | |
| hidden_size: int, | |
| frequency_embedding_size: int = 256, | |
| ) -> None: | |
| super().__init__() | |
| if hidden_size <= 0 or frequency_embedding_size <= 1: | |
| raise ValueError("Embedding dimensions must be positive.") | |
| self.projection = nn.Sequential( | |
| nn.Linear(frequency_embedding_size, hidden_size, bias=True), | |
| nn.SiLU(), | |
| nn.Linear(hidden_size, hidden_size, bias=True), | |
| ) | |
| self.frequency_embedding_size = frequency_embedding_size | |
| def create_sinusoidal_embedding( | |
| times: Tensor, | |
| embedding_dimension: int, | |
| max_period: int = 10_000, | |
| ) -> Tensor: | |
| """Create sinusoidal embeddings for one-dimensional timesteps.""" | |
| if times.ndim != 1: | |
| raise ValueError("times must be one-dimensional.") | |
| half_dimension = embedding_dimension // 2 | |
| frequencies = torch.exp( | |
| -math.log(max_period) | |
| * torch.arange( | |
| half_dimension, | |
| dtype=torch.float32, | |
| device=times.device, | |
| ) | |
| / half_dimension | |
| ) | |
| phase = times[:, None].float() * frequencies[None] | |
| embedding = torch.cat( | |
| [torch.cos(phase), torch.sin(phase)], | |
| dim=-1, | |
| ) | |
| if embedding_dimension % 2: | |
| embedding = torch.cat( | |
| [embedding, torch.zeros_like(embedding[:, :1])], | |
| dim=-1, | |
| ) | |
| return embedding | |
| def forward(self, times: Tensor) -> Tensor: | |
| """Embed a ``[B]`` tensor of timesteps.""" | |
| frequency_embedding = self.create_sinusoidal_embedding( | |
| times, | |
| self.frequency_embedding_size, | |
| ) | |
| return self.projection(frequency_embedding) | |