Vision Transformer(vit)的Embedding层结构

代码:

class PatchEmbed(nn.Module):
    """
    2D Image to Patch Embedding
    """
    def __init__(self, img_size=224, patch_size=16, in_c=3, embed_dim=768, norm_layer=None):
        super().__init__()
        img_size = (img_size, img_size)
#图像尺寸默认224×224
        patch_size = (patch_size, patch_size)
#划分图像的块大小,默认为 16×16
        self.img_size = img_size
        self.patch_size = patch_size
        self.grid_size = (img_size[0] // patch_size[0], img_size[1] // patch_size[1])
#将输入图像的高度和宽度分别除以图像块的高度和宽度,得到图像在高度和宽度方向上划分出的块的
#数量,例如:输入(224,224)除以patch:(16,16),得到数量(14,14)
        self.num_patches = self.grid_size[0] * self.grid_size[1]
#计算图像总共划分出的块的数量

        self.proj = nn.Conv2d(in_c, embed_dim, kernel_size=patch_size, stride=patch_size)
#使用卷积层(nn.Conv2d)将每个补丁映射到一个高维向量
        self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
#根据传入的 norm_layer 参数决定是否应用归一化层

    def forward(self, x):
        B, C, H, W = x.shape
        assert H == self.img_size[0] and W == self.img_size[1], \
            f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."
#检查输入图像的高度和宽度是否与类初始化时设置的 img_size 一致。如果不一致,就会抛出异常并
#给出相应的提示信息,确保输入图像的尺寸符合模型的预期。

        # flatten: [B, C, H, W] -> [B, C, HW]
        # transpose: [B, C, HW] -> [B, HW, C]
        x = self.proj(x).flatten(2).transpose(1, 2)
        x = self.norm(x)
#如果在初始化时传入了有效的归一化层 self.norm,那么就会对经过上述处理后的张量 x 进行归一#化处理
        return x

其中embed_dim=768:

embed_dim 是一个重要的参数,它代表嵌入的维度,即每个图像补丁(patch)经过嵌入层后所映射到的向量空间的维度。在深度学习和特别是在视觉变换器(Vision Transformers,简称ViT)模型中,embed_dim 通常用来指定模型中特征向量的维度。

默认值768的来源:在许多ViT模型的实现中,embed_dim 的默认值被设置为768,这个值来源于一些流行的预训练模型,如BERT,它在自然语言处理任务中取得了很好的效果。这个维度被证明能够有效地捕捉和表示数据的特征,因此在ViT模型中也被广泛采用。

操作:

代码: 

img_size = (img_size, img_size)
#图像尺寸默认224×224
        patch_size = (patch_size, patch_size)
#划分图像的块大小,默认为 16×16
        self.img_size = img_size
        self.patch_size = patch_size
        self.grid_size = (img_size[0] // patch_size[0], img_size[1] // patch_size[1])
#将输入图像的高度和宽度分别除以图像块的高度和宽度,得到图像在高度和宽度方向上划分出的块的
#数量,例如:输入(224,224)除以patch:(16,16),得到数量(14,14)
        self.num_patches = self.grid_size[0] * self.grid_size[1]
#计算图像总共划分出的块的数量

操作:

代码:

        self.proj = nn.Conv2d(in_c, embed_dim, kernel_size=patch_size, stride=patch_size)
#使用卷积层(nn.Conv2d)将每个补丁映射到一个高维向量
        self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()
#根据传入的 norm_layer 参数决定是否应用归一化层

此处1、2、3...为位置编码暂时忽略

ViTVision Transformer)中,position embedding是用来为每个patch分配一个位置信息的。在NLP中,不同的词汇之间是有顺序的,因此需要位置编码来表示它们的相对位置。而在视觉领域,图像与图像之间是没有顺序的,但是ViT将图像划分为一个个patch,每个patch对应于NLP中的一个Token,并且每个patch都有一个位置。因此,在ViT中,为了引入位置信息,每个特征维度都加入了一个position embedding模块。这个position embedding模块会为每个patch生成一个位置向量,用来表示该patch在图像中的位置。在高分辨率图像做微调时,作者建议保持patch size不变,直接对position embedding向量进行插值处理,以适应不同分辨率的图像。具体来说,就是对position embedding向量进行插值,使其与新的图像分辨率相匹配。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* [【ViT 微调时关于position embedding如何插值(interpolate)的详解】](https://blog.youkuaiyun.com/qq_44166630/article/details/127429697)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [关于ViT中pos embed的可视化](https://blog.youkuaiyun.com/weixin_41978699/article/details/122404192)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值