combostoc / models.py
suvadityamuk's picture
suvadityamuk HF Staff
Add ComboStoc ZeroGPU app
0f8e260 verified
Raw
History Blame Contribute Delete
13.8 kB
import torch
import torch.nn as nn
import numpy as np
import math
from timm.models.vision_transformer import PatchEmbed, Attention, Mlp
# def modulate(x, shift, scale):
# return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
def modulate(x, shift, scale):
return x * (1 + scale) + shift
class TimestepEmbedder(nn.Module):
"""
Embeds scalar timesteps into vector representations.
"""
def __init__(self, input_size, patch_size, in_channels, hidden_size, frequency_embedding_size=256):
# (self, hidden_size, frequency_embedding_size=256):
compress_size = 4
super().__init__()
self.mlp = nn.Sequential(
nn.Linear(frequency_embedding_size, compress_size, bias=True),
nn.SiLU(),
nn.Linear(compress_size, compress_size, bias=True),
)
self.frequency_embedding_size = frequency_embedding_size
self.patchEmb = PatchEmbed(input_size, patch_size, in_channels*compress_size, hidden_size, norm_layer=None, bias=True)
@staticmethod
def timestep_embedding(t, dim, max_period=10000):
"""
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.
"""
half = dim // 2
freqs = torch.exp(
-math.log(max_period) * torch.arange(start=0, end=half, dtype=torch.float32) / half
).to(device=t.device)
args = t[..., None].float() * freqs[None]
embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
if dim % 2:
embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1)
return embedding
def forward(self, t):
t_freq = self.timestep_embedding(t, self.frequency_embedding_size)
t_freq = self.mlp(t_freq)
t_freq = torch.einsum('nchwf->ncfhw',t_freq)
t_freq = t_freq.reshape(t_freq.shape[0], -1, t_freq.shape[3], t_freq.shape[4])
t_emb = self.patchEmb(t_freq)
return t_emb
class LabelEmbedder(nn.Module):
"""
Embeds class labels into vector representations. Also handles label dropout for classifier-free guidance.
"""
def __init__(self, num_classes, hidden_size, dropout_prob):
super().__init__()
use_cfg_embedding = dropout_prob > 0
self.embedding_table = nn.Embedding(num_classes + use_cfg_embedding, hidden_size)
self.num_classes = num_classes
self.dropout_prob = dropout_prob
def token_drop(self, labels, force_drop_ids=None):
"""
Drops labels to enable classifier-free guidance.
"""
if force_drop_ids is None:
drop_ids = torch.rand(labels.shape[0], device=labels.device) < self.dropout_prob
else:
drop_ids = force_drop_ids == 1
labels = torch.where(drop_ids, self.num_classes, labels)
return labels
def forward(self, labels, train, force_drop_ids=None):
use_dropout = self.dropout_prob > 0
if (train and use_dropout) or (force_drop_ids is not None):
labels = self.token_drop(labels, force_drop_ids)
embeddings = self.embedding_table(labels)
return embeddings
class ComboStocBlock(nn.Module):
def __init__(self, hidden_size, num_heads, mlp_ratio=4.0, **block_kwargs):
super().__init__()
self.norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
self.attn = Attention(hidden_size, num_heads=num_heads, qkv_bias=True, **block_kwargs)
self.norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
mlp_hidden_dim = int(hidden_size * mlp_ratio)
approx_gelu = lambda: nn.GELU(approximate="tanh")
self.mlp = Mlp(in_features=hidden_size, hidden_features=mlp_hidden_dim, act_layer=approx_gelu, drop=0)
self.adaLN_modulation = nn.Sequential(
nn.SiLU(),
nn.Linear(hidden_size, 6 * hidden_size, bias=True)
)
def forward(self, x, c):
shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.adaLN_modulation(c).chunk(6, dim=-1)
x = x + gate_msa * self.attn(modulate(self.norm1(x), shift_msa, scale_msa))
x = x + gate_mlp * self.mlp(modulate(self.norm2(x), shift_mlp, scale_mlp))
return x
class FinalLayer(nn.Module):
def __init__(self, hidden_size, patch_size, out_channels):
super().__init__()
self.norm_final = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
self.linear = nn.Linear(hidden_size, patch_size * patch_size * out_channels, bias=True)
self.adaLN_modulation = nn.Sequential(
nn.SiLU(),
nn.Linear(hidden_size, 2 * hidden_size, bias=True)
)
def forward(self, x, c):
shift, scale = self.adaLN_modulation(c).chunk(2, dim=-1)
x = modulate(self.norm_final(x), shift, scale)
x = self.linear(x)
return x
class ComboStoc(nn.Module):
def __init__(
self,
input_size=32,
patch_size=2,
in_channels=4,
hidden_size=1152,
depth=28,
num_heads=16,
mlp_ratio=4.0,
class_dropout_prob=0.1,
num_classes=1000,
learn_sigma=True,
):
super().__init__()
self.learn_sigma = learn_sigma
self.in_channels = in_channels
self.out_channels = in_channels * 2 if learn_sigma else in_channels
self.patch_size = patch_size
self.num_heads = num_heads
self.x_embedder = PatchEmbed(input_size, patch_size, in_channels, hidden_size, bias=True)
# self.t_embedder = TimestepEmbedder(hidden_size)
self.t_embedder = TimestepEmbedder(input_size, patch_size, in_channels, hidden_size, frequency_embedding_size = 256)
self.y_embedder = LabelEmbedder(num_classes, hidden_size, class_dropout_prob)
num_patches = self.x_embedder.num_patches
# Will use fixed sin-cos embedding:
self.pos_embed = nn.Parameter(torch.zeros(1, num_patches, hidden_size), requires_grad=False)
self.blocks = nn.ModuleList([
ComboStocBlock(hidden_size, num_heads, mlp_ratio=mlp_ratio) for _ in range(depth)
])
self.final_layer = FinalLayer(hidden_size, patch_size, self.out_channels)
self.initialize_weights()
def initialize_weights(self):
# Initialize transformer layers:
def _basic_init(module):
if isinstance(module, nn.Linear):
torch.nn.init.xavier_uniform_(module.weight)
if module.bias is not None:
nn.init.constant_(module.bias, 0)
self.apply(_basic_init)
# Initialize (and freeze) pos_embed by sin-cos embedding:
pos_embed = get_2d_sincos_pos_embed(self.pos_embed.shape[-1], int(self.x_embedder.num_patches ** 0.5))
self.pos_embed.data.copy_(torch.from_numpy(pos_embed).float().unsqueeze(0))
# Initialize patch_embed like nn.Linear (instead of nn.Conv2d):
w = self.x_embedder.proj.weight.data
nn.init.xavier_uniform_(w.view([w.shape[0], -1]))
nn.init.constant_(self.x_embedder.proj.bias, 0)
# Initialize label embedding table:
nn.init.normal_(self.y_embedder.embedding_table.weight, std=0.02)
# Initialize timestep embedding MLP:
nn.init.normal_(self.t_embedder.mlp[0].weight, std=0.02)
nn.init.normal_(self.t_embedder.mlp[2].weight, std=0.02)
w = self.t_embedder.patchEmb.proj.weight.data
nn.init.xavier_uniform_(w.view([w.shape[0], -1]))
nn.init.constant_(self.t_embedder.patchEmb.proj.bias, 0)
# Zero-out adaLN modulation layers in ComboStoc blocks:
for block in self.blocks:
nn.init.constant_(block.adaLN_modulation[-1].weight, 0)
nn.init.constant_(block.adaLN_modulation[-1].bias, 0)
# Zero-out output layers:
nn.init.constant_(self.final_layer.adaLN_modulation[-1].weight, 0)
nn.init.constant_(self.final_layer.adaLN_modulation[-1].bias, 0)
nn.init.constant_(self.final_layer.linear.weight, 0)
nn.init.constant_(self.final_layer.linear.bias, 0)
def unpatchify(self, x):
c = self.out_channels
p = self.x_embedder.patch_size[0]
h = w = int(x.shape[1] ** 0.5)
assert h * w == x.shape[1]
x = x.reshape(shape=(x.shape[0], h, w, p, p, c))
x = torch.einsum('nhwpqc->nchpwq', x)
imgs = x.reshape(shape=(x.shape[0], c, h * p, h * p))
return imgs
def ckpt_wrapper(self, module):
def ckpt_forward(*inputs):
outputs = module(*inputs)
return outputs
return ckpt_forward
def forward(self, x, t, y):
x_size = x.size()
x = self.x_embedder(x) + self.pos_embed # (N, T, D), where T = H * W / patch_size ** 2
if t.shape != x_size: # if t is not of shape x, expand it. haopan
dims = [1] * (len(x_size) - 1)
t = t.view(t.size(0), *dims)
t = t.repeat(1, x_size[1], x_size[2], x_size[3])
t = self.t_embedder(t) # (N, T, D)
y = self.y_embedder(y, self.training) # (N, D)
y = y.unsqueeze(1) # (N, 1, D)
c = t + y # (N, T, D)
for block in self.blocks:
# x = block(x, c) # (N, T, D)
x = torch.utils.checkpoint.checkpoint(self.ckpt_wrapper(block), x, c, use_reentrant=False) # (N, T, D)
x = self.final_layer(x, c) # (N, T, patch_size ** 2 * out_channels)
x = self.unpatchify(x) # (N, out_channels, H, W)
if self.learn_sigma:
x, _ = x.chunk(2, dim=1)
return x
def forward_with_cfg(self, x, t, y, cfg_scale):
half = x[: len(x) // 2]
combined = torch.cat([half, half], dim=0)
model_out = self.forward(combined, t, y)
eps, rest = model_out[:, :3], model_out[:, 3:]
cond_eps, uncond_eps = torch.split(eps, len(eps) // 2, dim=0)
half_eps = uncond_eps + cfg_scale * (cond_eps - uncond_eps)
eps = torch.cat([half_eps, half_eps], dim=0)
return torch.cat([eps, rest], dim=1)
def get_2d_sincos_pos_embed(embed_dim, grid_size, cls_token=False, extra_tokens=0):
grid_h = np.arange(grid_size, dtype=np.float32)
grid_w = np.arange(grid_size, dtype=np.float32)
grid = np.meshgrid(grid_w, grid_h) # here w goes first
grid = np.stack(grid, axis=0)
grid = grid.reshape([2, 1, grid_size, grid_size])
pos_embed = get_2d_sincos_pos_embed_from_grid(embed_dim, grid)
if cls_token and extra_tokens > 0:
pos_embed = np.concatenate([np.zeros([extra_tokens, embed_dim]), pos_embed], axis=0)
return pos_embed
def get_2d_sincos_pos_embed_from_grid(embed_dim, grid):
assert embed_dim % 2 == 0
# use half of dimensions to encode grid_h
emb_h = get_1d_sincos_pos_embed_from_grid(embed_dim // 2, grid[0]) # (H*W, D/2)
emb_w = get_1d_sincos_pos_embed_from_grid(embed_dim // 2, grid[1]) # (H*W, D/2)
emb = np.concatenate([emb_h, emb_w], axis=1) # (H*W, D)
return emb
def get_1d_sincos_pos_embed_from_grid(embed_dim, pos):
assert embed_dim % 2 == 0
omega = np.arange(embed_dim // 2, dtype=np.float64)
omega /= embed_dim / 2.
omega = 1. / 10000**omega # (D/2,)
pos = pos.reshape(-1) # (M,)
out = np.einsum('m,d->md', pos, omega) # (M, D/2), outer product
emb_sin = np.sin(out) # (M, D/2)
emb_cos = np.cos(out) # (M, D/2)
emb = np.concatenate([emb_sin, emb_cos], axis=1) # (M, D)
return emb
def ComboStoc_XL_2(**kwargs):
return ComboStoc(depth=28, hidden_size=1152, patch_size=2, num_heads=16, **kwargs)
def ComboStoc_XL_4(**kwargs):
return ComboStoc(depth=28, hidden_size=1152, patch_size=4, num_heads=16, **kwargs)
def ComboStoc_XL_8(**kwargs):
return ComboStoc(depth=28, hidden_size=1152, patch_size=8, num_heads=16, **kwargs)
def ComboStoc_L_2(**kwargs):
return ComboStoc(depth=24, hidden_size=1024, patch_size=2, num_heads=16, **kwargs)
def ComboStoc_L_4(**kwargs):
return ComboStoc(depth=24, hidden_size=1024, patch_size=4, num_heads=16, **kwargs)
def ComboStoc_L_8(**kwargs):
return ComboStoc(depth=24, hidden_size=1024, patch_size=8, num_heads=16, **kwargs)
def ComboStoc_B_2(**kwargs):
return ComboStoc(depth=12, hidden_size=768, patch_size=2, num_heads=12, **kwargs)
def ComboStoc_B_4(**kwargs):
return ComboStoc(depth=12, hidden_size=768, patch_size=4, num_heads=12, **kwargs)
def ComboStoc_B_8(**kwargs):
return ComboStoc(depth=12, hidden_size=768, patch_size=8, num_heads=12, **kwargs)
def ComboStoc_S_2(**kwargs):
return ComboStoc(depth=12, hidden_size=384, patch_size=2, num_heads=6, **kwargs)
def ComboStoc_S_4(**kwargs):
return ComboStoc(depth=12, hidden_size=384, patch_size=4, num_heads=6, **kwargs)
def ComboStoc_S_8(**kwargs):
return ComboStoc(depth=12, hidden_size=384, patch_size=8, num_heads=6, **kwargs)
ComboStoc_models = {
'ComboStoc-XL/2': ComboStoc_XL_2, 'ComboStoc-XL/4': ComboStoc_XL_4, 'ComboStoc-XL/8': ComboStoc_XL_8,
'ComboStoc-L/2': ComboStoc_L_2, 'ComboStoc-L/4': ComboStoc_L_4, 'ComboStoc-L/8': ComboStoc_L_8,
'ComboStoc-B/2': ComboStoc_B_2, 'ComboStoc-B/4': ComboStoc_B_4, 'ComboStoc-B/8': ComboStoc_B_8,
'ComboStoc-S/2': ComboStoc_S_2, 'ComboStoc-S/4': ComboStoc_S_4, 'ComboStoc-S/8': ComboStoc_S_8,
}