ViT代码体会

 Transformer 编码器 由交替的 多头自注意力层 (MSA) 和 多层感知机块 (MLP) 构成。在每个块前应用 层归一化 (Layer Norm),在每个块后应用 残差连接 (Residual Connection)

 一个 Transformer Encoder Block 就包含一个 MSA 和一个 FFN,二者都有 跳跃连接 和 层归一化 操作构成 MSA Block 和 MLP Block。

图像本身大小是imgsize*imgsize,现在想要切成patchsize*patchsize。

现在图像的大小是(batchsize channelsize imgsize imgsize),

设为(20, 3, 256, 256),设patch_size = 32。设置中间层大小是dim=1024,所以:

1、Patch Embeddings:切块。

切的块数为w=(image_size / patch_size),h=(image_size / patch_size),横向切成w个,纵向切成h个,总体个数为w*h=num

a. 转换为(batchsize, num,patchsize*patchsize*channelsize)

即将第2维度变换为块的个数,将图像切块后展平

b.得到w*h个数据,每个数据的大小是patchsize*patchsize*channelsize,由于每个数据的大小太大,经过一个线性变换,将每个输入的大小处理为中间层大小dim

切块后,得到patch_embedding数据,(batchsize,num,dim)

2、Patch Embeddings:可学习的分类向量,加入可学习的嵌入向量作为分类向量预测结果。Position Embeddings:位置编码保留块之间的位置信息,直接加入进入x + self.pos_embed(扰动不变性,打乱顺序不会改变结果)

3、transformer:得到的(batchsize,num+1,dim)进行attention操作:

可以参考源代码知道attention的操作过程:

# MHA
class Attention(nn.Module):
    def __init__(self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., proj_drop=0.):
        super().__init__()
 
        self.num_heads = num_heads
        head_dim = dim // num_heads
 
        self.scale = qk_scale or head_dim ** -0.5
 
        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
        self.attn_drop = nn.Dropout(attn_drop)
        self.proj = nn.Linear(dim, dim)
 
        # 附带 dropout
        self.proj_drop = nn.Dropout(proj_drop)
 
    def forward(self, x):
        B, N, C = x.shape
        qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
        q, k, v = qkv[0], qkv[1], qkv[2]  # make torchscript happy (cannot use tensor as tuple)
 
        attn = (q @ k.transpose(-2, -1)) * self.scale
        attn = attn.softmax(dim=-1)
        attn = self.attn_drop(attn)
 
        x = (attn @ v).transpose(1, 2).reshape(B, N, C)
        x = self.proj(x)
        x = self.proj_drop(x)
 
        return x

即可知,attention操作的步骤是先通过线性层使维度数*3,即大小为(batchsize,num+1,dim)变成(batchsize,num+1,dim*3),分别取出每一个dim作为q、k、v。再分割出numhead的数量大小为:(batchsize,numhead,num+1,dim/numhead),k*q后乘以scale,再经过softmax后,乘v,最后得到的结果大小为:(batchsize,numhead,num+1,dim/numhead),reshape后得到(batchsize,num+1,dim)尺寸的结果即为输出。

a.深度depth=transformer块的使用个数,每个里面都包括以下的操作:

 先把x进行norm归一化,再做kqv操作,得到的output效果加x=y

y再经过一个norm归一化,得到的结果经过线性变换,得到新的output,再与y相加,output+y=dst

b.把得到的dst作为x重新输入,经过depth次,得到最后的out

每经过一个块,大小都不变,

最终的结果仍然是(batchsize,num+1,dim)

4、第二维的数据mean或直接取类别向量操作,得到(batchsize,dim)

5、经过norm正则化+线性输出,得到(batchsize,classnum)

参考:

参考:【机器学习】详解 Vision Transformer (ViT)_闻韶-CSDN博客_vit位置编码

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的示例代码,用于实现Vision Transformer (ViT)的Transformer模型部分: ```python import torch import torch.nn as nn import torch.nn.functional as F class PatchEmbedding(nn.Module): def __init__(self, image_size, patch_size, in_channels, embed_dim): super().__init__() self.image_size = image_size self.patch_size = patch_size self.num_patches = (image_size // patch_size) ** 2 self.patch_embedding = nn.Conv2d(in_channels, embed_dim, kernel_size=patch_size, stride=patch_size) def forward(self, x): x = self.patch_embedding(x) x = x.flatten(2).transpose(1, 2) return x class Transformer(nn.Module): def __init__(self, embed_dim, num_heads, num_layers, hidden_dim, dropout): super().__init__() self.encoder_layers = nn.ModuleList([ nn.TransformerEncoderLayer(d_model=embed_dim, nhead=num_heads, dim_feedforward=hidden_dim, dropout=dropout) for _ in range(num_layers) ]) def forward(self, x): for layer in self.encoder_layers: x = layer(x) return x class ViT(nn.Module): def __init__(self, image_size, patch_size, in_channels, embed_dim, num_heads, num_layers, hidden_dim, num_classes): super().__init__() self.patch_embedding = PatchEmbedding(image_size, patch_size, in_channels, embed_dim) self.transformer = Transformer(embed_dim, num_heads, num_layers, hidden_dim, dropout=0.1) self.classifier = nn.Linear(embed_dim, num_classes) def forward(self, x): x = self.patch_embedding(x) x = self.transformer(x) x = x.mean(1) x = self.classifier(x) return x ``` 这段代码定义了一个简单的Vision Transformer模型,包括PatchEmbedding模块、Transformer模块和ViT模型。你可以根据需要进行修改和扩展。请注意,此代码只包括Transformer的模型部分,有关数据加载和训练的部分需要根据具体任务进行实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值