图像识别中的 Vision Transformers (ViT)

引言

Vision Transformers (ViT) 最近已成为卷积神经网络(CNN) 的竞争替代品,而卷积神经网络 (CNN) 目前在不同的图像识别计算机视觉任务中处于最先进的水平。ViT 模型在计算效率和准确性方面比当前最先进的 (CNN) 模型高出近 4 倍。

Transformer 模型已成为自然语言处理 (NLP) 领域事实上的SOTA。例如,流行的 ChatGPT AI 聊天机器人就是基于 Transformer 的语言模型。具体来说,它基于 GPT(生成式预训练Transformer)架构,该架构使用自注意力机制来对文本中单词之间的依赖关系进行建模。 在计算机视觉研究中,最近人们对Vision Transformers (ViT) 和多层感知机 (MLP)的兴趣日益浓厚。

本文将涵盖以下主题:

  • 什么是Vision Transformers (ViT)?
  • 在图像识别中使用 ViT 模型
  • Vision Transformers如何工作?
  • Vision Transformer 的用例和应用

图像识别中的 Vision Transformer (ViT)

虽然 Transformer 架构已成为涉及自然语言处理 (NLP)的任务的事实基准,但其与计算机视觉 (CV)相关的用例仍然很少。在许多计算机视觉任务中,注意力要么与卷积网络(CNN)结合使用,要么用于替代卷积网络的某些方面,同时保持其整个组成完整。流行的图像识别算法包括ResNet、VGG、YOLOv3、YOLOv7或YOLOv8以及Segment Anything (SAM)。下图展示了广泛流行的CNN结构:
在这里插入图片描述
然而,这种对 CNN 的依赖不是强制性的,直接应用于图像块序列的纯 Transformer 可以在图像分类任务上表现得非常好。

Vision Transformers在CV中的性能

Vision Transformers (ViT)最近在 图像分类、目标检测和语义分割等多种计算机视觉应用的基准测试中取得了极具竞争力的性能。 CSWin Transformer是一个高效且有效的基于 Transformer 的主干网,用于通用视觉任务。它使用一种名为“十字形窗口自注意力”的新技术来同时分析图像的不同部分,从而使其速度更快。 CSWin Transformer 超越了 Swin Transformer 等之前最先进的方法。在基准任务中,CSWIN取得了优异的性能,包括在ImageNet-1K上达到85.4%的Top-1准确率,在COCO检测任务上达到53.9 box AP和46.4 mask AP,在ADE20K语义分割任务上达到52.2 mIOU。下图展示了CV中的分割应用:
在这里插入图片描述

什么是Vision Transformers?

在 ICLR 2021 上作为会议论文发表的一篇研究论文中介绍了 Vision Transformer (ViT) 模型架构,题为“An Image is Worth 16*16 Words: Transformers for Image Recognition at Scale”。它由 Neil Houlsby、Alexey Dosovitskiy 以及Google 研究大脑团队的另外 10 位作者开发和发布。 微调代码 和预训练的ViT模型可在 Google 研究团队的 GitHub 上获取。 你可以在这里找到它们。ViT 模型在 ImageNet 和 ImageNet-21k 数据集上进行了预训练。

Vision Transformers模型的起源和历史

下面,我们重点介绍多年来开发的一些最重要的Vision Transformers。它们基于 Transformer 架构,该架构最初于 2017 年提出用于自然语言处理 (NLP)。

在这里插入图片描述

Transformer 是一种深度学习方法吗?

机器学习中的Transformer是一种深度学习模型,它使用注意力机制,对输入数据序列的每个部分的重要性进行不同的权衡。机器学习中的 Transformer 由多个自注意力层组成。它们主要用于自然语言处理(NLP)和计算机视觉(CV)的人工智能子领域。 机器学习中的Transformer有很大潜力成为可应用于各种数据模态的通用学习方法,包括计算机视觉领域最近取得的突破,以更好的参数效率实现了最先进的标准精度。

Vision Transformers和图像分类

图像分类是计算机视觉中的一项基本任务,涉及根据图像的内容为其分配标签。多年来,像YOLOv7这样的深度卷积神经网络 (CNN)一直是最先进的图像分类方法。 然而,Transformer架构的最新进展最初是为自然语言处理(NLP)而引入的,在图像分类任务中取得有竞争力的结果显示出了巨大的希望。下图展示了医疗图像分类的一个具体应用:
在这里插入图片描述
CrossViT就是一个例子,它是一种用于图像分类的交叉注意力ViT。计算机视觉研究表明,当使用足够多的数据进行预训练时,ViT 模型至少与ResNet 模型一样稳健。 其他论文表明,Vision Transformer 模型在保护隐私的图像分类方面具有巨大潜力,并且在抵御攻击的鲁棒性和分类准确性方面优于最先进的方法。

CNN 和 ViT 的区别(ViT vs. CNN)

与卷积神经网络 (CNN) 相比,Vision Transformer (ViT) 取得了显著的效果,同时需要的预训练计算资源要少得多。与 卷积神经网络 (CNN)相比,Vision Transformer (ViT) 通常表现出较弱的归纳偏差,导致 在较小数据集上训练时对模型正则化或数据增强(AugReg)的依赖增加。 ViT 是一种基于Transformer架构的视觉模型,最初是为基于文本的任务而设计的。ViT 模型将输入图像表示为一系列图像块,就像使用Transformer处理文本时使用的一系列词嵌入一样,并直接预测图像的类标签。当使用足够的数据进行训练时,ViT 表现出非凡的性能,以减少 4 倍的计算资源打破了类似的最先进 CNN 的性能。下图展示了CNN vs ViT 的FLOPs和吞吐量:
在这里插入图片描述
这些 Transformer 在 NLP 模型方面具有很高的成功率,现在也应用于图像识别任务。CNN 使用像素数组,而 ViT 将输入图像切分成视觉tokens。ViT将图像划分为固定大小的块,正确地嵌入每个块,并将位置嵌入作为Transformer编码器的输入。此外,在计算效率和准确性方面,ViT 模型的性能比 CNN 高出近四倍。

ViT 中的自注意力层使得在整个图像中全局嵌入信息成为可能。该模型还学习训练数据来对图像块的相对位置进行编码,以重建图像的结构。

ViT包括以下内容:

  • 多头自注意力层(MSP):该层将所有注意力输出线性连接到正确的维度。许多注意力头有助于训练图像中的局部和全局依赖性。
  • 多层感知器 (MLP) 层:该层包含具有高斯误差线性单元 (GELU) 的两层。
  • 层范数 (LN):这是在每个块之前添加的,因为它不包含训练图像之间的任何新依赖关系。这有助于提高训练时间和整体表现。

此外,每个块之后都包含残差连接,因为它们允许组件直接流过网络,而无需经过非线性激活。 在图像分类的情况下,MLP 层实现分类头。它在预训练时使用一个隐藏层,并使用一个线性层进行微调。

什么是 Vision Transformer 的 self-attention?

自注意力机制是 Transformer 架构的关键组成部分,用于捕获输入数据中的远程依赖关系和上下文信息。自注意力机制允许 ViT 模型根据输入数据与当前任务的相关性来关注输入数据的不同区域。

因此,自注意力机制计算输入数据的加权和,其中权重是根据输入特征之间的相似性计算的。这使得模型能够更加重视相关的输入特征,这有助于它捕获输入数据的更多信息表示。

因此,自注意力是一种计算原生语言,用于量化成对实体交互,帮助网络学习输入数据中存在的层次结构和对齐方式。事实证明,注意力是视觉网络实现更高鲁棒性的关键要素。下图展示了原始图像(左)和 ViT-S/16 模型的注意力图(右):
在这里插入图片描述

ViT 的注意力图是什么?

Vision Transformer (ViT) 的注意力图是表示输入图像的不同部分对模型学习表示的不同部分的重要性的矩阵。在 ViT 中,输入数据的整个图像首先被划分为不重叠的块,然后将其展平并输入到 Transformer 编码器中(更多关于下面的架构)。

注意力图是指在图像中的每个token(或块)与所有其他tokens之间计算的注意力权重的可视化。这些注意力图是使用自注意力机制计算的,其中每个token都会关注所有其他token以获得其表示的加权和。

注意力图可以可视化为热力图网格,其中每个热力图代表给定token和所有其他token之间的注意力权重。热力图中像素的颜色越亮,相应token之间的注意力权重就越高。通过分析注意力图,我们可以深入了解图像的哪些部分对于手头的分类任务最重要。下图展示了来自 ImageNet-A- Source的图像上 ViT 注意力图的可视化:
在这里插入图片描述

ViT 架构

文献中已经提出了几种ViT模型。Vision Transformer架构的整体结构包括以下步骤:

  • 将图像分割成patches(固定大小)
  • 展平图像patches
  • 从这些展平的图像块创建低维线性嵌入
  • 引入位置嵌入
  • 将序列作为输入提供给最先进的ViT
  • 使用图像标签预训练 ViT 模型,然后在大数据集上进行全面监督
  • 微调下游数据集以进行图像分类

下图展示了Vision Transformer 架构:
在这里插入图片描述
Vision Transformers (ViT) 是一种使用自注意力机制来处理图像的架构。Vision Transformer 架构由一系列Transformer blocks组成。每个Transformer block由两个子层组成:多头自注意力层和前馈层。

自注意力层根据图像中每个像素与所有其他像素的关系计算其注意力权重,而前馈层对自注意力层的输出应用非线性变换。多头注意力通过允许模型同时关注输入序列的不同部分来扩展这种机制。

ViT 还包括一个额外的patch嵌入层,它将图像划分为固定大小的patches,并将每个patch映射到高维向量表示。然后将这些patch嵌入馈送到Transformer blocks中以进行进一步处理。 ViT 架构的最终输出是类预测,通过将最后一个 Transformer 块的输出传递给分类头来获得,分类头通常由单个全连接层组成。下图展示了在 ImageNet 上从头开始训练时,Vision Transformers (ViT) 与ResNet和 MobileNet 的性能基准比较。
在这里插入图片描述

虽然 ViT full-transformer架构对于视觉处理任务来说是一个有潜力的选择,但当在 ImageNet 等中等规模的数据集上从头开始训练时,ViT 的性能仍然不如类似大小的 CNN 替代方案(例如ResNet )。总体而言,ViT 架构允许以更灵活、更高效的方式处理图像,而无需依赖预定义的手工特征。

ViT如何工作?

ViT模型的性能取决于优化器、网络深度和特定于数据集的超参数等决策。与 ViT 相比,CNN 更容易优化。 纯 Transformer 的不同之处在于将 Transformer 与 CNN 前端结合起来。通常的 ViT 词干利用 1616 卷积和 16 步长。相比之下,步幅为 2 的 33 卷积增加了稳定性并提高了精度。

CNN 将基本像素转换为特征图。随后,特征图被分词器转换为一系列分词,然后输入到Transformer中。然后,Transformer应用注意力技术来创建一系列输出token。 最终,一个projector将输出token重新连接到特征图。后者允许检查潜在的关键像素级细节。这从而减少了需要研究的token数量,从而显着降低了成本。

特别的,如果 ViT 模型在超过 1400 万张图像的庞大数据集上进行训练,它的性能可以超越 CNN。如果没有,最好的选择是坚持使用ResNet或 EfficientNet。

ViT模型甚至在微调过程之前就在巨大的数据集上进行了训练。唯一的变化是忽略 MLP 层并添加新的 D 倍 KD*K 层,其中 K 是小数据集的类数。 为了微调更好的分辨率,完成了预训练位置嵌入的 2D 表示。这是因为可训练的衬垫层对位置嵌入进行建模。

ViT的挑战

ViT面临很多挑战,其中包括与架构设计、泛化、鲁棒性、可解释性和效率相关的问题。 总的来说,Transformer 与 CNN 相比缺乏一些归纳偏差,并且严重依赖海量数据集进行大规模训练,这就是为什么数据质量显着影响 Transformer 在计算机视觉任务中的泛化性和鲁棒性。

虽然 ViT 在 VTAB 和 CIFAR 等下游图像分类任务上表现出出色的性能,但直接将 ViT 主干应用于目标检测未能超越 CNN 的结果。

此外,充分理解为什么 Transformer 在视觉任务上表现良好仍然是一个挑战。此外,开发可部署在资源有限设备上的高效计算机视觉Transformer模型是一个具有挑战性的问题。

真实世界 ViT 应用

ViT在流行的图像识别任务中有着广泛的应用,例如目标检测、分割、图像分类和动作识别。此外,ViT 还应用于生成建模和多模型任务,包括视觉基础、视觉问答和视觉推理。 视频预测和活动识别都是视频处理中需要ViT的部分。此外,图像增强、着色和图像超分辨率也使用ViT模型。最后但并非最不重要的一点是,ViT 在 3D 分析中有许多应用,例如分割和点云分类。下图展示了体育运动中图像分割的一个应用:
在这里插入图片描述

结论

ViT模型在计算机视觉中使用多头自注意力,不需要图像领域特定的bias。该模型将图像切分成一系列位置嵌入块,由Transformer编码器处理。 这样做是为了了解图像所具有的局部和全局特征。最后但并非最不重要的一点是,ViT 在大型数据集上具有更高的准确率,同时减少了训练时间。

  • 31
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于vit图像识别代码,一般分为以下几个步骤:数据准备、模型构建、模型训练和模型评估。具体实现过程可以参考以下代码: 1. 数据准备 ``` from torchvision import transforms, datasets data_transform = transforms.Compose([ transforms.Resize(224), # 缩放到指定大小 transforms.CenterCrop(224), # 居裁剪 transforms.ToTensor(), # 转化为张量 transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) # 标准化 ]) train_dataset = datasets.ImageFolder(root='train_path', transform=data_transform) val_dataset = datasets.ImageFolder(root='val_path', transform=data_transform) ``` 2. 模型构建 ``` import torch.nn as nn class ViT(nn.Module): def __init__(self, img_size, patch_size, num_classes, dim): super().__init__() self.patch_size = patch_size num_patches = (img_size // patch_size) ** 2 patch_dim = 3 * patch_size ** 2 # 输入的通道数,3表示RGB通道 self.class_embed = nn.Parameter(torch.randn(1, 1, dim)) self.patch_embed = nn.Linear(patch_dim, dim) self.pos_embed = nn.Parameter(torch.randn(1, num_patches + 1, dim)) self.cls_token = nn.Parameter(torch.randn(1, 1, dim)) self.transformer = nn.TransformerEncoderLayer(d_model=dim, nhead=8) self.linear = nn.Linear(dim, num_classes) def forward(self, x): batch_size, _, _, _ = x.shape patches = x.unfold(2, self.patch_size, self.patch_size).unfold(3, self.patch_size, self.patch_size) patches = patches.flatten(2).transpose(1, 2) patch_embed = self.patch_embed(patches) pos_embed = self.pos_embed[:, :(patches.size(1) + 1)] cls_tokens = self.cls_token.expand(batch_size, -1, -1) x = torch.cat([cls_tokens, patch_embed], dim=1) x += pos_embed x = self.transformer(x) x = x.mean(dim=1) x = self.linear(x) return x ``` 3. 模型训练 ``` import torch.optim as optim device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') model = ViT(img_size=224, patch_size=16, num_classes=10, dim=512).to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9) scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1) num_epochs = 50 for epoch in range(num_epochs): train_loss = 0.0 train_acc = 0.0 model.train() for inputs, labels in train_loader: inputs = inputs.to(device) labels = labels.to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() train_loss += loss.item() * inputs.size(0) _, preds = torch.max(outputs, 1) train_acc += torch.sum(preds == labels.data) train_loss /= len(train_loader.dataset) train_acc = train_acc.float() / len(train_loader.dataset) val_loss = 0.0 val_acc = 0.0 model.eval() with torch.no_grad(): for inputs, labels in val_loader: inputs = inputs.to(device) labels = labels.to(device) outputs = model(inputs) loss = criterion(outputs, labels) val_loss += loss.item() * inputs.size(0) _, preds = torch.max(outputs, 1) val_acc += torch.sum(preds == labels.data) val_loss /= len(val_loader.dataset) val_acc = val_acc.float() / len(val_loader.dataset) scheduler.step() print('[Epoch %d/%d] Train Loss: %.4f, Train Acc: %.4f, Val Loss: %.4f, Val Acc: %.4f' \ % (epoch + 1, num_epochs, train_loss, train_acc, val_loss, val_acc)) ``` 4. 模型评估 ``` correct = 0 total = 0 model.eval() with torch.no_grad(): for data in test_loader: images, labels = data images = images.to(device) labels = labels.to(device) outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the test images: %d %%' % (100 * correct / total)) ``` 以上代码仅为参考,实际实现时需要根据具体的需求进行相应的修改和调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值