仅供仔细学习记录有错欢迎指出这里fps16, chunk_size3图像像素先过VAE空间 stride 8再过patch(1, 2, 2)才能到token像素 [B, 3, T, H, W] , 这里假如H和W分别为480,832, T表示时间表输入的clip有T个像素帧Wan VAE编码后再把时间维挪到前面得到[B, T_latent, 16, H/8, W/8]那VAE latent变成60×104通道 16空间高和宽各除以 8。通道RGB 的 3 变成 VAE 的 16。这个 16 是压缩后的像素特征不是 DiT 的隐藏维度。patch时间维是1空间各除以 230 × 52 1560这块是 patch 怎么把一帧 latent 切成 token。我对着 Wan 的 patch embedding 把(1, 2, 2)具体切在哪几个轴上对一下。(1, 2, 2)是一个不重叠的 3D 小窗口时间上每次只取 1 帧空间上每次取 2×2 个 latent 格子。窗口扫完整张图每个窗口变成 1 个 token所以一帧是30 × 52 1560个 token。这就是视频 DiT 里的 3D patch embedding和 ViT 把图片切成 patch 是同一件事只是多了一个时间轴。Wan 用一个3D 卷积来做self.patch_embedding nn.Conv3d( in_dim, dim, kernel_sizepatch_size, stridepatch_size)kernel_size和stride都是(1, 2, 2)三个数依次是 时间、高、宽。stride 等于 kernel所以窗口挨着排、不重叠。一帧是怎么变成 1560 的VAE 出来的一帧 latent 可以想成一张60 × 104的小图每个格子有 16 个通道。卷积在这张图上滑时间: 窗口厚度 1步长 1 这一帧单独切不跟前后帧揉在一起 高: 窗口 2步长 2 60 / 2 30 宽: 窗口 2步长 2 104 / 2 52空间上就是把60 × 104铺成不重叠的 2×2 砖块60 行 latent ┌────┬────┬────┬─ ... ─┐ │2×2 │2×2 │2×2 │ │ 每一块 → 1 个 token ├────┼────┼────┤ │ │ │ │ │ │ 一行有 104/2 52 块 └────┴────┴────┴─ ... ─┘ 一共 30 行30 × 52 1560。每一块里有1 × 2 × 2 × 16 64个数卷积把这 64 个数投影成一个 1536 维向量这就是一个 token。一个 chunk 有 3 个 latent 帧时间窗口是 1所以帧数不变还是 3 帧每帧 1560 个 token。卷积输出是[1, 1536, 3, 30, 52]随后把空间和时间摊平x_noisy [u.flatten(2).transpose(1, 2) for u in x_noisy]变成[1, 3×1560, 1536]。hook 再按帧切开就是 gate 看到的[1, 3, 1560, 1536]。
阅读完成 · 觉得有帮助?