ALSv/self-forcing
0
1# Copyright 2024-2025 The Alibaba Wan Team Authors. All rights reserved.2import math3 4import torch5import torch.nn as nn6from diffusers.configuration_utils import ConfigMixin, register_to_config7from diffusers.models.modeling_utils import ModelMixin8from einops import repeat9 10from .attention import flash_attention11 12__all__ = ['WanModel']13 14 15def sinusoidal_embedding_1d(dim, position):16 # preprocess17 assert dim % 2 == 018 half = dim // 219 position = position.type(torch.float64)20 21 # calculation22 sinusoid = torch.outer(23 position, torch.pow(10000, -torch.arange(half).to(position).div(half)))24 x = torch.cat([torch.cos(sinusoid), torch.sin(sinusoid)], dim=1)25 return x26 27 28# @amp.autocast(enabled=False)29def rope_params(max_seq_len, dim, theta=10000):30 assert dim % 2 == 031 freqs = torch.outer(32 torch.arange(max_seq_len),33 1.0 / torch.pow(theta,34 torch.arange(0, dim, 2).to(torch.float64).div(dim)))35 freqs = torch.polar(torch.ones_like(freqs), freqs)36 return freqs37 38 39# @amp.autocast(enabled=False)40def rope_apply(x, grid_sizes, freqs):41 n, c = x.size(2), x.size(3) // 242 43 # split freqs44 freqs = freqs.split([c - 2 * (c // 3), c // 3, c // 3], dim=1)45 46 # loop over samples47 output = []48 for i, (f, h, w) in enumerate(grid_sizes.tolist()):49 seq_len = f * h * w50 51 # precompute multipliers52 x_i = torch.view_as_complex(x[i, :seq_len].to(torch.float64).reshape(53 seq_len, n, -1, 2))54 freqs_i = torch.cat([55 freqs[0][:f].view(f, 1, 1, -1).expand(f, h, w, -1),56 freqs[1][:h].view(1, h, 1, -1).expand(f, h, w, -1),57 freqs[2][:w].view(1, 1, w, -1).expand(f, h, w, -1)58 ],59 dim=-1).reshape(seq_len, 1, -1)60 61 # apply rotary embedding62 x_i = torch.view_as_real(x_i * freqs_i).flatten(2)63 x_i = torch.cat([x_i, x[i, seq_len:]])64 65 # append to collection66 output.append(x_i)67 return torch.stack(output).type_as(x)68 69 70class WanRMSNorm(nn.Module):71 72 def __init__(self, dim, eps=1e-5):73 super().__init__()74 self.dim = dim75 self.eps = eps76 self.weight = nn.Parameter(torch.ones(dim))77 78 def forward(self, x):79 r"""80 Args:81 x(Tensor): Shape [B, L, C]82 """83 return self._norm(x.float()).type_as(x) * self.weight84 85 def _norm(self, x):86 return x * torch.rsqrt(x.pow(2).mean(dim=-1, keepdim=True) + self.eps)87 88 89class WanLayerNorm(nn.LayerNorm):90 91 def __init__(self, dim, eps=1e-6, elementwise_affine=False):92 super().__init__(dim, elementwise_affine=elementwise_affine, eps=eps)93 94 def forward(self, x):95 r"""96 Args:97 x(Tensor): Shape [B, L, C]98 """99 return super().forward(x).type_as(x)100 101 102class WanSelfAttention(nn.Module):103 104 def __init__(self,105 dim,106 num_heads,107 window_size=(-1, -1),108 qk_norm=True,109 eps=1e-6):110 assert dim % num_heads == 0111 super().__init__()112 self.dim = dim113 self.num_heads = num_heads114 self.head_dim = dim // num_heads115 self.window_size = window_size116 self.qk_norm = qk_norm117 self.eps = eps118 119 # layers120 self.q = nn.Linear(dim, dim)121 self.k = nn.Linear(dim, dim)122 self.v = nn.Linear(dim, dim)123 self.o = nn.Linear(dim, dim)124 self.norm_q = WanRMSNorm(dim, eps=eps) if qk_norm else nn.Identity()125 self.norm_k = WanRMSNorm(dim, eps=eps) if qk_norm else nn.Identity()126 127 def forward(self, x, seq_lens, grid_sizes, freqs):128 r"""129 Args:130 x(Tensor): Shape [B, L, num_heads, C / num_heads]131 seq_lens(Tensor): Shape [B]132 grid_sizes(Tensor): Shape [B, 3], the second dimension contains (F, H, W)133 freqs(Tensor): Rope freqs, shape [1024, C / num_heads / 2]134 """135 b, s, n, d = *x.shape[:2], self.num_heads, self.head_dim136 137 # query, key, value function138 def qkv_fn(x):139 q = self.norm_q(self.q(x)).view(b, s, n, d)140 k = self.norm_k(self.k(x)).view(b, s, n, d)141 v = self.v(x).view(b, s, n, d)142 return q, k, v143 144 q, k, v = qkv_fn(x)145 146 x = flash_attention(147 q=rope_apply(q, grid_sizes, freqs),148 k=rope_apply(k, grid_sizes, freqs),149 v=v,150 k_lens=seq_lens,151 window_size=self.window_size)152 153 # output154 x = x.flatten(2)155 x = self.o(x)156 return x157 158 159class WanT2VCrossAttention(WanSelfAttention):160 161 def forward(self, x, context, context_lens, crossattn_cache=None):162 r"""163 Args:164 x(Tensor): Shape [B, L1, C]165 context(Tensor): Shape [B, L2, C]166 context_lens(Tensor): Shape [B]167 crossattn_cache (List[dict], *optional*): Contains the cached key and value tensors for context embedding.168 """169 b, n, d = x.size(0), self.num_heads, self.head_dim170 171 # compute query, key, value172 q = self.norm_q(self.q(x)).view(b, -1, n, d)173 174 if crossattn_cache is not None:175 if not crossattn_cache["is_init"]:176 crossattn_cache["is_init"] = True177 k = self.norm_k(self.k(context)).view(b, -1, n, d)178 v = self.v(context).view(b, -1, n, d)179 crossattn_cache["k"] = k180 crossattn_cache["v"] = v181 else:182 k = crossattn_cache["k"]183 v = crossattn_cache["v"]184 else:185 k = self.norm_k(self.k(context)).view(b, -1, n, d)186 v = self.v(context).view(b, -1, n, d)187 188 # compute attention189 x = flash_attention(q, k, v, k_lens=context_lens)190 191 # output192 x = x.flatten(2)193 x = self.o(x)194 return x195 196 197class WanGanCrossAttention(WanSelfAttention):198 199 def forward(self, x, context, crossattn_cache=None):200 r"""201 Args:202 x(Tensor): Shape [B, L1, C]203 context(Tensor): Shape [B, L2, C]204 context_lens(Tensor): Shape [B]205 crossattn_cache (List[dict], *optional*): Contains the cached key and value tensors for context embedding.206 """207 b, n, d = x.size(0), self.num_heads, self.head_dim208 209 # compute query, key, value210 qq = self.norm_q(self.q(context)).view(b, 1, -1, d)211 212 kk = self.norm_k(self.k(x)).view(b, -1, n, d)213 vv = self.v(x).view(b, -1, n, d)214 215 # compute attention216 x = flash_attention(qq, kk, vv)217 218 # output219 x = x.flatten(2)220 x = self.o(x)221 return x222 223 224class WanI2VCrossAttention(WanSelfAttention):225 226 def __init__(self,227 dim,228 num_heads,229 window_size=(-1, -1),230 qk_norm=True,231 eps=1e-6):232 super().__init__(dim, num_heads, window_size, qk_norm, eps)233 234 self.k_img = nn.Linear(dim, dim)235 self.v_img = nn.Linear(dim, dim)236 # self.alpha = nn.Parameter(torch.zeros((1, )))237 self.norm_k_img = WanRMSNorm(238 dim, eps=eps) if qk_norm else nn.Identity()239 240 def forward(self, x, context, context_lens):241 r"""242 Args:243 x(Tensor): Shape [B, L1, C]244 context(Tensor): Shape [B, L2, C]245 context_lens(Tensor): Shape [B]246 """247 context_img = context[:, :257]248 context = context[:, 257:]249 b, n, d = x.size(0), self.num_heads, self.head_dim250 251 # compute query, key, value252 q = self.norm_q(self.q(x)).view(b, -1, n, d)253 k = self.norm_k(self.k(context)).view(b, -1, n, d)254 v = self.v(context).view(b, -1, n, d)255 k_img = self.norm_k_img(self.k_img(context_img)).view(b, -1, n, d)256 v_img = self.v_img(context_img).view(b, -1, n, d)257 img_x = flash_attention(q, k_img, v_img, k_lens=None)258 # compute attention259 x = flash_attention(q, k, v, k_lens=context_lens)260 261 # output262 x = x.flatten(2)263 img_x = img_x.flatten(2)264 x = x + img_x265 x = self.o(x)266 return x267 268 269WAN_CROSSATTENTION_CLASSES = {270 't2v_cross_attn': WanT2VCrossAttention,271 'i2v_cross_attn': WanI2VCrossAttention,272}273 274 275class WanAttentionBlock(nn.Module):276 277 def __init__(self,278 cross_attn_type,279 dim,280 ffn_dim,281 num_heads,282 window_size=(-1, -1),283 qk_norm=True,284 cross_attn_norm=False,285 eps=1e-6):286 super().__init__()287 self.dim = dim288 self.ffn_dim = ffn_dim289 self.num_heads = num_heads290 self.window_size = window_size291 self.qk_norm = qk_norm292 self.cross_attn_norm = cross_attn_norm293 self.eps = eps294 295 # layers296 self.norm1 = WanLayerNorm(dim, eps)297 self.self_attn = WanSelfAttention(dim, num_heads, window_size, qk_norm,298 eps)299 self.norm3 = WanLayerNorm(300 dim, eps,301 elementwise_affine=True) if cross_attn_norm else nn.Identity()302 self.cross_attn = WAN_CROSSATTENTION_CLASSES[cross_attn_type](dim,303 num_heads,304 (-1, -1),305 qk_norm,306 eps)307 self.norm2 = WanLayerNorm(dim, eps)308 self.ffn = nn.Sequential(309 nn.Linear(dim, ffn_dim), nn.GELU(approximate='tanh'),310 nn.Linear(ffn_dim, dim))311 312 # modulation313 self.modulation = nn.Parameter(torch.randn(1, 6, dim) / dim**0.5)314 315 def forward(316 self,317 x,318 e,319 seq_lens,320 grid_sizes,321 freqs,322 context,323 context_lens,324 ):325 r"""326 Args:327 x(Tensor): Shape [B, L, C]328 e(Tensor): Shape [B, 6, C]329 seq_lens(Tensor): Shape [B], length of each sequence in batch330 grid_sizes(Tensor): Shape [B, 3], the second dimension contains (F, H, W)331 freqs(Tensor): Rope freqs, shape [1024, C / num_heads / 2]332 """333 # assert e.dtype == torch.float32334 # with amp.autocast(dtype=torch.float32):335 e = (self.modulation + e).chunk(6, dim=1)336 # assert e[0].dtype == torch.float32337 338 # self-attention339 y = self.self_attn(340 self.norm1(x) * (1 + e[1]) + e[0], seq_lens, grid_sizes,341 freqs)342 # with amp.autocast(dtype=torch.float32):343 x = x + y * e[2]344 345 # cross-attention & ffn function346 def cross_attn_ffn(x, context, context_lens, e):347 x = x + self.cross_attn(self.norm3(x), context, context_lens)348 y = self.ffn(self.norm2(x) * (1 + e[4]) + e[3])349 # with amp.autocast(dtype=torch.float32):350 x = x + y * e[5]351 return x352 353 x = cross_attn_ffn(x, context, context_lens, e)354 return x355 356 357class GanAttentionBlock(nn.Module):358 359 def __init__(self,360 dim=1536,361 ffn_dim=8192,362 num_heads=12,363 window_size=(-1, -1),364 qk_norm=True,365 cross_attn_norm=True,366 eps=1e-6):367 super().__init__()368 self.dim = dim369 self.ffn_dim = ffn_dim370 self.num_heads = num_heads371 self.window_size = window_size372 self.qk_norm = qk_norm373 self.cross_attn_norm = cross_attn_norm374 self.eps = eps375 376 # layers377 # self.norm1 = WanLayerNorm(dim, eps)378 # self.self_attn = WanSelfAttention(dim, num_heads, window_size, qk_norm,379 # eps)380 self.norm3 = WanLayerNorm(381 dim, eps,382 elementwise_affine=True) if cross_attn_norm else nn.Identity()383 384 self.norm2 = WanLayerNorm(dim, eps)385 self.ffn = nn.Sequential(386 nn.Linear(dim, ffn_dim), nn.GELU(approximate='tanh'),387 nn.Linear(ffn_dim, dim))388 389 self.cross_attn = WanGanCrossAttention(dim, num_heads,390 (-1, -1),391 qk_norm,392 eps)393 394 # modulation395 # self.modulation = nn.Parameter(torch.randn(1, 6, dim) / dim**0.5)396 397 def forward(398 self,399 x,400 context,401 # seq_lens,402 # grid_sizes,403 # freqs,404 # context,405 # context_lens,406 ):407 r"""408 Args:409 x(Tensor): Shape [B, L, C]410 e(Tensor): Shape [B, 6, C]411 seq_lens(Tensor): Shape [B], length of each sequence in batch412 grid_sizes(Tensor): Shape [B, 3], the second dimension contains (F, H, W)413 freqs(Tensor): Rope freqs, shape [1024, C / num_heads / 2]414 """415 # assert e.dtype == torch.float32416 # with amp.autocast(dtype=torch.float32):417 # e = (self.modulation + e).chunk(6, dim=1)418 # assert e[0].dtype == torch.float32419 420 # # self-attention421 # y = self.self_attn(422 # self.norm1(x) * (1 + e[1]) + e[0], seq_lens, grid_sizes,423 # freqs)424 # # with amp.autocast(dtype=torch.float32):425 # x = x + y * e[2]426 427 # cross-attention & ffn function428 def cross_attn_ffn(x, context):429 token = context + self.cross_attn(self.norm3(x), context)430 y = self.ffn(self.norm2(token)) + token # * (1 + e[4]) + e[3])431 # with amp.autocast(dtype=torch.float32):432 # x = x + y * e[5]433 return y434 435 x = cross_attn_ffn(x, context)436 return x437 438 439class Head(nn.Module):440 441 def __init__(self, dim, out_dim, patch_size, eps=1e-6):442 super().__init__()443 self.dim = dim444 self.out_dim = out_dim445 self.patch_size = patch_size446 self.eps = eps447 448 # layers449 out_dim = math.prod(patch_size) * out_dim450 self.norm = WanLayerNorm(dim, eps)451 self.head = nn.Linear(dim, out_dim)452 453 # modulation454 self.modulation = nn.Parameter(torch.randn(1, 2, dim) / dim**0.5)455 456 def forward(self, x, e):457 r"""458 Args:459 x(Tensor): Shape [B, L1, C]460 e(Tensor): Shape [B, C]461 """462 # assert e.dtype == torch.float32463 # with amp.autocast(dtype=torch.float32):464 e = (self.modulation + e.unsqueeze(1)).chunk(2, dim=1)465 x = (self.head(self.norm(x) * (1 + e[1]) + e[0]))466 return x467 468 469class MLPProj(torch.nn.Module):470 471 def __init__(self, in_dim, out_dim):472 super().__init__()473 474 self.proj = torch.nn.Sequential(475 torch.nn.LayerNorm(in_dim), torch.nn.Linear(in_dim, in_dim),476 torch.nn.GELU(), torch.nn.Linear(in_dim, out_dim),477 torch.nn.LayerNorm(out_dim))478 479 def forward(self, image_embeds):480 clip_extra_context_tokens = self.proj(image_embeds)481 return clip_extra_context_tokens482 483 484class RegisterTokens(nn.Module):485 def __init__(self, num_registers: int, dim: int):486 super().__init__()487 self.register_tokens = nn.Parameter(torch.randn(num_registers, dim) * 0.02)488 self.rms_norm = WanRMSNorm(dim, eps=1e-6)489 490 def forward(self):491 return self.rms_norm(self.register_tokens)492 493 def reset_parameters(self):494 nn.init.normal_(self.register_tokens, std=0.02)495 496 497class WanModel(ModelMixin, ConfigMixin):498 r"""499 Wan diffusion backbone supporting both text-to-video and image-to-video.500 """501 502 ignore_for_config = [503 'patch_size', 'cross_attn_norm', 'qk_norm', 'text_dim', 'window_size'504 ]505 _no_split_modules = ['WanAttentionBlock']506 _supports_gradient_checkpointing = True507 508 @register_to_config509 def __init__(self,510 model_type='t2v',511 patch_size=(1, 2, 2),512 text_len=512,513 in_dim=16,514 dim=2048,515 ffn_dim=8192,516 freq_dim=256,517 text_dim=4096,518 out_dim=16,519 num_heads=16,520 num_layers=32,521 window_size=(-1, -1),522 qk_norm=True,523 cross_attn_norm=True,524 eps=1e-6):525 r"""526 Initialize the diffusion model backbone.527 528 Args:529 model_type (`str`, *optional*, defaults to 't2v'):530 Model variant - 't2v' (text-to-video) or 'i2v' (image-to-video)531 patch_size (`tuple`, *optional*, defaults to (1, 2, 2)):532 3D patch dimensions for video embedding (t_patch, h_patch, w_patch)533 text_len (`int`, *optional*, defaults to 512):534 Fixed length for text embeddings535 in_dim (`int`, *optional*, defaults to 16):536 Input video channels (C_in)537 dim (`int`, *optional*, defaults to 2048):538 Hidden dimension of the transformer539 ffn_dim (`int`, *optional*, defaults to 8192):540 Intermediate dimension in feed-forward network541 freq_dim (`int`, *optional*, defaults to 256):542 Dimension for sinusoidal time embeddings543 text_dim (`int`, *optional*, defaults to 4096):544 Input dimension for text embeddings545 out_dim (`int`, *optional*, defaults to 16):546 Output video channels (C_out)547 num_heads (`int`, *optional*, defaults to 16):548 Number of attention heads549 num_layers (`int`, *optional*, defaults to 32):550 Number of transformer blocks551 window_size (`tuple`, *optional*, defaults to (-1, -1)):552 Window size for local attention (-1 indicates global attention)553 qk_norm (`bool`, *optional*, defaults to True):554 Enable query/key normalization555 cross_attn_norm (`bool`, *optional*, defaults to False):556 Enable cross-attention normalization557 eps (`float`, *optional*, defaults to 1e-6):558 Epsilon value for normalization layers559 """560 561 super().__init__()562 563 assert model_type in ['t2v', 'i2v']564 self.model_type = model_type565 566 self.patch_size = patch_size567 self.text_len = text_len568 self.in_dim = in_dim569 self.dim = dim570 self.ffn_dim = ffn_dim571 self.freq_dim = freq_dim572 self.text_dim = text_dim573 self.out_dim = out_dim574 self.num_heads = num_heads575 self.num_layers = num_layers576 self.window_size = window_size577 self.qk_norm = qk_norm578 self.cross_attn_norm = cross_attn_norm579 self.eps = eps580 self.local_attn_size = 21581 582 # embeddings583 self.patch_embedding = nn.Conv3d(584 in_dim, dim, kernel_size=patch_size, stride=patch_size)585 self.text_embedding = nn.Sequential(586 nn.Linear(text_dim, dim), nn.GELU(approximate='tanh'),587 nn.Linear(dim, dim))588 589 self.time_embedding = nn.Sequential(590 nn.Linear(freq_dim, dim), nn.SiLU(), nn.Linear(dim, dim))591 self.time_projection = nn.Sequential(592 nn.SiLU(), nn.Linear(dim, dim * 6))593 594 # blocks595 cross_attn_type = 't2v_cross_attn' if model_type == 't2v' else 'i2v_cross_attn'596 self.blocks = nn.ModuleList([597 WanAttentionBlock(cross_attn_type, dim, ffn_dim, num_heads,598 window_size, qk_norm, cross_attn_norm, eps)599 for _ in range(num_layers)600 ])601 602 # head603 self.head = Head(dim, out_dim, patch_size, eps)604 605 # buffers (don't use register_buffer otherwise dtype will be changed in to())606 assert (dim % num_heads) == 0 and (dim // num_heads) % 2 == 0607 d = dim // num_heads608 self.freqs = torch.cat([609 rope_params(1024, d - 4 * (d // 6)),610 rope_params(1024, 2 * (d // 6)),611 rope_params(1024, 2 * (d // 6))612 ],613 dim=1)614 615 if model_type == 'i2v':616 self.img_emb = MLPProj(1280, dim)617 618 # initialize weights619 self.init_weights()620 621 self.gradient_checkpointing = False622 623 def _set_gradient_checkpointing(self, module, value=False):624 self.gradient_checkpointing = value625 626 def forward(627 self,628 *args,629 **kwargs630 ):631 # if kwargs.get('classify_mode', False) is True:632 # kwargs.pop('classify_mode')633 # return self._forward_classify(*args, **kwargs)634 # else:635 return self._forward(*args, **kwargs)636 637 def _forward(638 self,639 x,640 t,641 context,642 seq_len,643 classify_mode=False,644 concat_time_embeddings=False,645 register_tokens=None,646 cls_pred_branch=None,647 gan_ca_blocks=None,648 clip_fea=None,649 y=None,650 ):651 r"""652 Forward pass through the diffusion model653 654 Args:655 x (List[Tensor]):656 List of input video tensors, each with shape [C_in, F, H, W]657 t (Tensor):658 Diffusion timesteps tensor of shape [B]659 context (List[Tensor]):660 List of text embeddings each with shape [L, C]661 seq_len (`int`):662 Maximum sequence length for positional encoding663 clip_fea (Tensor, *optional*):664 CLIP image features for image-to-video mode665 y (List[Tensor], *optional*):666 Conditional video inputs for image-to-video mode, same shape as x667 668 Returns:669 List[Tensor]:670 List of denoised video tensors with original input shapes [C_out, F, H / 8, W / 8]671 """672 if self.model_type == 'i2v':673 assert clip_fea is not None and y is not None674 # params675 device = self.patch_embedding.weight.device676 if self.freqs.device != device:677 self.freqs = self.freqs.to(device)678 679 if y is not None:680 x = [torch.cat([u, v], dim=0) for u, v in zip(x, y)]681 682 # embeddings683 x = [self.patch_embedding(u.unsqueeze(0)) for u in x]684 grid_sizes = torch.stack(685 [torch.tensor(u.shape[2:], dtype=torch.long) for u in x])686 x = [u.flatten(2).transpose(1, 2) for u in x]687 seq_lens = torch.tensor([u.size(1) for u in x], dtype=torch.long)688 assert seq_lens.max() <= seq_len689 x = torch.cat([690 torch.cat([u, u.new_zeros(1, seq_len - u.size(1), u.size(2))],691 dim=1) for u in x692 ])693 694 # time embeddings695 # with amp.autocast(dtype=torch.float32):696 e = self.time_embedding(697 sinusoidal_embedding_1d(self.freq_dim, t).type_as(x))698 e0 = self.time_projection(e).unflatten(1, (6, self.dim))699 # assert e.dtype == torch.float32 and e0.dtype == torch.float32700 701 # context702 context_lens = None703 context = self.text_embedding(704 torch.stack([705 torch.cat(706 [u, u.new_zeros(self.text_len - u.size(0), u.size(1))])707 for u in context708 ]))709 710 if clip_fea is not None:711 context_clip = self.img_emb(clip_fea) # bs x 257 x dim712 context = torch.concat([context_clip, context], dim=1)713 714 # arguments715 kwargs = dict(716 e=e0,717 seq_lens=seq_lens,718 grid_sizes=grid_sizes,719 freqs=self.freqs,720 context=context,721 context_lens=context_lens)722 723 def create_custom_forward(module):724 def custom_forward(*inputs, **kwargs):725 return module(*inputs, **kwargs)726 return custom_forward727 728 # TODO: Tune the number of blocks for feature extraction729 final_x = None730 if classify_mode:731 assert register_tokens is not None732 assert gan_ca_blocks is not None733 assert cls_pred_branch is not None734 735 final_x = []736 registers = repeat(register_tokens(), "n d -> b n d", b=x.shape[0])737 # x = torch.cat([registers, x], dim=1)738 739 gan_idx = 0740 for ii, block in enumerate(self.blocks):741 if torch.is_grad_enabled() and self.gradient_checkpointing:742 x = torch.utils.checkpoint.checkpoint(743 create_custom_forward(block),744 x, **kwargs,745 use_reentrant=False,746 )747 else:748 x = block(x, **kwargs)749 750 if classify_mode and ii in [13, 21, 29]:751 gan_token = registers[:, gan_idx: gan_idx + 1]752 final_x.append(gan_ca_blocks[gan_idx](x, gan_token))753 gan_idx += 1754 755 if classify_mode:756 final_x = torch.cat(final_x, dim=1)757 if concat_time_embeddings:758 final_x = cls_pred_branch(torch.cat([final_x, 10 * e[:, None, :]], dim=1).view(final_x.shape[0], -1))759 else:760 final_x = cls_pred_branch(final_x.view(final_x.shape[0], -1))761 762 # head763 x = self.head(x, e)764 765 # unpatchify766 x = self.unpatchify(x, grid_sizes)767 768 if classify_mode:769 return torch.stack(x), final_x770 771 return torch.stack(x)772 773 def _forward_classify(774 self,775 x,776 t,777 context,778 seq_len,779 register_tokens,780 cls_pred_branch,781 clip_fea=None,782 y=None,783 ):784 r"""785 Feature extraction through the diffusion model786 787 Args:788 x (List[Tensor]):789 List of input video tensors, each with shape [C_in, F, H, W]790 t (Tensor):791 Diffusion timesteps tensor of shape [B]792 context (List[Tensor]):793 List of text embeddings each with shape [L, C]794 seq_len (`int`):795 Maximum sequence length for positional encoding796 clip_fea (Tensor, *optional*):797 CLIP image features for image-to-video mode798 y (List[Tensor], *optional*):799 Conditional video inputs for image-to-video mode, same shape as x800 801 Returns:802 List[Tensor]:803 List of video features with original input shapes [C_block, F, H / 8, W / 8]804 """805 if self.model_type == 'i2v':806 assert clip_fea is not None and y is not None807 # params808 device = self.patch_embedding.weight.device809 if self.freqs.device != device:810 self.freqs = self.freqs.to(device)811 812 if y is not None:813 x = [torch.cat([u, v], dim=0) for u, v in zip(x, y)]814 815 # embeddings816 x = [self.patch_embedding(u.unsqueeze(0)) for u in x]817 grid_sizes = torch.stack(818 [torch.tensor(u.shape[2:], dtype=torch.long) for u in x])819 x = [u.flatten(2).transpose(1, 2) for u in x]820 seq_lens = torch.tensor([u.size(1) for u in x], dtype=torch.long)821 assert seq_lens.max() <= seq_len822 x = torch.cat([823 torch.cat([u, u.new_zeros(1, seq_len - u.size(1), u.size(2))],824 dim=1) for u in x825 ])826 827 # time embeddings828 # with amp.autocast(dtype=torch.float32):829 e = self.time_embedding(830 sinusoidal_embedding_1d(self.freq_dim, t).type_as(x))831 e0 = self.time_projection(e).unflatten(1, (6, self.dim))832 # assert e.dtype == torch.float32 and e0.dtype == torch.float32833 834 # context835 context_lens = None836 context = self.text_embedding(837 torch.stack([838 torch.cat(839 [u, u.new_zeros(self.text_len - u.size(0), u.size(1))])840 for u in context841 ]))842 843 if clip_fea is not None:844 context_clip = self.img_emb(clip_fea) # bs x 257 x dim845 context = torch.concat([context_clip, context], dim=1)846 847 # arguments848 kwargs = dict(849 e=e0,850 seq_lens=seq_lens,851 grid_sizes=grid_sizes,852 freqs=self.freqs,853 context=context,854 context_lens=context_lens)855 856 def create_custom_forward(module):857 def custom_forward(*inputs, **kwargs):858 return module(*inputs, **kwargs)859 return custom_forward860 861 # TODO: Tune the number of blocks for feature extraction862 for block in self.blocks[:16]:863 if torch.is_grad_enabled() and self.gradient_checkpointing:864 x = torch.utils.checkpoint.checkpoint(865 create_custom_forward(block),866 x, **kwargs,867 use_reentrant=False,868 )869 else:870 x = block(x, **kwargs)871 872 # unpatchify873 x = self.unpatchify(x, grid_sizes, c=self.dim // 4)874 return torch.stack(x)875 876 def unpatchify(self, x, grid_sizes, c=None):877 r"""878 Reconstruct video tensors from patch embeddings.879 880 Args:881 x (List[Tensor]):882 List of patchified features, each with shape [L, C_out * prod(patch_size)]883 grid_sizes (Tensor):884 Original spatial-temporal grid dimensions before patching,885 shape [B, 3] (3 dimensions correspond to F_patches, H_patches, W_patches)886 887 Returns:888 List[Tensor]:889 Reconstructed video tensors with shape [C_out, F, H / 8, W / 8]890 """891 892 c = self.out_dim if c is None else c893 out = []894 for u, v in zip(x, grid_sizes.tolist()):895 u = u[:math.prod(v)].view(*v, *self.patch_size, c)896 u = torch.einsum('fhwpqrc->cfphqwr', u)897 u = u.reshape(c, *[i * j for i, j in zip(v, self.patch_size)])898 out.append(u)899 return out900 901 def init_weights(self):902 r"""903 Initialize model parameters using Xavier initialization.904 """905 906 # basic init907 for m in self.modules():908 if isinstance(m, nn.Linear):909 nn.init.xavier_uniform_(m.weight)910 if m.bias is not None:911 nn.init.zeros_(m.bias)912 913 # init embeddings914 nn.init.xavier_uniform_(self.patch_embedding.weight.flatten(1))915 for m in self.text_embedding.modules():916 if isinstance(m, nn.Linear):917 nn.init.normal_(m.weight, std=.02)918 for m in self.time_embedding.modules():919 if isinstance(m, nn.Linear):920 nn.init.normal_(m.weight, std=.02)921 922 # init output layer923 nn.init.zeros_(self.head.head.weight)924 