| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import numpy as np |
| | import torch |
| | import torch.nn as nn |
| | import torch.utils.checkpoint |
| | from einops import rearrange |
| | from timm.models.vision_transformer import Mlp |
| |
|
| | from opensora.acceleration.checkpoint import auto_grad_checkpoint |
| | from opensora.models.layers.blocks import ( |
| | Attention, |
| | CaptionEmbedder, |
| | FinalLayer, |
| | LabelEmbedder, |
| | PatchEmbed3D, |
| | TimestepEmbedder, |
| | approx_gelu, |
| | get_1d_sincos_pos_embed, |
| | get_2d_sincos_pos_embed, |
| | get_layernorm, |
| | modulate, |
| | ) |
| | from opensora.registry import MODELS |
| | from opensora.utils.ckpt_utils import load_checkpoint |
| |
|
| |
|
| | class DiTBlock(nn.Module): |
| | """ |
| | A DiT block with adaptive layer norm zero (adaLN-Zero) conditioning. |
| | """ |
| |
|
| | def __init__( |
| | self, |
| | hidden_size, |
| | num_heads, |
| | mlp_ratio=4.0, |
| | enable_flashattn=False, |
| | enable_layernorm_kernel=False, |
| | ): |
| | super().__init__() |
| | self.hidden_size = hidden_size |
| | self.num_heads = num_heads |
| | self.enable_flashattn = enable_flashattn |
| | mlp_hidden_dim = int(hidden_size * mlp_ratio) |
| |
|
| | self.norm1 = get_layernorm(hidden_size, eps=1e-6, affine=False, use_kernel=enable_layernorm_kernel) |
| | self.attn = Attention( |
| | hidden_size, |
| | num_heads=num_heads, |
| | qkv_bias=True, |
| | enable_flashattn=enable_flashattn, |
| | ) |
| | self.norm2 = get_layernorm(hidden_size, eps=1e-6, affine=False, use_kernel=enable_layernorm_kernel) |
| | 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.unsqueeze(1) * self.attn(modulate(self.norm1, x, shift_msa, scale_msa)) |
| | x = x + gate_mlp.unsqueeze(1) * self.mlp(modulate(self.norm2, x, shift_mlp, scale_mlp)) |
| | return x |
| |
|
| |
|
| | @MODELS.register_module() |
| | class DiT(nn.Module): |
| | """ |
| | Diffusion model with a Transformer backbone. |
| | """ |
| |
|
| | def __init__( |
| | self, |
| | input_size=(16, 32, 32), |
| | in_channels=4, |
| | patch_size=(1, 2, 2), |
| | hidden_size=1152, |
| | depth=28, |
| | num_heads=16, |
| | mlp_ratio=4.0, |
| | class_dropout_prob=0.1, |
| | learn_sigma=True, |
| | condition="text", |
| | no_temporal_pos_emb=False, |
| | caption_channels=512, |
| | model_max_length=77, |
| | dtype=torch.float32, |
| | enable_flashattn=False, |
| | enable_layernorm_kernel=False, |
| | ): |
| | 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.hidden_size = hidden_size |
| | self.patch_size = patch_size |
| | self.input_size = input_size |
| | num_patches = np.prod([input_size[i] // patch_size[i] for i in range(3)]) |
| | self.num_patches = num_patches |
| | self.num_temporal = input_size[0] // patch_size[0] |
| | self.num_spatial = num_patches // self.num_temporal |
| | self.num_heads = num_heads |
| | self.dtype = dtype |
| | self.use_text_encoder = not condition.startswith("label") |
| | if enable_flashattn: |
| | assert dtype in [ |
| | torch.float16, |
| | torch.bfloat16, |
| | ], f"Flash attention only supports float16 and bfloat16, but got {self.dtype}" |
| | self.no_temporal_pos_emb = no_temporal_pos_emb |
| | self.mlp_ratio = mlp_ratio |
| | self.depth = depth |
| |
|
| | self.register_buffer("pos_embed_spatial", self.get_spatial_pos_embed()) |
| | self.register_buffer("pos_embed_temporal", self.get_temporal_pos_embed()) |
| |
|
| | self.x_embedder = PatchEmbed3D(patch_size, in_channels, embed_dim=hidden_size) |
| | if not self.use_text_encoder: |
| | num_classes = int(condition.split("_")[-1]) |
| | self.y_embedder = LabelEmbedder(num_classes, hidden_size, class_dropout_prob) |
| | else: |
| | self.y_embedder = CaptionEmbedder( |
| | in_channels=caption_channels, |
| | hidden_size=hidden_size, |
| | uncond_prob=class_dropout_prob, |
| | act_layer=approx_gelu, |
| | token_num=1, |
| | ) |
| | self.t_embedder = TimestepEmbedder(hidden_size) |
| | self.blocks = nn.ModuleList( |
| | [ |
| | DiTBlock( |
| | hidden_size, |
| | num_heads, |
| | mlp_ratio=mlp_ratio, |
| | enable_flashattn=enable_flashattn, |
| | enable_layernorm_kernel=enable_layernorm_kernel, |
| | ) |
| | for _ in range(depth) |
| | ] |
| | ) |
| | self.final_layer = FinalLayer(hidden_size, np.prod(self.patch_size), self.out_channels) |
| |
|
| | self.initialize_weights() |
| | self.enable_flashattn = enable_flashattn |
| | self.enable_layernorm_kernel = enable_layernorm_kernel |
| |
|
| | def get_spatial_pos_embed(self): |
| | pos_embed = get_2d_sincos_pos_embed( |
| | self.hidden_size, |
| | self.input_size[1] // self.patch_size[1], |
| | ) |
| | pos_embed = torch.from_numpy(pos_embed).float().unsqueeze(0).requires_grad_(False) |
| | return pos_embed |
| |
|
| | def get_temporal_pos_embed(self): |
| | pos_embed = get_1d_sincos_pos_embed( |
| | self.hidden_size, |
| | self.input_size[0] // self.patch_size[0], |
| | ) |
| | pos_embed = torch.from_numpy(pos_embed).float().unsqueeze(0).requires_grad_(False) |
| | return pos_embed |
| |
|
| | def unpatchify(self, x): |
| | c = self.out_channels |
| | t, h, w = [self.input_size[i] // self.patch_size[i] for i in range(3)] |
| | pt, ph, pw = self.patch_size |
| |
|
| | x = x.reshape(shape=(x.shape[0], t, h, w, pt, ph, pw, c)) |
| | x = rearrange(x, "n t h w r p q c -> n c t r h p w q") |
| | imgs = x.reshape(shape=(x.shape[0], c, t * pt, h * ph, w * pw)) |
| | return imgs |
| |
|
| | def forward(self, x, t, y): |
| | """ |
| | Forward pass of DiT. |
| | x: (B, C, T, H, W) tensor of inputs |
| | t: (B,) tensor of diffusion timesteps |
| | y: list of text |
| | """ |
| | |
| | x = x.to(self.dtype) |
| |
|
| | |
| | x = self.x_embedder(x) |
| | x = rearrange(x, "b (t s) d -> b t s d", t=self.num_temporal, s=self.num_spatial) |
| | x = x + self.pos_embed_spatial |
| | if not self.no_temporal_pos_emb: |
| | x = rearrange(x, "b t s d -> b s t d") |
| | x = x + self.pos_embed_temporal |
| | x = rearrange(x, "b s t d -> b (t s) d") |
| | else: |
| | x = rearrange(x, "b t s d -> b (t s) d") |
| |
|
| | t = self.t_embedder(t, dtype=x.dtype) |
| | y = self.y_embedder(y, self.training) |
| | if self.use_text_encoder: |
| | y = y.squeeze(1).squeeze(1) |
| | condition = t + y |
| |
|
| | |
| | for _, block in enumerate(self.blocks): |
| | c = condition |
| | x = auto_grad_checkpoint(block, x, c) |
| |
|
| | |
| | x = self.final_layer(x, condition) |
| | x = self.unpatchify(x) |
| |
|
| | |
| | x = x.to(torch.float32) |
| | return x |
| |
|
| | def initialize_weights(self): |
| | |
| | def _basic_init(module): |
| | if isinstance(module, nn.Linear): |
| | if module.weight.requires_grad_: |
| | torch.nn.init.xavier_uniform_(module.weight) |
| | if module.bias is not None: |
| | nn.init.constant_(module.bias, 0) |
| |
|
| | self.apply(_basic_init) |
| |
|
| | |
| | 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) |
| |
|
| | |
| | nn.init.normal_(self.t_embedder.mlp[0].weight, std=0.02) |
| | nn.init.normal_(self.t_embedder.mlp[2].weight, std=0.02) |
| |
|
| | |
| | for block in self.blocks: |
| | nn.init.constant_(block.adaLN_modulation[-1].weight, 0) |
| | nn.init.constant_(block.adaLN_modulation[-1].bias, 0) |
| |
|
| | |
| | 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) |
| |
|
| | |
| | if self.use_text_encoder: |
| | nn.init.normal_(self.y_embedder.y_proj.fc1.weight, std=0.02) |
| | nn.init.normal_(self.y_embedder.y_proj.fc2.weight, std=0.02) |
| |
|
| |
|
| | @MODELS.register_module("DiT-XL/2") |
| | def DiT_XL_2(from_pretrained=None, **kwargs): |
| | model = DiT( |
| | depth=28, |
| | hidden_size=1152, |
| | patch_size=(1, 2, 2), |
| | num_heads=16, |
| | **kwargs, |
| | ) |
| | if from_pretrained is not None: |
| | load_checkpoint(model, from_pretrained) |
| | return model |
| |
|
| |
|
| | @MODELS.register_module("DiT-XL/2x2") |
| | def DiT_XL_2x2(from_pretrained=None, **kwargs): |
| | model = DiT( |
| | depth=28, |
| | hidden_size=1152, |
| | patch_size=(2, 2, 2), |
| | num_heads=16, |
| | **kwargs, |
| | ) |
| | if from_pretrained is not None: |
| | load_checkpoint(model, from_pretrained) |
| | return model |
| |
|