CogVideo
CogVideo copied to clipboard
finetune CogVideoX frames
我在README中看到,finetune CogVideoX 帧数必须是8的倍数 +1 ,請問如果只是8的倍數沒有加1可以嗎,因為我在VAE code 裡面看到帧数可以是8的倍数 或 8的倍数 +1。
这个 + 1 不是你准备数据哟用的,你准备数据就是8N。比如48帧 6秒
- 1 是因为第一帧要么是图(来自视频第一帧复制得来) 或者空白的噪声(T2V)
不好意思我想再問一下,我在I2V model的 code 裡看到image 好像是vae encode後concat在video latent 的channel dimension 上,可以問一下為什麼你說那個 1 是因为第一帧要么是图(来自视频第一帧复制得来) 或者空白的噪声(T2V)嗎,因為好像concat是在channel dimension 上,好像跟frames數沒什麼關係嗎
是concat在latent,而且处理的是 8*N的部分在拼上前面的latent。我们在encode的时候,微调实现的逻辑是这样的。
latent初始化的时候是 21的形状。
如果是I2V,你准备8N长度的视频。代码复制视频第一帧变成 8N + 1。接着,vae encode。8N +1。 此时latent形状就是21。 如果是T2V,你准备8N长度的视频。vae encode 8N,latent[0]还是初始化的噪声。还是21。
可是按照train code的話,如果是I2V,我準備8N长度的视频,vae 應該是 encode 8N frames 成video latent,然後vae會在encode 视频第一帧 image 成 image latent,並且padding image latent 的latent frames數跟video latent的frames數相同,如下code
image_latents = image_latents.permute(0, 2, 1, 3, 4) # [B, F, C, H, W]
video_latents = video_latents.permute(0, 2, 1, 3, 4) # [B, F, C, H, W]
padding_shape = (video_latents.shape[0], video_latents.shape[1] - 1, *video_latents.shape[2:])
latent_padding = image_latents.new_zeros(padding_shape)
image_latents = torch.cat([image_latents, latent_padding], dim=1)
然後video latent跟image latent,會一起concat在latent 的 channel dimension 上,不是frame dimension 上,如下code
noisy_video_latents = scheduler.add_noise(video_latents, noise, timesteps)
noisy_model_input = torch.cat([noisy_video_latents, image_latents], dim=2)
所以這樣好像跟latent 的frames數量沒有關係嗎? 想再請問一下inference 的時候設定輸出49frames,最後會輸出48frames還是49frames呢?
在此进行确认: 首先,我们在训练的时候(post train)视频长度就是81。(8N + 1),有两种情况
- 你的帧数超过了81,会直接裁剪前面的81帧。
- 如果你的帧没有到81,会pad最后一帧都视频到81。
- latent的第一个块要进行一次复制,不是对图像进行一次复制。 这一版代码我们在dev分支会进行更新,预计今天完成,
請問如果training frames數是8N的話例如48 frames不是就不需要複製第一個latent了嗎,為什麼還要用8n+1的frames去train,然後在複製第一個latent
而且你的code中有下面這段
sample_frames = self.state.train_frames - 1
if self.args.model_type == "i2v":
self.dataset = I2VDatasetWithResize(
**(self.args.model_dump()),
device=self.accelerator.device,
max_num_frames=sample_frames,
height=self.state.train_height,
width=self.state.train_width,
trainer=self,
)
self.state.train_frames=49 sample_frames=48 這樣看起training時 我們要準備的video 長度還是準備 8N frames 對嗎
推理和训练并不相同。 用户想看到的其实是8N的视频,但是模型在postrain的时候,是使用8N + 1 训练的。
对于训练,则应该正常的使用8N + 1的视频长度座位数据集。正确的做法不应该是复制第一帧,而是把8N(假设N是6)的视频复制最后一帧(如果你的数据集都不足49, 比如你是43 的视频,则是pad最后一帧6次。 由于8N 和 8N + 1 只差距1帧率,导致之前在微调I2V的时候我们在测试迪士尼数据集的时候差距不大。忽略了这个问题。 正确的做法是,你可以准备任意长度的数据集,假设你的数据集是47帧,43帧,35帧,60帧(总帧)混合的数据集。他们在训练的时候都会变成49. 其中 47 pad 2个最后一帧,43pad6个,35 pad 14个,60的仅取前49帧。这样就行了。我们dev已经更新了最新的一个PR。 https://github.com/THUDM/CogVideo/pull/654
我目前用cli_demo.py 設num_frames=49 inference出來還是49張frames 好像不像你說的解码出来是8N frames (例如48 frames)
想再請問一下如果以 I2V model 的inference情況來說,有一張image 當作input condition 時,inference 時出來的video 會包含input的那張image嗎,還是只包含input image 下個timestep 之後的frames呢
再請問一下finetune的時候,是建議不要用main branch 改用CogvideoX_dev branch的code嗎
- 这点操作是这样的 latent的形状是21,但是为了整除t patch,所以实际上推理中是22,所以要丢弃第一个latent来做vae,此时 4N + 1 被还原成了8N + 1.得到了81。这个确实是81(1.0 是49 且不存在pad 的问题,1.0版本没有tpatch,latent 应该就是13)。
- 包含,images是你的首帧, 但是这一帧经过VAE重建,可能与原始图像完全相同。 3 如果你现在就要用,建议还是用dev,或者我们周末弄完确定合并PR后用main的版本。
了解,所以inference出來的video的第一個frame是經過VAE重建的condition image,那第二個frame就是condition image的下個timestep對嗎
这已经是老的代码了,建议看一下新的代码 #654 的 i2v_dataset 和 trainer。
对于I2V来说用户必须指定8N + 1,然后视频直接采样8N + 1(老的代码是用户输入8N+1,在视频里采样8N,然后把图片复制到第一帧,从而变成8N + 1帧)。
这里以81帧为例:vae decode时下采样四倍得到21个latent,由于CogvideoX1.5的patch_t = 2,因此要让latent数目满足2的倍数,所以后面会给第一个latent复制一次,变成22个latent然后训练。
推理也是同理,用户要跟训练时一样输入8N + 1的帧数,同样以用户输入81帧为例:先在这里转换到85帧(加了4帧),再在这里算出latent的个数( (85-1)//4 + 1 = 22)
vae解码前,需要先取出第一个复制出来的latent(参考这里),还剩21个latent,然后解码10次,每一次分别得到9帧,8帧,8帧, ...,8帧,最后得到81帧的视频(可以参考这部分代码)
有,謝謝,zRzRzRzRzRzRzR 回我後我已經看過新的code了,我只是想再確認一下我上面提到的問題,也就是 inference出來的video的第一個frame是經過VAE重建的condition image,那第二個frame就是condition image的下個timestep對嗎
这已经是老的代码了,建议看一下新的代码 #654 的 i2v_dataset 和 trainer。
对于I2V来说用户必须指定8N + 1,然后视频直接采样8N + 1(老的代码是用户输入8N+1,在视频里采样8N,然后把图片复制到第一帧,从而变成8N + 1帧)。
这里以81帧为例:vae decode时下采样四倍得到21个latent,由于CogvideoX1.5的patch_t = 2,因此要让latent数目满足2的倍数,所以后面会给第一个latent复制一次,变成22个latent然后训练。
推理也是同理,用户要跟训练时一样输入8N + 1的帧数,同样以用户输入81帧为例:先在这里转换到85帧(加了4帧),再在这里算出latent的个数( (85-1)//4 + 1 = 22)
vae解码前,需要先取出第一个复制出来的latent(参考这里),还剩21个latent,然后解码10次,每一次分别得到9帧,8帧,8帧, ...,8帧,最后得到81帧的视频(可以参考这部分代码)
emm...也可以这么理解吧,但实际上生成视频帧的时候不是一帧一帧生成的,准确来说这里指的应该是latent
了解謝謝,我只是想確認最後生成的video 的第二個frame就是否就是condition image的下個timestep