from __future__ import annotations import math import torch from torch import nn import torch.nn.functional as F def sinusoidal_timestep_embedding( timesteps: torch.Tensor, dim: int, max_period: int = 10_000, ) -> torch.Tensor: """ Create sinusoidal timestep embeddings """ half_dim = dim // 2 frequencies = torch.exp( -math.log(max_period) * torch.arange( start=0, end=half_dim, dtype=torch.float32, device=timesteps.device, ) / half_dim ) args = timesteps.float()[:, None] * frequencies[None] embedding = torch.cat( [ torch.cos(args), torch.sin(args), ], dim=-1, ) if dim % 2 == 1: embedding = F.pad(embedding, (0, 1)) return embedding class TimestepEmbedding(nn.Module): def __init__( self, embedding_dim: int, time_embed_dim: int, ): super().__init__() self.embedding_dim = embedding_dim self.time_embed_dim = time_embed_dim self.mlp = nn.Sequential( nn.Linear(embedding_dim, time_embed_dim), nn.SiLU(), nn.Linear(time_embed_dim, time_embed_dim), ) def forward(self, timesteps: torch.Tensor) -> torch.Tensor: emb = sinusoidal_timestep_embedding( timesteps=timesteps, dim=self.embedding_dim, ) emb = self.mlp(emb) return emb