|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| from __future__ import annotations
|
|
|
| from math import pi
|
| from typing import Optional, Tuple
|
|
|
| import torch
|
| import torch.nn as nn
|
| import torch.nn.functional as F
|
| from einops import rearrange
|
| from torch import Tensor, einsum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| def exists(x) -> bool:
|
| return x is not None
|
|
|
|
|
| def rand_bool(shape, proba: float, device=None) -> Tensor:
|
| if proba <= 0.0:
|
| return torch.zeros(shape, dtype=torch.bool, device=device)
|
| if proba >= 1.0:
|
| return torch.ones(shape, dtype=torch.bool, device=device)
|
| return torch.rand(shape, device=device) < proba
|
|
|
|
|
| def rearrange_many(tensors, pattern: str, **kwargs):
|
| return tuple(rearrange(t, pattern, **kwargs) for t in tensors)
|
|
|
|
|
| @torch.no_grad()
|
| def _time_warp(u: Tensor, kind: str = "cos") -> Tensor:
|
|
|
| if kind == "linear":
|
| return u
|
| if kind == "cos":
|
|
|
| return 0.5 * (1.0 - torch.cos(pi * u))
|
| raise ValueError(f"Unknown time_scheduler: {kind}")
|
|
|
|
|
| class DropPath(nn.Module):
|
| """
|
| Stochastic depth (per-sample). Zera cały residual branch z prawdopodobieństwem
|
| drop_prob w trakcie treningu. W ewaluacji: identity.
|
| """
|
|
|
| def __init__(self, drop_prob: float = 0.0):
|
| super().__init__()
|
| self.drop_prob = float(drop_prob)
|
|
|
| def forward(self, x: Tensor) -> Tensor:
|
| if self.drop_prob == 0.0 or not self.training:
|
| return x
|
| keep = 1.0 - self.drop_prob
|
| shape = (x.shape[0],) + (1,) * (x.ndim - 1)
|
| mask = x.new_empty(shape).bernoulli_(keep)
|
| return x * mask / keep
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class RMSNorm(nn.Module):
|
| def __init__(self, dim: int, eps: float = 1e-8, elementwise_affine: bool = True):
|
| super().__init__()
|
| self.eps = eps
|
| if elementwise_affine:
|
| self.weight = nn.Parameter(torch.ones(dim))
|
| else:
|
| self.register_buffer("weight", torch.ones(dim))
|
|
|
| def forward(self, x: Tensor) -> Tensor:
|
| rms = x.pow(2).mean(dim=-1, keepdim=True).add(self.eps).sqrt()
|
| return x / rms * self.weight
|
|
|
|
|
| def _make_norm(norm_type: str, dim: int) -> nn.Module:
|
| if norm_type is None or norm_type == "none":
|
| return nn.Identity()
|
| if norm_type == "layer":
|
| return nn.LayerNorm(dim)
|
| if norm_type == "rms":
|
| return RMSNorm(dim)
|
| raise ValueError(f"Unknown norm_type: {norm_type}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class SinusoidalTimeEmbedding(nn.Module):
|
| def __init__(self, dim: int):
|
| super().__init__()
|
| assert dim % 2 == 0, "time embedding dim must be even"
|
| self.dim = dim
|
|
|
| def forward(self, t: Tensor) -> Tensor:
|
|
|
| half = self.dim // 2
|
| device = t.device
|
| exponents = torch.arange(half, device=device, dtype=t.dtype)
|
| freqs = torch.exp(
|
| -torch.log(torch.tensor(10000.0, device=device)) * exponents / half
|
| )
|
| args = t[:, None] * freqs[None, :]
|
| return torch.cat([torch.sin(args), torch.cos(args)], dim=-1)
|
|
|
|
|
| def TimePositionalEmbedding(out_features: int, time_embed_dim: int = 128) -> nn.Module:
|
| return nn.Sequential(
|
| SinusoidalTimeEmbedding(time_embed_dim),
|
| nn.Linear(time_embed_dim, out_features),
|
| nn.SiLU(),
|
| nn.Linear(out_features, out_features),
|
| )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class FixedEmbedding(nn.Module):
|
| """
|
| Learned positional embedding o długości 'max_length' i wymiarze 'features'.
|
| Używany jako embedding bezwarunkowy (CFG).
|
| """
|
|
|
| def __init__(self, max_length: int, features: int):
|
| super().__init__()
|
| self.max_length = max_length
|
| self.features = features
|
| if features > 0:
|
| self.embedding = nn.Embedding(max_length, features)
|
| else:
|
| self.register_buffer("dummy", torch.zeros(1))
|
|
|
| def forward(self, x_like: Tensor) -> Tensor:
|
|
|
| batch_size, length = x_like.shape[0], x_like.shape[1]
|
| assert length <= self.max_length, "L must be <= max_length"
|
| device = x_like.device
|
| if self.features == 0:
|
| return x_like.new_zeros(batch_size, length, 0)
|
| pos = torch.arange(length, device=device)
|
| fixed = self.embedding(pos)
|
| fixed = fixed.unsqueeze(0).expand(batch_size, -1, -1)
|
| return fixed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class RotaryEmbedding(nn.Module):
|
| def __init__(self, dim: int, max_seq_len: int = 2048, base: int = 10000):
|
| super().__init__()
|
| assert dim % 2 == 0, "RoPE head dim must be even"
|
| self.dim = dim
|
| inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
|
| self.register_buffer("inv_freq", inv_freq, persistent=False)
|
|
|
| def _build_sin_cos(self, n: int, device: torch.device, dtype: torch.dtype):
|
| positions = torch.arange(n, device=device, dtype=dtype).unsqueeze(1)
|
| angles = positions * self.inv_freq.to(device=device, dtype=dtype)[None, :]
|
| sin = torch.sin(angles)
|
| cos = torch.cos(angles)
|
| sin = torch.stack([sin, sin], dim=-1).reshape(n, self.dim)
|
| cos = torch.stack([cos, cos], dim=-1).reshape(n, self.dim)
|
| return sin, cos
|
|
|
| @staticmethod
|
| def rotate_half(x: Tensor) -> Tensor:
|
| x1, x2 = x[..., ::2], x[..., 1::2]
|
| return torch.stack((-x2, x1), dim=-1).reshape_as(x)
|
|
|
|
|
| def apply_rotary_same(self, q: Tensor, k: Tensor) -> Tuple[Tensor, Tensor]:
|
| n = q.shape[-2]
|
| device, dtype = q.device, q.dtype
|
| sin, cos = self._build_sin_cos(n, device, dtype)
|
| sin = sin.unsqueeze(0).unsqueeze(0)
|
| cos = cos.unsqueeze(0).unsqueeze(0)
|
| q = (q * cos) + (self.rotate_half(q) * sin)
|
| k = (k * cos) + (self.rotate_half(k) * sin)
|
| return q, k
|
|
|
|
|
| def apply_rotary_qk(self, q: Tensor, k: Tensor) -> Tuple[Tensor, Tensor]:
|
| n_q, n_k = q.shape[-2], k.shape[-2]
|
|
|
| sin_q, cos_q = self._build_sin_cos(n_q, q.device, q.dtype)
|
| sin_q = sin_q.unsqueeze(0).unsqueeze(0)
|
| cos_q = cos_q.unsqueeze(0).unsqueeze(0)
|
| q = (q * cos_q) + (self.rotate_half(q) * sin_q)
|
|
|
| sin_k, cos_k = self._build_sin_cos(n_k, k.device, k.dtype)
|
| sin_k = sin_k.unsqueeze(0).unsqueeze(0)
|
| cos_k = cos_k.unsqueeze(0).unsqueeze(0)
|
| k = (k * cos_k) + (self.rotate_half(k) * sin_k)
|
| return q, k
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class FeedForward(nn.Module):
|
| def __init__(self, features: int, multiplier: int):
|
| super().__init__()
|
| mid = features * multiplier
|
| self.net = nn.Sequential(
|
| nn.Linear(features, mid),
|
| nn.SiLU(),
|
| nn.Linear(mid, features),
|
| )
|
|
|
| def forward(self, x: Tensor) -> Tensor:
|
| return self.net(x)
|
|
|
|
|
| class SelfAttention(nn.Module):
|
| def __init__(
|
| self,
|
| features: int,
|
| *,
|
| head_features: int,
|
| num_heads: int,
|
| use_rope: bool = False,
|
| rope_max_seq_len: int = 512,
|
| attn_dropout: float = 0.0,
|
| out_dropout: float = 0.0,
|
| norm_type: str = "rms",
|
| ):
|
| super().__init__()
|
| self.num_heads = num_heads
|
| self.scale = head_features**-0.5
|
| mid = head_features * num_heads
|
|
|
| self.norm = _make_norm(norm_type, features)
|
| self.to_qkv = nn.Linear(features, mid * 3, bias=False)
|
|
|
| self.to_out = nn.Linear(mid, features)
|
| self.attn_dropout = (
|
| nn.Dropout(attn_dropout) if attn_dropout > 0.0 else nn.Identity()
|
| )
|
| self.out_dropout = (
|
| nn.Dropout(out_dropout) if out_dropout > 0.0 else nn.Identity()
|
| )
|
| self.rotary = (
|
| RotaryEmbedding(head_features, max_seq_len=rope_max_seq_len)
|
| if use_rope
|
| else None
|
| )
|
|
|
| def forward(self, x: Tensor) -> Tensor:
|
|
|
| x_n = self.norm(x) if not isinstance(self.norm, nn.Identity) else x
|
| q, k, v = self.to_qkv(x_n).chunk(3, dim=-1)
|
| q, k, v = rearrange_many((q, k, v), "b n (h d) -> b h n d", h=self.num_heads)
|
| if self.rotary is not None:
|
| q, k = self.rotary.apply_rotary_same(q, k)
|
| sim = einsum("b h n d, b h m d -> b h n m", q, k) * self.scale
|
| attn = self.attn_dropout(sim.softmax(dim=-1))
|
| out = einsum("b h n m, b h m d -> b h n d", attn, v)
|
| out = rearrange(out, "b h n d -> b n (h d)")
|
| out = self.out_dropout(self.to_out(out))
|
| return out
|
|
|
|
|
| class CrossAttention(nn.Module):
|
| def __init__(
|
| self,
|
| features_q: int,
|
| features_kv: int,
|
| *,
|
| head_features: int,
|
| num_heads: int,
|
| use_rope: bool = False,
|
| rope_max_seq_len: int = 512,
|
| attn_dropout: float = 0.0,
|
| out_dropout: float = 0.0,
|
| norm_type: str = "rms",
|
| ):
|
| super().__init__()
|
| self.num_heads = num_heads
|
| self.scale = head_features**-0.5
|
| mid = head_features * num_heads
|
|
|
| self.norm_q = _make_norm(norm_type, features_q)
|
| self.norm_kv = _make_norm(norm_type, features_kv)
|
|
|
| self.to_q = nn.Linear(features_q, mid, bias=False)
|
| self.to_kv = nn.Linear(features_kv, mid * 2, bias=False)
|
|
|
| self.to_out = nn.Linear(mid, features_q)
|
| self.attn_dropout = (
|
| nn.Dropout(attn_dropout) if attn_dropout > 0.0 else nn.Identity()
|
| )
|
| self.out_dropout = (
|
| nn.Dropout(out_dropout) if out_dropout > 0.0 else nn.Identity()
|
| )
|
| self.rotary = (
|
| RotaryEmbedding(head_features, max_seq_len=rope_max_seq_len)
|
| if use_rope
|
| else None
|
| )
|
|
|
| def forward(self, x: Tensor, mem: Tensor) -> Tensor:
|
|
|
| x_n = self.norm_q(x) if not isinstance(self.norm_q, nn.Identity) else x
|
| m_n = self.norm_kv(mem) if not isinstance(self.norm_kv, nn.Identity) else mem
|
|
|
| q = self.to_q(x_n)
|
| k, v = self.to_kv(m_n).chunk(2, dim=-1)
|
|
|
| q, k, v = rearrange_many((q, k, v), "b n (h d) -> b h n d", h=self.num_heads)
|
|
|
| if self.rotary is not None:
|
|
|
| q, k = self.rotary.apply_rotary_qk(q, k)
|
|
|
| sim = einsum("b h n d, b h m d -> b h n m", q, k) * self.scale
|
| attn = self.attn_dropout(sim.softmax(dim=-1))
|
| out = einsum("b h n m, b h m d -> b h n d", attn, v)
|
| out = rearrange(out, "b h n d -> b n (h d)")
|
| out = self.out_dropout(self.to_out(out))
|
| return out
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class StyleBlock(nn.Module):
|
| """
|
| Jeden blok:
|
| x = x + DropPath(SelfAttn(x))
|
| x = x + DropPath(CrossAttn(x, mem))
|
| x = x + DropPath(FF(x))
|
| """
|
|
|
| def __init__(
|
| self,
|
| d_model: int,
|
| d_mem: int,
|
| *,
|
| num_heads: int,
|
| head_features: int,
|
| multiplier: int,
|
| use_rope_sa: bool = True,
|
| use_rope_ca: bool = True,
|
| rope_max_seq_len: int = 512,
|
| dropout: float = 0.0,
|
| attn_dropout: float = 0.0,
|
| ff_dropout: float = 0.0,
|
| norm_type: str = "rms",
|
| drop_path: Optional[nn.Module] = None,
|
| ):
|
| super().__init__()
|
| self.self_attn = SelfAttention(
|
| features=d_model,
|
| head_features=head_features,
|
| num_heads=num_heads,
|
| use_rope=use_rope_sa,
|
| rope_max_seq_len=rope_max_seq_len,
|
| attn_dropout=attn_dropout,
|
| out_dropout=dropout,
|
| norm_type=norm_type,
|
| )
|
| self.cross_attn = (
|
| CrossAttention(
|
| features_q=d_model,
|
| features_kv=d_mem,
|
| head_features=head_features,
|
| num_heads=num_heads,
|
| use_rope=use_rope_ca,
|
| rope_max_seq_len=rope_max_seq_len,
|
| attn_dropout=attn_dropout,
|
| out_dropout=dropout,
|
| norm_type=norm_type,
|
| )
|
| if d_mem > 0
|
| else None
|
| )
|
| self.ff_norm = _make_norm(norm_type, d_model)
|
| self.ff = FeedForward(d_model, multiplier)
|
| self.ff_dropout = nn.Dropout(ff_dropout) if ff_dropout > 0.0 else nn.Identity()
|
| self.drop_path = drop_path if drop_path is not None else nn.Identity()
|
|
|
| def forward(self, x: Tensor, mem: Optional[Tensor]) -> Tensor:
|
| x = x + self.drop_path(self.self_attn(x))
|
| if self.cross_attn is not None and exists(mem) and mem.size(-1) > 0:
|
| x = x + self.drop_path(self.cross_attn(x, mem))
|
| ff_in = self.ff_norm(x) if not isinstance(self.ff_norm, nn.Identity) else x
|
| x = x + self.drop_path(self.ff_dropout(self.ff(ff_in)))
|
| return x
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class StyleTransformer1d(nn.Module):
|
| """
|
| Model do przewidywania 3 wektorów stylu (B, 3, 64) w Flow Matching.
|
| 3 tokeny stylu są dekodowane z pomocą self-attn i cross-attn do tokenów
|
| kondycjonujących (embedding).
|
| """
|
|
|
| def __init__(
|
| self,
|
| *,
|
| style_count: int = 3,
|
| channels: int = 64,
|
| context_embedding_features: int = 256,
|
| d_model: int = 256,
|
| num_layers: int = 6,
|
| num_heads: int = 8,
|
| head_features: int = 32,
|
| multiplier: int = 4,
|
| use_rope_sa: bool = True,
|
| use_rope_ca: bool = True,
|
| rope_max_seq_len: int = 512,
|
| time_embed_dim: int = 128,
|
| dropout: float = 0.0,
|
| attn_dropout: float = 0.0,
|
| ff_dropout: float = 0.0,
|
| norm_type: str = "rms",
|
| embedding_max_length: int = 512,
|
| mem_token_keep_prob: float = 1.0,
|
| drop_path_prob: float = 0.0,
|
| ):
|
| super().__init__()
|
| assert head_features % 2 == 0, "head_features must be even for RoPE"
|
| self.style_count = style_count
|
| self.channels = channels
|
| self.context_embedding_features = context_embedding_features
|
| self.d_model = d_model
|
| self.mem_token_keep_prob = float(mem_token_keep_prob)
|
| assert 0.0 < self.mem_token_keep_prob <= 1.0, "keep_prob in (0,1]"
|
| self.drop_path_prob = float(drop_path_prob)
|
|
|
|
|
| self.x_in = nn.Linear(channels, d_model)
|
| self.mem_in = (
|
| nn.Linear(context_embedding_features, d_model)
|
| if context_embedding_features > 0
|
| else None
|
| )
|
|
|
|
|
| self.time_mlp_x = TimePositionalEmbedding(d_model, time_embed_dim)
|
| self.time_mlp_mem = (
|
| TimePositionalEmbedding(d_model, time_embed_dim)
|
| if context_embedding_features > 0
|
| else None
|
| )
|
|
|
|
|
| self.style_id_emb = nn.Embedding(style_count, d_model)
|
|
|
|
|
| self.type_emb = nn.Embedding(2, d_model)
|
|
|
|
|
| self.input_dropout = nn.Dropout(dropout) if dropout > 0.0 else nn.Identity()
|
|
|
|
|
| dps = []
|
| if num_layers > 0 and self.drop_path_prob > 0.0:
|
| steps = [i / max(1, num_layers - 1) for i in range(num_layers)]
|
| dps = [DropPath(self.drop_path_prob * s) for s in steps]
|
| else:
|
| dps = [nn.Identity() for _ in range(num_layers)]
|
|
|
|
|
| self.blocks = nn.ModuleList()
|
| for li in range(num_layers):
|
| self.blocks.append(
|
| StyleBlock(
|
| d_model=d_model,
|
| d_mem=d_model if context_embedding_features > 0 else 0,
|
| num_heads=num_heads,
|
| head_features=head_features,
|
| multiplier=multiplier,
|
| use_rope_sa=use_rope_sa,
|
| use_rope_ca=use_rope_ca,
|
| rope_max_seq_len=rope_max_seq_len,
|
| dropout=dropout,
|
| attn_dropout=attn_dropout,
|
| ff_dropout=ff_dropout,
|
| norm_type=norm_type,
|
| drop_path=dps[li],
|
| )
|
| )
|
|
|
|
|
| self.to_out = nn.Linear(d_model, channels)
|
|
|
|
|
| self.fixed_embedding = FixedEmbedding(
|
| max_length=embedding_max_length, features=context_embedding_features
|
| )
|
|
|
| def _encode_style_tokens(self, x: Tensor, t: Tensor) -> Tensor:
|
|
|
| assert (
|
| x.size(1) == self.style_count and x.size(2) == self.channels
|
| ), "x must be (B, 3, 64)"
|
| b, t_len, _ = x.shape
|
| x_tok = self.x_in(x)
|
|
|
|
|
| style_ids = torch.arange(t_len, device=x.device).unsqueeze(0).expand(b, -1)
|
| x_tok = x_tok + self.style_id_emb(style_ids)
|
|
|
|
|
| x_tok = x_tok + self.type_emb.weight[0]
|
|
|
|
|
| time_bias = self.time_mlp_x(t)
|
| x_tok = x_tok + time_bias.unsqueeze(1)
|
| return x_tok
|
|
|
| def _encode_memory_tokens(self, mem: Tensor, t: Tensor) -> Optional[Tensor]:
|
|
|
| if self.context_embedding_features == 0 or mem.size(-1) == 0:
|
| return None
|
| mem_tok = self.mem_in(mem)
|
| mem_tok = mem_tok + self.type_emb.weight[1]
|
| mem_tok = mem_tok + self.time_mlp_mem(t).unsqueeze(1)
|
| return mem_tok
|
|
|
| def run(self, x: Tensor, time: Tensor, embedding: Tensor) -> Tensor:
|
| """
|
| x: (B, 3, 64)
|
| time: (B,)
|
| embedding: (B, L, D)
|
| return: (B, 3, 64)
|
| """
|
|
|
| x_tok = self._encode_style_tokens(x, time)
|
| mem_tok = self._encode_memory_tokens(embedding, time)
|
|
|
|
|
| x_tok = self.input_dropout(x_tok)
|
| if exists(mem_tok):
|
| mem_tok = self.input_dropout(mem_tok)
|
|
|
| if self.training and self.mem_token_keep_prob < 1.0:
|
| keep = self.mem_token_keep_prob
|
| b, l, _ = mem_tok.shape
|
| mask = mem_tok.new_empty(b, l, 1).bernoulli_(keep)
|
| mem_tok = mem_tok * mask / keep
|
|
|
|
|
| for blk in self.blocks:
|
| x_tok = blk(x_tok, mem_tok)
|
|
|
|
|
| out = self.to_out(x_tok)
|
| return out
|
|
|
| def forward(
|
| self,
|
| x: Tensor,
|
| time: Tensor,
|
| embedding_mask_proba: float = 0.1,
|
| embedding: Optional[Tensor] = None,
|
| embedding_scale: float = 1.0,
|
| ) -> Tensor:
|
| b, device = x.shape[0], x.device
|
|
|
|
|
| if not exists(embedding):
|
| if self.context_embedding_features == 0:
|
| embedding = x.new_zeros(b, 1, 0)
|
| else:
|
| raise AssertionError("embedding must be provided when D > 0")
|
|
|
| fixed_embedding = self.fixed_embedding(embedding)
|
| if embedding_mask_proba > 0.0:
|
| mask = rand_bool((b, 1, 1), proba=embedding_mask_proba, device=device)
|
| embedding = torch.where(mask, fixed_embedding, embedding)
|
|
|
| if embedding_scale != 1.0:
|
| out = self.run(x, time=time, embedding=embedding)
|
| out_u = self.run(x, time=time, embedding=fixed_embedding)
|
| return out_u + (out - out_u) * embedding_scale
|
| else:
|
| return self.run(x, time=time, embedding=embedding)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| class FlowMatching1DFR(nn.Module):
|
| """
|
| Flow Matching z StyleTransformer1d jako siecią prędkości.
|
| Ścieżka:
|
| x_t = ((1 - (1 - sigma) * t) * z + t * x), z ~ N(0, I), t w (0, 1]
|
| Cel:
|
| v*(x_t, t) = x - (1 - sigma) * z
|
| Sieć przewiduje v_theta(x_t, t, cond). Strata: MSE lub SmoothL1.
|
| """
|
|
|
| def __init__(
|
| self,
|
| net: nn.Module,
|
| *,
|
| sigma: float = 1e-5,
|
| time_scheduler: str = "cos",
|
| embedding_mask_proba: float = 0.1,
|
| loss_type: str = "smooth_l1",
|
| huber_delta: float = 0.02,
|
| ):
|
| super().__init__()
|
| self.net = net
|
| self.sigma = float(sigma)
|
| self.time_scheduler = time_scheduler
|
| self.embedding_mask_proba = float(embedding_mask_proba)
|
| assert loss_type in ("mse", "smooth_l1")
|
| self.loss_type = loss_type
|
| self.huber_delta = float(huber_delta)
|
|
|
| @torch.no_grad()
|
| def forward_diffusion(
|
| self, x: Tensor, t: Tensor, noise: Optional[Tensor] = None
|
| ) -> Tuple[Tensor, Tensor, Tensor]:
|
| if noise is None:
|
| noise = torch.randn_like(x)
|
| t_view = t.view(-1, 1, 1)
|
| x_t = ((1.0 - (1.0 - self.sigma) * t_view) * noise) + (t_view * x)
|
| return x_t, noise, t
|
|
|
| def _velocity_target(self, x: Tensor, z: Tensor) -> Tensor:
|
| return x - (1.0 - self.sigma) * z
|
|
|
| def velocity(
|
| self,
|
| x_t: Tensor,
|
| t: Tensor,
|
| *,
|
| embedding: Tensor,
|
| cfg: float = 1.0,
|
| rescale_cfg: float = 0.0,
|
| ) -> Tensor:
|
|
|
| if cfg == 1.0 and rescale_cfg == 0.0:
|
| return self.net(
|
| x_t,
|
| time=t,
|
| embedding=embedding,
|
| embedding_mask_proba=0.0,
|
| embedding_scale=1.0,
|
| )
|
|
|
|
|
| v = self.net.run(x_t, time=t, embedding=embedding)
|
| fixed_emb = self.net.fixed_embedding(embedding)
|
| v_u = self.net.run(x_t, time=t, embedding=fixed_emb)
|
| v_cfg = v + cfg * (v - v_u)
|
|
|
| if rescale_cfg > 0.0:
|
| s_pos = v.std(dim=(-1, -2), keepdim=True).clamp_min(1e-8)
|
| s_cfg = v_cfg.std(dim=(-1, -2), keepdim=True).clamp_min(1e-8)
|
| v_rescaled = v_cfg * (s_pos / s_cfg)
|
| v_cfg = rescale_cfg * v_rescaled + (1.0 - rescale_cfg) * v_cfg
|
| return v_cfg
|
|
|
| def denoise_fn(self, x_t: Tensor, *, t: Tensor, embedding: Tensor) -> Tensor:
|
| v = self.net(
|
| x_t,
|
| time=t,
|
| embedding=embedding,
|
| embedding_mask_proba=0.0,
|
| embedding_scale=1.0,
|
| )
|
| t_view = t.view(-1, 1, 1)
|
| x_hat = x_t + (1.0 - t_view) * v
|
| return x_hat
|
|
|
| def forward(
|
| self,
|
| x: Tensor,
|
| *,
|
| embedding: Tensor,
|
| x_mask: Optional[Tensor] = None,
|
| noise: Optional[Tensor] = None,
|
| ) -> Tuple[Tensor, Tensor]:
|
| B = x.size(0)
|
| device = x.device
|
|
|
|
|
| u = torch.rand(B, device=device).clamp_(1e-5, 1.0)
|
| t = _time_warp(u, kind=self.time_scheduler)
|
|
|
|
|
| x_t, z, t = self.forward_diffusion(x, t, noise=noise)
|
| v_target = self._velocity_target(x, z)
|
|
|
|
|
| v_pred = self.net(
|
| x_t,
|
| time=t,
|
| embedding=embedding,
|
| embedding_mask_proba=self.embedding_mask_proba,
|
| embedding_scale=1.0,
|
| )
|
|
|
|
|
| if x_mask is not None:
|
| m = x_mask[..., None].float()
|
| else:
|
| m = torch.ones_like(v_pred)
|
|
|
| if self.loss_type == "mse":
|
| loss = F.mse_loss(v_pred, v_target, reduction="none")
|
| else:
|
| loss = F.smooth_l1_loss(
|
| v_pred, v_target, reduction="none", beta=self.huber_delta
|
| )
|
|
|
| loss = (loss * m).mean()
|
|
|
| with torch.no_grad():
|
| x_hat = self.denoise_fn(x_t, t=t, embedding=embedding)
|
| return loss, x_hat
|
|
|
|
|
|
|
|
|
|
|
| if __name__ == "__main__":
|
|
|
| net = StyleTransformer1d(
|
| style_count=3,
|
| channels=64,
|
| context_embedding_features=256,
|
| d_model=128,
|
| num_layers=4,
|
| num_heads=4,
|
| head_features=32,
|
| multiplier=3,
|
| use_rope_sa=True,
|
| use_rope_ca=True,
|
| rope_max_seq_len=512,
|
| time_embed_dim=128,
|
| dropout=0.1,
|
| attn_dropout=0.1,
|
| ff_dropout=0.1,
|
| norm_type="rms",
|
| embedding_max_length=512,
|
| mem_token_keep_prob=0.8,
|
| drop_path_prob=0.1,
|
| )
|
|
|
| fm = FlowMatching1D(
|
| net=net,
|
| sigma=1e-5,
|
| time_scheduler="cos",
|
| embedding_mask_proba=0.2,
|
| loss_type="smooth_l1",
|
| huber_delta=0.02,
|
| )
|
|
|
| B, L, D = 6, 14, 256
|
| x = torch.randn(B, 3, 64)
|
| cond = torch.randn(B, L, D)
|
|
|
| loss, x_hat = fm(x, embedding=cond)
|
| print("loss:", float(loss.item()), "x_hat:", tuple(x_hat.shape)) |