代码:
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...为位置编码暂时忽略