论文阅读6——VIT:Vision Transformer(包括ViT代码复现)

论文原文地址:https://openreview.net/pdf?id=YicbFdNTTy

代码地址:https://github.com/google-research/vision_transformer

Pytorch版本代码:https://github.com/lucidrains/vit-pytorch

目录

论文翻译

摘要

1 介绍

2 相关工作

3 方法

3.1 VISION TRANSFORMER (ViT)

3.2 微调和更高分辨率

4 实验

4.1 设置

4.2与现有技术的比较

4.3 预训练数据要求

4.4 规模研究

4.5 预测视觉Transformer

4.6 自监督

5 结论

学习笔记

ViT与Transformer的关系

架构图详细解释

ViT代码复现——以Pytorch-VIT为例(包括部分运行结果)

第一步:进入github下载代码并解压

第二步:用Pycharm打开项目

第三步:阅读README.md文件

第四步:获得图像高维特征向量

第五步:使用 Hugging Face 加载 ViT 模型进行图像分类


论文翻译

AN IMAGE IS WORTH 16X16 WORDS:
TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE

一张图片胜过16X16个单词:用于大规模图像识别的变换器

摘要

虽然Transformer架构已成为自然语言处理任务的事实标准,但其在计算机视觉中的应用仍然有限。在视觉中,注意力要么与卷积网络结合应用,要么用于替换卷积网络的某些组件,同时保持其整体结构。我们表明,这种对CNN的依赖是没有必要的,并且直接应用于图像补丁序列的纯Transformer可以在图像分类任务中表现得非常好。当对大量数据进行预训练并传输到多个中型或小型图像识别基准(ImageNet、CIFAR-100、VTab等)时,与最先进的卷积网络相比,Vision Transformer(ViT)可以获得出色的结果,同时训练所需的计算资源少得多。

1 介绍

基于自我注意力的架构,特别是Transformers(Vaswani等人,2017),已成为自然语言处理(NLP)的首选模型。主要的方法是在大型文本库上进行预训练,然后在较小的特定任务数据集上进行微调(Devlin et al,2019)。得益于Transformers的计算效率和可扩展性,训练参数超过100 B的前所未有规模的模型已成为可能(Brown et al,2020; Lepikhin et al,2020)。随着模型和数据集的增长,仍然没有表现饱和的迹象。

然而,在计算机视觉中,卷积架构仍然占主导地位(LeCun等人,1989; Krizhevsky等人,2012; He等人,2016)。受NLP成功的启发,多部作品尝试将类似CNN的架构与自我注意力结合起来(Wang等人,2018; Carion等人,2020),其中一些完全取代了卷积(Ramachandran等人,2019; Wang等人,2020 a)。后一种模型虽然理论上有效,但由于使用专门的注意力模式,尚未在现代硬件加速器上有效扩展。因此,在大规模图像识别中,经典的ResNet类架构仍然是最先进的(Mahajan等人,2018; Xie等人,2020; Kolesnikov等人,2020)。

受NLP中Transformer扩展成功的启发,我们尝试将标准Transformer直接应用于图像,并且修改尽可能少。为此,我们将图像分割为补丁,并提供这些补丁的线性嵌入序列作为Transformer的输入。在NLP应用程序中,图像补丁的处理方式与标记(单词)相同。我们以监督的方式训练模型进行图像分类。

当在没有强正规化的ImageNet等中等规模数据集上进行训练时,这些模型的准确性较同等规模的ResNet低几个百分点。这种看似令人沮丧的结果可能是意料之中的:变形者缺乏CNN固有的一些归纳偏差,例如翻译等方差和局部性,因此在数据量不足时无法很好地概括。

然而,如果模型在更大的数据集(14 M-300 M张图像)上训练,情况就会发生变化。我们发现大规模训练胜过归纳偏见。当以足够大的规模进行预训练并转移到具有更少数据点的任务时,我们的Vision Transformer(ViT)可以获得出色的结果。当在公共ImageNet-21 k数据集或内部JFT-300 M数据集上进行预训练时,ViT在多个图像识别基准上接近或超越了最新水平。特别是,最佳模型在ImageNet上的准确率为88:55%,在ImageNet-ReaL上的准确率为90:72%,在CIFAR-100上的准确率为94:55%,在包含19个任务的VTAB套件上的准确率为77:63%。

2 相关工作

Vaswani等人(2017年)提出了Transformers用于机器翻译,此后已成为许多NLP任务中的最先进方法。基于Transformer的大型模型通常在大型数据库上进行预训练,然后针对手头的任务进行微调:BERT(Devlin等人,2019)使用去噪自我监督预训练任务,而GPT工作线使用语言建模作为其预训练任务(Radford等人,2018; 2019; Brown等人,2020)。

对图像天真地应用自我注意力需要每个像素关注每个其他像素。由于像素数的二次成本,这无法扩展到现实的输入大小。因此,为了在图像处理的环境中应用变形金刚,过去已经尝试过几种近似。Parmar等人(2018)仅在每个查询像素的局部社区中应用自我注意力,而不是在全球范围内应用。这种局部多头点积自我注意块可以完全取代卷积(Hu等人,2019; Ramachandran等人,2019; Zhao等人,2020)。在另一项工作中,Sparse Transformers(Child等人,2019)采用可扩展的全球自我注意力逼近,以便适用于图像。衡量注意力的另一种方法是将其应用于不同大小的块(Weissenborn等人,2019),在极端情况下仅沿着单个轴应用(Ho等人,2019; Wang等人,2020 a)。许多这些专门的注意力架构在计算机视觉任务上展示了有希望的结果,但需要复杂的工程才能在硬件加速器上有效实施。

与我们最相关的是Cordonnier等人(2020)的模型,该模型从输入图像中提取大小为2 x 2的补丁,并在顶部应用完全的自我注意力。该模型与ViT非常相似,但我们的工作进一步证明,大规模预训练使vanilla Transformers能够与最先进的CNN竞争(甚至更好)。此外,Cordonnier等人(2020)使用了2 x 2像素的小补丁大小,这使得该模型仅适用于小分辨率图像,而我们也可以处理中分辨率图像。

人们对将卷积神经网络(CNN)与自我注意形式相结合也很感兴趣,例如通过增强图像分类的特征图(Bello等人,2019)或通过使用自我注意力进一步处理CNN的输出,例如用于对象检测(Hu等人,2018; Carion等人,2020),视频处理(Wang等人,2018; Sun等人,2019),图像分类(Wu等人,2020)、无监督对象发现(Locatello等人,2020)或统一文本视觉任务(Chen等人,2020 c; Lu等人,2019; Li等人,2019)。

最近的另一个相关模型是图像GPT(iGPT)(Chen等人,2020 a),它在降低图像分辨率和色彩空间后将变形金刚应用于图像像素。该模型以无监督的方式作为生成模型进行训练,然后可以对生成的表示进行微调或线性探索以获得分类性能,从而在ImageNet上实现72%的最高准确率。

我们的工作增加了越来越多的论文,这些论文以比标准ImageNet数据集更大的规模探索图像识别。使用额外的数据源可以在标准基准上实现最先进的结果(Mahajan等人,2018; Touvron等人,2019; Xie等人,2020)。此外,Sun等人(2017)研究了CNN性能如何随着数据集大小而变化,Kolesnikov等人(2020); Djolonga等人(2020)对来自ImageNet-21 k和JFT-300 M等大规模数据集的CNN迁移学习进行了实证探索。我们也关注后两个数据集,但训练Transformers,而不是之前作品中使用的基于ResNet的模型。

图1:模型概述。我们将图像分割成固定大小的补丁,线性嵌入其中的每个补丁,添加位置嵌入,并将生成的载体序列提供给标准的Transformer编码器。为了执行分类,我们使用标准方法,即向序列添加额外的可学习的“分类标记”。Transformer编码器的插图受到Vaswani等人(2017)的启发。

3 方法

在模型设计中,我们尽可能遵循最初的Transformer(Vaswani等人,2017)。这种故意简单设置的一个优点是,可扩展的NLP Transformer架构及其高效实现几乎可以立即使用。

3.1 VISION TRANSFORMER (ViT)

图1描述了该模型的概述。标准Transformer接收令牌嵌入的1D序列作为输入。为了处理2D图像,我们将图像重塑为一系列扁平化的2D补丁,其中(H, W)是原始图像的分辨率,C是通道数量,(P, P)是每个图像补丁的分辨率,

<think>好的,我现在要回答用户关于Vision TransformerViT)模型实现代码的问题。用户已经提供了相关的引用内容,我需要结合这些引用,并按照系统级指令来组织回答。 首先,我需要确认用户的需求。用户明确提到想要寻找ViT模型的相关代码,因此我需要提供一个代码示例,并解释其结构。根据引用[1],ViT分为三个部分:图像特征嵌入模块、Transformer编码器模块和MLP分类模块。我需要确保代码结构覆盖这三个部分。 接下来,我需要考虑代码的实现。ViT使用Transformer的编码器部分,所以代码中应该包含多个Encoder Block。每个Encoder Block包括多头自注意力机制和前馈网络。同时,图像需要被分割成块并转换为嵌入向量,这可能通过卷积层或线性投影来实现。分类头通常是一个MLP。 在编写代码时,需要注意PyTorch的模块化设计,使用nn.Module来构建各个组件。例如,图像嵌入模块可能使用一个卷积层来将图像块展平为向量,并添加位置编码。然后,多个Transformer编码器层堆叠,最后通过MLP进行分类。 我需要确保代码符合用户提供的引用内容。引用[2]提到输入需要是token序列,即二维矩阵[num_token, token_dim],所以在嵌入模块中需要将图像转换为这样的形式。例如,将输入图像(假设为3x224x224)分割成16x16的块,每个块大小为16x16x3,总共有(224/16)^2 = 196个token,每个token的维度是16*16*3=768。这可以通过卷积核和步长均为16的卷积层来实现,输出形状为(196, 768)。 然后,位置编码需要添加到这些嵌入的块中。通常使用可学习的位置编码,即一个与token数量相同的嵌入层。接着,加上类别token(cls_token),用于最终的分类Transformer编码器部分需要实现多头自注意力和前馈网络。每个编码器层包括LayerNorm、多头注意力、残差连接、LayerNorm再次,然后是MLP。这些部分需要按照标准的Transformer编码器结构来编写。 最后,分类头部分取出cls_token,通过层归一化和MLP得到分类结果。 在代码示例中,我需要包含这些模块,并确保语法正确。同时,按照系统指令,独立公式使用$$...$$格式,行内公式用$...$。例如,图像分块的过程可以用公式表示,如将输入图像$x \in \mathbb{R}^{H \times W \times C}$分割为$N$个$P \times P$的块,其中$N = \frac{HW}{P^2}$,每个块展平后的维度为$P^2C$。 此外,需要生成相关问题,可能涉及ViT的结构细节、位置编码的作用、图像分块的影响、训练技巧等。这些问题应该帮助用户进一步理解ViT的实现和优化。 最后,检查引用是否正确添加。根据用户提供的引用,引用[1]和[2]需要自然地插入到回答中,例如在解释整体架构时引用[1],在讨论输入形式时引用[2]。 总结步骤: 1. 根据引用内容,分三个模块构建ViT代码结构。 2. 编写PyTorch代码包括嵌入模块、编码器层、分类头。 3. 解释代码各部分的功能,对应引用中的描述。 4. 生成相关问题,覆盖实现细节和扩展应用。 5. 确保LaTeX格式正确,引用标识正确放置。</think>以下提供基于PyTorch的简化版ViT模型实现代码,结合引用内容解析其核心模块: ```python import torch import torch.nn as nn class PatchEmbedding(nn.Module): def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768): super().__init__() self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size) # 将图像切分为16x16块并线性投影[^2] self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim)) self.pos_embed = nn.Parameter(torch.zeros(1, (img_size//patch_size)**2 + 1, embed_dim)) def forward(self, x): x = self.proj(x) # 输出形状: [B, embed_dim, H/P, W/P] x = x.flatten(2).transpose(1, 2) # 转换为[B, num_patches, embed_dim] cls_token = self.cls_token.expand(x.shape[0], -1, -1) x = torch.cat([cls_token, x], dim=1) # 添加分类token[^1] x += self.pos_embed return x class TransformerEncoder(nn.Module): def __init__(self, embed_dim, num_heads, mlp_ratio=4., depth=12): super().__init__() self.layers = nn.ModuleList([ nn.TransformerEncoderLayer(d_model=embed_dim, nhead=num_heads, dim_feedforward=int(embed_dim*mlp_ratio), activation='gelu') for _ in range(depth) ]) def forward(self, x): for layer in self.layers: x = layer(x) return x class VisionTransformer(nn.Module): def __init__(self, num_classes=1000): super().__init__() self.patch_embed = PatchEmbedding() self.encoder = TransformerEncoder(embed_dim=768, num_heads=12) self.head = nn.Sequential( nn.LayerNorm(768), nn.Linear(768, num_classes) ) def forward(self, x): x = self.patch_embed(x) # 图像特征嵌入模块 x = self.encoder(x) # Transformer编码器模块 cls_token = x[:, 0] # 提取分类token return self.head(cls_token) # MLP分类模块 ``` **代码解析:** 1. **图像分块嵌入**:将$224\times224$图像分割为$16\times16$的196个块,每个块展平为768维向量($16\times16\times3$),通过`PatchEmbedding`实现空间信息到序列的转换 2. **位置编码**:`pos_embed`为可学习的位置编码,与图像块嵌入相加,赋予模型空间位置感知能力 3. **分类token**:`cls_token`作为全局特征表示,最终用于分类任务 4. **Transformer编码器**:包含12层编码器(与原论文一致),每层包含多头自注意力和前馈网络 5. **分类头**:对`cls_token`进行层归一化后通过线性层输出分类结果 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值