Vision Transformer (ViT)的原理讲解与后续革新【附上pytorch的代码!】

Vision Transformer (ViT)详解

一、背景介绍

  Vision Transformer (ViT)是Google团队在2020年提出的一种新型图像分类模型,它成功地将Transformer架构应用于视觉领域。通过将图像分割成多个patch并送入Transformer编码器处理,ViT模型能够在大规模数据集上实现卓越的性能,超越了传统的CNN模型。本文将详细解析ViT模型的工作原理、关键组件以及代码实现。以新手的身份来谈谈自己的理解。
在这里插入图片描述

二、相关工作

  Transformers最初由Vaswani等人提出,用于机器翻译任务,并随后在多个NLP任务中取得了显著成果。这些基于大型Transformers的模型通常首先在大型语料库上进行预训练,然后根据具体下游任务进行微调。ViT模型借鉴了这种预训练与微调的策略,将其应用于图像分类任务中。

三、方法

  1. 图像块嵌入 (Patch Embeddings)
      ViT模型首先将输入图像分割成一系列固定大小的patch(例如16x16像素)。然后,每个patch通过线性层转换为固定长度的向量,这些向量将作为Transformer编码器的输入。

  2. 可学习的位置嵌入 (Learnable Position Embeddings)
      由于Transformer模型本身不具有处理序列位置信息的能力,因此ViT引入了可学习的位置嵌入来弥补这一缺陷。位置嵌入是一个与patch嵌入维度相同的向量表,其中每一行代表一个位置向量。通过将位置嵌入与patch嵌入相加,模型能够捕捉到图像中不同位置的信息。
    在这里插入图片描述

  3. Transformer 编码器
      ViT模型的核心组件是Transformer编码器,它负责处理经过嵌入的图像块序列。Transformer编码器由多个堆叠的编码器层组成,每个编码器层包含自注意力机制和前馈神经网络。通过多层堆叠,模型能够捕捉到图像中的多层次信息。
    在这里插入图片描述

# 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
  1. 归纳偏置与混合架构
      与CNN模型相比,ViT模型摒弃了卷积操作,完全依赖于自注意力机制来处理图像块序列。这种设计使得ViT能够捕捉到图像中的全局信息,并在大规模预训练后在多个图像识别任务中取得优异的结果。同时,一些研究也探索了将CNN与Transformer相结合的混合架构,以进一步提升模型性能。

  2. 微调及更高分辨率
      在预训练阶段,ViT模型通常在大规模数据集上进行训练,以学习通用的视觉特征。然后,针对具体的下游任务(如图像分类、目标检测等),可以通过微调来使模型适应任务需求。此外,为了适应更高分辨率的输入图像,可以采用插值等方法对patch嵌入进行调整。

  3. 超参数调整
      在训练ViT模型时,学习率是一个关键的超参数。适当的学习率可以加速模型的收敛速度并提升性能。因此,在训练过程中需要对学习率进行细致的调整和优化。

四、实验

  为了验证ViT模型的有效性,原文在多个图像分类数据集上进行了实验。实验结果表明,ViT模型在大规模数据集上取得了显著的性能提升,并且在微调后能够很好地适应不同的下游任务。
在这里插入图片描述

五、后续相关工作

  Vision Transformer(ViT)无疑是近年来计算机视觉领域的一项重大突破,其将Transformer架构成功引入图像识别任务,为处理大尺寸图像和长序列数据提供了一种全新的视角。自ViT模型问世以来,其在图像分类、目标检测等多个任务上均取得了卓越的性能,为计算机视觉领域的发展注入了新的活力。
  在ViT的基础上,后续的研究工作主要围绕模型优化、性能提升以及跨领域应用展开。首先,针对ViT模型参数量和计算量较大的问题,研究者们通过改进模型架构,引入残差注意力模块等方法,有效地减少了模型的参数量和计算量,同时提升了模型的性能。这些改进不仅使得ViT模型在处理大规模数据集时更加高效,还增强了模型对平移不变性的鲁棒性。
  其次,随着预训练技术的发展,研究者们开始探索ViT模型的预训练方法和微调技术。通过在大规模数据集上进行预训练,ViT模型能够学习到更加丰富的视觉特征,从而提高了其在下游任务中的性能。此外,跨模态应用也是ViT模型发展的重要方向之一。通过将图像和文本数据相结合,研究者们构建了一种基于ViT的跨模态模型,用于图像和文本的分类和生成等任务。这种跨模态应用不仅拓展了ViT的应用范围,也为计算机视觉和自然语言处理之间的交互提供了新的思路。ViT模型还在实时性应用和多任务学习等领域展现出巨大的潜力。通过将ViT与轻量级神经网络相结合,研究者们构建了一种高效的实时性目标检测系统,用于监控和安全等领域。同时,为了进一步提高ViT的性能和应用范围,研究者们还尝试了将ViT应用于多任务学习中,通过共享底层特征和信息交互,实现了多个任务的同时优化。

参考资料

论文:Vision Transformer
博客:Vision Transformer详解

版权声明

本博客内容仅供学习交流,转载请注明出处。

  • 25
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于Vision Transformer模型的搭建,我可以给你一些指导。 首先,你需要导入PyTorch和一些其他的必要库。下面是一个简单的示例: ```python import torch import torch.nn as nn import torch.nn.functional as F from einops.layers.torch import Rearrange ``` 接下来,你需要定义模型的各个模块。一个标准的Vision Transformer模型由多个Transformer层组成,每个Transformer层包含了多头自注意力机制、前馈网络和残差连接。下面是一个简单的Transformer层的示例: ```python class TransformerBlock(nn.Module): def __init__(self, embed_dim, num_heads, dropout=0.1): super().__init__() self.attention = nn.MultiheadAttention(embed_dim, num_heads) self.norm1 = nn.LayerNorm(embed_dim) self.dropout1 = nn.Dropout(dropout) self.fc = nn.Sequential( nn.Linear(embed_dim, 4 * embed_dim), nn.GELU(), nn.Linear(4 * embed_dim, embed_dim), nn.Dropout(dropout) ) self.norm2 = nn.LayerNorm(embed_dim) self.dropout2 = nn.Dropout(dropout) def forward(self, x): attn_output, _ = self.attention(x, x, x) x = self.norm1(x + self.dropout1(attn_output)) fc_output = self.fc(x) x = self.norm2(x + self.dropout2(fc_output)) return x ``` 接下来,你需要将多个Transformer层堆叠起来组成一个完整的Vision Transformer模型。这个示例中,我们还添加了一个可训练的分类头用于图像分类任务: ```python class VisionTransformer(nn.Module): def __init__(self, num_classes, image_size=224, patch_size=16, embed_dim=768, depth=12, num_heads=12, mlp_ratio=4., dropout=0.1): super().__init__() assert image_size % patch_size == 0, "Image size must be divisible by patch size." num_patches = (image_size // patch_size) ** 2 patch_dim = 3 * patch_size ** 2 self.patch_embedding = nn.Sequential( Rearrange('b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1=patch_size, p2=patch_size), nn.Linear(patch_dim, embed_dim), nn.Dropout(dropout) ) self.positional_encoding = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim)) self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) self.transformer_blocks = nn.ModuleList([ TransformerBlock(embed_dim, num_heads, dropout) for _ in range(depth) ]) self.mlp_head = nn.Sequential( nn.LayerNorm(embed_dim), nn.Linear(embed_dim, int(embed_dim * mlp_ratio)), nn.GELU(), nn.Dropout(dropout), nn.Linear(int(embed_dim * mlp_ratio), num_classes) ) def forward(self, x): b = x.shape[0] x = self.patch_embedding(x) cls_tokens = self.cls_token.expand(b, -1, -1) x = torch.cat((cls_tokens, x), dim=1) x += self.positional_encoding[:, :(x.shape[1]), :] for transformer_block in self.transformer_blocks: x = transformer_block(x) x = x.mean(dim=1) x = self.mlp_head(x) return x ``` 最后,你可以实例化该模型并传递输入数据来进行推理或训练: ```python model = VisionTransformer(num_classes=10) input_data = torch.randn((1, 3, 224, 224)) output = model(input_data) ``` 希望这能够帮助到你。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值