ZHOU_CAMP头像
关注

5. fastwam 模型 video expert pre dit过程

代码

  • 原始代码
    def pre_dit(
        self,
        x: torch.Tensor,
        timestep: torch.Tensor,
        context: torch.Tensor,
        context_mask: Optional[torch.Tensor] = None,
        action: Optional[torch.Tensor] = None,
        fuse_vae_embedding_in_latents: bool = False,
        control_camera_latents_input: Optional[torch.Tensor] = None,
    ) -> Dict[str, Any]:
        x, timestep, context_mask = self._validate_forward_inputs(
            x=x,
            timestep=timestep,
            context=context,
            context_mask=context_mask,
            action=action,
        )

        batch_size = x.shape[0]
        patch_h = int(self.patch_size[1])
        patch_w = int(self.patch_size[2])
        if x.shape[3] % patch_h != 0 or x.shape[4] % patch_w != 0:
            raise ValueError(
                "Latent spatial shape must be divisible by DiT patch size, "
                f"got HxW=({x.shape[3]}, {x.shape[4]}), patch=({patch_h}, {patch_w})"
            )
        tokens_per_frame = (x.shape[3] // patch_h) * (x.shape[4] // patch_w)

        if self.seperated_timestep and fuse_vae_embedding_in_latents:
            if not hasattr(self, "patch_size") or len(self.patch_size) < 3:
                raise ValueError(f"Invalid dit.patch_size: {getattr(self, 'patch_size', None)}")
            
            token_timesteps = torch.ones(
                (batch_size, x.shape[2], tokens_per_frame),
                dtype=timestep.dtype,
                device=timestep.device,
            ) * timestep.view(batch_size, 1, 1)
            token_timesteps[:, 0, :] = 0
            token_timesteps = token_timesteps.reshape(batch_size, -1)
            token_t_emb = sinusoidal_embedding_1d(self.freq_dim, token_timesteps.reshape(-1))
            t = self.time_embedding(token_t_emb).reshape(batch_size, -1, self.hidden_dim)
            t_mod = self.time_projection(t).unflatten(2, (6, self.hidden_dim))
        else:
            raise NotImplementedError("Only support seperated_timestep with fuse_vae_embedding_in_latents for now.")
            t = self.time_embedding(sinusoidal_embedding_1d(self.freq_dim, timestep))
            t_mod = self.time_projection(t).unflatten(1, (6, self.hidden_dim))

        print("patchify前的x:", x.shape)            
        x = self.patchify(x, control_camera_latents_input=control_camera_latents_input)
        print("patchify后的x:", x.shape)  
        f, h, w = x.shape[2:]

        print("text_embedding前的维度:", context.shape)
        context = self.text_embedding(context) # (B, L, dim)
        print("text_embedding后的维度:", context.shape)
        context_len = context.shape[1]
        if self.action_conditioned and action is not None:
            action_len = action.shape[1]
            action_emb = self.action_embedding(action) # (B, action_len, dim)
            action_pos_embed = sinusoidal_embedding_1d(self.hidden_dim, 
                torch.arange(action_len, device=action_emb.device)) # (action_len, dim)
            action_emb = action_emb + action_pos_embed.unsqueeze(0) # (B, action_len, dim)
            context = torch.cat([context, action_emb], dim=1) # (B, context_len + action_len, dim)

            # new mask
            num_temporal_groups = f - 1 # first latent frame do not attend to actions
            if num_temporal_groups <= 0:
                raise ValueError(
                    "Action-conditioned context mask requires at least 2 latent frames when `action` is provided."
                )
            assert action_emb.shape[1] % num_temporal_groups == 0, \
                f"Action embedding length {action_emb.shape[1]} must be divisible by number of temporal groups {num_temporal_groups}"
            # Each latent frame (from the 2nd one) attends to the corresponding group of action tokens
            action_group_mask = create_group_causal_attn_mask(
                num_temporal_groups=num_temporal_groups,
                num_query_per_group=tokens_per_frame,
                num_key_per_group=action_len // num_temporal_groups,
                mode=self.action_group_causal_mask_mode,
            ).to(context.device) # ((f-1)*tokens_per_frame, action_len)

            seq_len = f * h * w # query length
            final_context_mask = torch.zeros((batch_size, seq_len, context.shape[1]), dtype=torch.bool, device=context.device) # (B, seq_len, L + action_len)
            # all latent frames attend to text tokens
            final_context_mask[:, :, :context_len] = context_mask.unsqueeze(1).expand(-1, seq_len, -1) # (B, seq_len, L)
            # latent frames from the 2nd one attend to action tokens
            final_context_mask[:, tokens_per_frame:, context_len:] = action_group_mask.unsqueeze(0).expand(batch_size, -1, -1) # (B, seq_len, action_len)
            context_mask = final_context_mask
        elif self.action_conditioned and action is None:
            if f != 1:
                raise ValueError(
                    "Action-conditioned model requires `action` unless running single-frame text-only mode with num_latent_frames=1."
                )
            context_mask = context_mask.unsqueeze(1).expand(-1, f * h * w, -1) # (B, seq_len, L)
        else:
            context_mask = context_mask.unsqueeze(1).expand(-1, f * h * w, -1) # (B, seq_len, L)

        x_tokens = rearrange(x, "b c f h w -> b (f h w) c").contiguous()

        freqs = torch.cat([
            self.freqs[0][:f].view(f, 1, 1, -1).expand(f, h, w, -1),
            self.freqs[1][:h].view(1, h, 1, -1).expand(f, h, w, -1),
            self.freqs[2][:w].view(1, 1, w, -1).expand(f, h, w, -1)
        ], dim=-1).reshape(f * h * w, 1, -1).to(x_tokens.device)

        return {
            "tokens": x_tokens,
            "freqs": freqs,
            "t": t,
            "t_mod": t_mod,
            "context": context,
            "context_mask": context_mask,
            "meta": {
                "grid_size": (f, h, w),
                "tokens_per_frame": tokens_per_frame,
                "batch_size": batch_size,
            },
        }
  • 运行结果
--------before video_expert.pre_dit--------------
first_frame_latents: (1, 48, 1, 14, 28) torch.bfloat16 cuda:0
timestep_video: (1,) torch.bfloat16 cuda:0
context: (1, 129, 4096) torch.bfloat16 cuda:0
context_mask: (1, 129) torch.bool cuda:0
fuse_flag: True
patchify前的x: torch.Size([1, 48, 1, 14, 28])
patchify后的x: torch.Size([1, 3072, 1, 7, 14])
text_embedding前的维度: torch.Size([1, 129, 4096])
text_embedding后的维度: torch.Size([1, 129, 3072])
--------after video_expert.pre_dit--------------
[Processing] Key: tokens | Shape: torch.Size([1, 98, 3072]) | Dtype: torch.bfloat16
[Processing] Key: freqs | Shape: torch.Size([98, 1, 64]) | Dtype: torch.complex128
[Processing] Key: t | Shape: torch.Size([1, 98, 3072]) | Dtype: torch.bfloat16
[Processing] Key: t_mod | Shape: torch.Size([1, 98, 6, 3072]) | Dtype: torch.bfloat16
[Processing] Key: context | Shape: torch.Size([1, 129, 3072]) | Dtype: torch.bfloat16
[Processing] Key: context_mask | Shape: torch.Size([1, 98, 129]) | Dtype: torch.bool
[Processing] Key: meta | Type: <class 'dict'>

流程图

pre_dit inputs
x (first_frame_latents): (1,48,1,14,28) bf16 cuda

timestep: (1,) bf16 cuda
context: (1,129,4096) bf16 cuda
context_mask: (1,129) bool cuda
fuse_vae_embedding_in_latents: True

Validate shapes
_validate_forward_inputs

Compute tokens_per_frame
patch_size=(1,2,2)
H'=14,W'=28
patchify grid: h=7,w=14
tokens_per_frame = 7*14 = 98

Separated timestep (per-token)
seperated_timestep=True & fuse=True

Build token_timesteps:
shape (B,F,tokens_per_frame)=(1,1,98)
set frame0 timestep=0
flatten -> (1,98)

sinusoidal_embedding -> token_t_emb
(time_embedding)-> t: (1,98,3072)
(time_projection)-> t_mod: (1,98,6,3072)

Patchify video latents
Before: x (1,48,1,14,28)
After: x (1,3072,1,7,14)

Flatten to token sequence
x_tokens = rearrange
(b,c,f,h,w)->(b,f*h*w,c)

tokens: (1,98,3072)

Text embedding
text_embedding: 4096 -> 3072
context: (1,129,4096) -> (1,129,3072)

Expand context_mask to per-query
context_mask: (1,129)
-> (1,seq_len,129)
seq_len = f*h*w = 98
context_mask: (1,98,129)

Build rotary freqs
freqs: (seq_len,1,64)
= (98,1,64) complex128

pre_dit outputs dict

Return payload
(tokens, freqs, t, t_mod,
context, context_mask,
meta={grid_size=(1,7,14), tokens_per_frame=98, batch_size=1})

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/qq_41472205/article/details/163512441

文章来源crawl

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--