Open-Sora 1.2
Configuration
配置文件位于 /configs/opensora-v1-2/inference/sample.py, 可以配置的参数如下
1 |
|
要生成的图像大小 image_size
由 resolution
和 aspect_ratio
计算。若 aspect_ratio
存在于 /dataset/aspect.py 预定义好的 ASPECT_RATIO_{aspect_ratio}
字典中,则直接取出对应的 image_size
,计算公式如下
1 |
|
要生成的帧数 num_frames
可以直接指定数字或者指定 /dataset/aspect.py 中预定义字典 NUM_FRAMES_MAP
里的倍数或者秒数 (fps=25.5).
1 |
|
命令行推理 (禁用 apex 和 flash-attn 需要加上 --layernorm-kernel False --flash-attn False \
)
1 |
|
Overview
VAE
VAE 的两部分分别为 spatial_vae 和 temporal_vae
1 |
|
Embedder Layer
会对输入视频噪声 (x),编码后的 prompt (y),去噪时间步 (t),fps 进行嵌入。
PositionEmbedding2D
1 |
|
TimestepEmbedder
为每个时间步创建唯一的表示,使用正弦和余弦函数来生成时间序列的嵌入。dim 被分为两部分,一部分用于计算正弦嵌入,另一部分用于计算余弦嵌入。t[:, None] * freqs[None]
时间步 t 和频率 freqs 进行外积,生成嵌入的值。然后再计算正弦和余弦嵌入,拼接起来。最后将生成的 embedding 矩阵经过两个 Linear 层,得到最终的输出。
1 |
|
CaptionEmbedder (encode_text)
CaptionEmbedder
中的 Mlp 来自于 timm.models.vision_transformer.Mlp (Linear->GELU->Dropout->Norm(Identity)->Linear->Dropout). 推理时不进行 token_drop
.
1 |
|
mask
是可选的掩码张量,用来标记 y 中的 token 是有效的 (1) 还是无效的 (0). masked_select
会保留 mask
中为 1 的索引处的 token 并重新调整成 (1, N_valid_token, self.hidden_size)
形状。然后统计 batch 中每个样本有效的 token 数量,并将其转换成列表。如果没有提供 mask
,则假设所有 token 都有效。
1 |
|
PatchEmbed3D
对输入的视频噪声进行 3D 卷积 (stride 和 kernel_size 设置成 patch_size
元组) 后 flatten 并从 (B, C, T, H, W)
reshape 成 (B, N, C)
,其中 N = T * H * W
.
1 |
|
STDiT3Block (backbone)
一个 STDiT3Block 由 Attention,MultiHeadCrossAttention 和 MLP 组成。
Attention
正常的注意力机制,使用 q @ k.transpose(-2, -1)
计算注意力矩阵,然后使用 softmax 归一化。
is_causal
分支用于处理 因果注意力机制(causal attention)。这是在某些模型(尤其是自回归模型,如 GPT 等生成模型)中非常常见的注意力机制,确保了模型在进行推理或生成时,当前时间步只能关注过去的时间步,不能看到未来的时间步。
1 |
|
MultiHeadCrossAttention
这里选择把 B 和 N 维度合并看作一个序列的长度,把计算交叉注意力转换成计算自注意力的过程(xformers.ops.memory_efficient_attention)。因此计算噪声和 prompt 的交叉注意力之前加入分块对角掩码 (BlockDiagonalMask),标出 batch 中每个 q 和 kv 分别的 sequence 长度。
1 |
|
Forward
涉及自注意力 (self-attention)、交叉注意力(cross-attention)、MLP、时序处理等操作。在多头自注意力和 MLP 的基础上加入了输入的调制(modulation)、输出门控和残差连接 (residual connections).
Parameters
1 |
|
输入参数 :
x
: 视频噪声 token,形状(B, N, C)
,其中B
是 batch 大小,N
是 token 数量,C
是每个 token 的特征维度。y
: 文本信息,形状(B, token_num, C)
。t
: 时间步嵌入(B, 6*C)
,用于调制输入。mask
: 文本掩码。x_mask
: 时序掩码,用于控制某些时序数据的处理。t0
: 时间步为 0 时的嵌入,用于对x_mask
处理的特殊处理。T
: 帧数S
: 空间上每个帧的 patch 数
调制参数 :
self.scale_shift_table
是用于生成调制参数的表。t
被映射为 6 个形状为(B, 1, C)
调制量:shift_msa
、scale_msa
、gate_msa
用于多头自注意力,shift_mlp
、scale_mlp
、gate_mlp
用于 MLP。- 如果
x_mask
存在(说明有时序信息),则同样对t0
(时间步为 0 的嵌入)生成对应的调制参数。
t2i_modulate
1 |
|
调制操作 :
t2i_modulate
是一个调制函数 (见注释),通过shift
和scale
对输入进行变换,这里对进行归一化的norm1(x)
进行调制。- 如果存在
x_mask
,则根据掩码使用t0
进行特定的调制。
Compute Attention Score
1 |
|
self.temporal
为 True
,则表示需要进行时序上的注意力计算,将 x_m
变为 (B S) T C
形状,表示 batch 中每个空间 patch 上的时序序列进行注意力操作。否则,在空间上进行注意力计算。
Residual Connection
1 |
|
使用 gate_msa
对注意力的输出进行门控(gate),并通过 drop_path 处理后与到原始输入 x 相加 (残差连接)。
Cross Attention and Residual Connection
1 |
|
x 和条件 y 的信息融合,把交叉注意力输出加到 x 上,完成残差连接。
MLP and Residual Connection
1 |
|
和自注意力层一样,通过 shift_mlp
和 scale_mlp
进行调制,再经过 MLP 层,再通过 gate_mlp
进行门控,再加到原始输入 x 上,完成残差连接。
T2IFinalLayer
将输入进行 LayerNorm 后进行调制,然后通过线性层将 channel 调整为 num_patch * out_channels
,其中 num_patch=prod(patch_size)
, out_channels
若预测方差则为 2*in_channels
否则为 in_channels
. 最后通过 unpatchify
变换成原来的形状。
广播操作的条件:两个张量在每个维度上要么相等,要么有一个维度的大小为 1.
1 |
|
Forward
输入视频噪声的形状为 (B,in_channels,T,H,W)
,是已经经过 VAE 的,in_channels=4
, H 和 W 都为原来的 1/8. timestep
是当前的去噪时间步骤. y 是经过 tokenizer 编码后的 prompt.
get_dynamic_size()
函数会获取划分 patch (默认 1x2x2) 后每个patch的大小 (不能整除会补 0).- 对划分 patch 后的 H 和 W 创建 Position Embedding 矩阵,形状为
(1, H*W, dim)
self.fps_embedder
是一个SizeEmbedder
,它是TimestepEmbedder
的子类,它用于将标量信息编码到时间步维度上。它会先将标量形状变成(B, 1)
,即在第 0 维上 repeat B 次,然后进行时间嵌入编码。t
和fps
经过嵌入后相加,经过t_block
(SiLU->Linear) 后形状为(B, 6*dim)
.- 对编码后的 prompt 进行嵌入,具体过程如上。
- 对输入的视频噪声进行
PatchEmbed3D
,具体过程如上。然后 reshape 成(B, T, S, C)
, 加上 Position Embedding 矩阵,reshape 回(B, N, C)
。 - 前面已经保证了 H 能被卡数整除,若采用了 sequence parallelism,则将 S 维度进行划分。
- 遍历
self.spatial_blocks
和self.temporal_blocks
,对输入的 patch 进行空间和时间卷积。 - 通过
final_layer
得到输出,并 reshape 成(B, C_out, T, H, W)
并返回。
1 |
|