|
import torch |
|
import torch.nn as nn |
|
|
|
|
|
|
|
|
|
class TimestepEmbedder(nn.Module): |
|
""" |
|
Embeds scalar timesteps into vector representations. |
|
""" |
|
|
|
def __init__(self, dim, frequency_embedding_size, max_period): |
|
super().__init__() |
|
self.mlp = nn.Sequential( |
|
nn.Linear(frequency_embedding_size, dim), |
|
nn.SiLU(), |
|
nn.Linear(dim, dim), |
|
) |
|
self.dim = dim |
|
self.max_period = max_period |
|
assert dim % 2 == 0, 'dim must be even.' |
|
|
|
with torch.autocast('cuda', enabled=False): |
|
self.freqs = nn.Buffer( |
|
1.0 / (10000**(torch.arange(0, frequency_embedding_size, 2, dtype=torch.float32) / |
|
frequency_embedding_size)), |
|
persistent=False) |
|
freq_scale = 10000 / max_period |
|
self.freqs = freq_scale * self.freqs |
|
|
|
def timestep_embedding(self, t): |
|
""" |
|
Create sinusoidal timestep embeddings. |
|
:param t: a 1-D Tensor of N indices, one per batch element. |
|
These may be fractional. |
|
:param dim: the dimension of the output. |
|
:param max_period: controls the minimum frequency of the embeddings. |
|
:return: an (N, D) Tensor of positional embeddings. |
|
""" |
|
|
|
|
|
args = t[:, None].float() * self.freqs[None] |
|
embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1) |
|
return embedding |
|
|
|
def forward(self, t): |
|
t_freq = self.timestep_embedding(t).to(t.dtype) |
|
t_emb = self.mlp(t_freq) |
|
return t_emb |
|
|