QwenLM / Qwen2-VL

Qwen2-VL is the multimodal large language model series developed by Qwen team, Alibaba Cloud.
Apache License 2.0
3.39k stars 210 forks source link

关于视频与图像3Dpatch_embed部分论文与代码对应的疑问 #300

Open GenuineWWD opened 2 months ago

GenuineWWD commented 2 months ago

请教一个问题,关于论文和代码有个地方对应不太上。论文中说视频embedding使用3D卷积从而不增加视频帧所占的序列长度,图像的embedding使用两个图像叠起来。但是我看代码里写的并非如此。Patchembed代码中,无论是图像还是视频,输入永远是一个二维的tensor,并且temporal_patch_size这个变量的值永远是2,这也就意味着无论是图像还是视频,在这一步都是拆成了2帧再进行3D卷积,(尽管image_processor在生成pixel_value的时候对于视频grid_t 并不是2)。对于这一步我有以下疑问:

  1. 这样的操作不符合论文中说在不增加序列长度的情况下处理更多视频帧,因为视频帧或者max_pixel仍然会影响pixel_value的数量。 2.这样的操作实际上也并没有利用好论文中强调的时间维度,因为都是当成2帧处理 能麻烦解答一下吗,万分感谢!

附上PatchEmbed的forward函数与论文的截图: 3a8b4352d1c0120ab85b5c46b6a8a95 97b47d380f1499864ec60461c60a91b

yangyang-nus-lv commented 1 month ago

有相同的疑问。感觉应该先做conv3d再flatten成token sequence,但是代码实现刚好相反。 raised a thread here to draw more visibility https://huggingface.co/Qwen/Qwen2-VL-7B-Instruct/discussions/39

PangziZhang523 commented 1 month ago

@GenuineWWD 我的理解是“使用3D卷积从而不增加视频帧所占的序列长度”是跟多图使用2d卷积相比。2d卷积的kernel是1414,3d卷积的kernel是214*14。

GenuineWWD commented 1 month ago

@GenuineWWD 我的理解是“使用3D卷积从而不增加视频帧所占的序列长度”是跟多图使用2d卷积相比。2d卷积的kernel是14_14,3d卷积的kernel是2_14*14。

多谢关注。从这个角度看的话相较于2D的确减少了token的数量,是说得通的。不过这样似乎对于长视频的支持或者增强时间维度理解的意义并不是特别大。还是希望官方团队解答一下疑惑

yangyang-nus-lv commented 1 month ago

可以看下我放在HF上的问题,从mask 角度看,模型并没有学习到多帧之间的关联,只在两帧组内部进行attention。也就是说无所谓有没有在time dim上进行3D conv,最后还是没关注时间维度。单纯从理论上看,视频理解能力有一定局限性。

yangyang-nus-lv commented 1 month ago
class FramePatchEmbed(nn.Module):
    def __init__(self,
                 patch_size,
                 temporal_patch_size,
                 in_channels,
                 embed_dim,
                 spatial_merge_size
                 ):
        super().__init__()
        self.patch_size = patch_size
        self.temporal_patch_size = temporal_patch_size
        self.in_channels = in_channels
        self.embed_dim = embed_dim
        self.spatial_merge_size = spatial_merge_size

        kernel_size = (temporal_patch_size, patch_size, patch_size)
        self.proj = nn.Conv3d(in_channels, embed_dim, kernel_size, stride=kernel_size, bias=False)

    def forward(self, hidden_states):
        # hidden_states is image tensor in shape of (t, in_channels, h, w)
        target_dtype = self.proj.weight.dtype
        hidden_states = hidden_states.transpose(0, 1).to(target_dtype) # (in_channels, t, h, w)
        hidden_states = self.proj(hidden_states) # (embed_dim, grid_t, grid_h, grid_w)
        _, grid_t, grid_h, grid_w = hidden_states.shape
        hidden_states = hidden_states.permute(1, 2, 3, 0)
        hidden_states = hidden_states.reshape(
            grid_t,
            grid_h // self.spatial_merge_size,
            self.spatial_merge_size,
            grid_w // self.spatial_merge_size,
            self.spatial_merge_size,
            self.embed_dim
        )
        hidden_states = hidden_states.permute(0, 1, 3, 2, 4, 5)
        hidden_states = hidden_states.reshape(
            grid_t * grid_h * grid_w, self.embed_dim

        )
        return hidden_states # (grid_t * grid_h * grid_w, embed_dim)

简单改了下patchembed,先做conv3D再flatten,并且保持merge patch需要的顺序关系。 supposed to work,但是plug到原模型还需要改下输入

GenuineWWD commented 1 month ago

可以看下我放在HF上的问题,从mask 角度看,模型并没有学习到多帧之间的关联,只在两帧组内部进行attention。也就是说无所谓有没有在time dim上进行3D conv,最后还是没关注时间维度。单纯从理论上看,视频理解能力有一定局限性。

谢谢解答,我看过你的问题了。是否可以这么理解,模型的3D卷积只是为了把token减少一半而已,后面还是希望使用不引入时间维度的处理,甚至加了mask人为的把时间维度剥离开?不知道这个设计是不是qwen团队有意为之,看起来有点不够简洁