ViT( Vision Transformer) 多头自注意力机制 计算机视觉领域应用Transformer架构的模型 首次将NLP领域中广泛使用的Transformer模型引入到了CV领域

ViT是首个将Transformer引入CV领域的模型,它在ImageNet上击败了当时的CNN。模型由Transformer编码器组成,使用多头自注意力机制处理图像块。ViT的优势在于其全局注意力机制和较低的参数数量,但挑战在于处理大图像时的计算复杂度和对大量数据的依赖。实验表明,ViT在大规模数据集上预训练后能取得SOTA性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ViT( Vision Transformer)

ViT(Vision Transformer)模型是一种在计算机视觉领域应用Transformer架构的模型。它首次将NLP领域中广泛使用的Transformer模型引入到了CV领域,并在ImageNet数据集上击败了当时最先进的CNN网络。

ViT模型的基本结构由Transformer编码器组成,其中包含多个Transformer编码层。每个编码层由多头自注意力机制(multi-head self-attention)和前馈神经网络(feed-forward neural network)组成。这种结构使得ViT能够充分捕捉图像中的全局信息和局部细节,从而实现准确的图像分类。

在ViT模型中,输入是一张图像,它首先被分割成一系列的图像块。每个图像块经过线性变换后,被展平成一个向量,并与位置编码相加。这样,每个图像块就被编码成一个向量表示,作为输入传递给Transformer编码器。每个编码层都包含一个多头自注意力机制和一个前馈神经网络,用于提取图像中的特征。

与CNN相比,ViT模型具有以下优势:

不依赖于卷积操作,减少了模型中的参数数量,从而降低了计算复杂度。
引入全局注意力机制,ViT模型能够有效地捕捉到图像中的全局信息,提高了在大规模图像数据集上的性能。

具有一定的泛化能力,可以应用于其他类型的数据,如自然语言处理中的序列数据。
然而,ViT模型也面临一些挑战。例如,对于较大的图像,ViT模型需要将其拆分为较小的图像块,这可能会导致信息丢失或精度下降。此外,ViT模型在处理高分辨率图像时的计算复杂度仍然较高。

ViT模型在中等规模(例如ImageNet)以及大规模(例如ImageNet-21K、JFT-300M)数据集上进行了实验验证。实验结果表明,当有大量的训练样本时,ViT模型可以达到或超越当前的SOTA水平。然而,在数据量不充分时,由于Transformer相较于CNN结构缺少一定的平移不变性和局部感知性,ViT模型的性能可能会受到一定影响。

模型介绍

在计算机视觉领域中,多数算法都是保持CNN整体结构不变,在CNN中增加attention模块或者使用attention模块替换CNN中的某些部分。有研究者提出,没有必要总是依赖于CNN。因此,作者提出ViT[1]算法,仅仅使用Transformer结构也能够在图像分类任务中表现很好。

受到NLP领域中Transformer成功应用的启发,ViT算法中尝试将标准的Transformer结构直接应用于图像,并对整个图像分类流程进行最少的修改。具体来讲,ViT算法中,会将整幅图像拆分成小图像块,然后把这些小图像块的线性嵌入序列作为Transformer的输入送入网络,然后使用监督学习的方式进行图像分类的训练。

该算法在中等规模(例如ImageNet)以及大规模(例如ImageNet-21K、JFT-300M)数据集上进行了实验验证,发现:

  • Transformer相较于CNN结构,缺少一定的平移不变性和局部感知性,因此在数据量不充分时,很难达到同等的效果。具体表现为使用中等规模的ImageNet训练的Transformer会比ResNet在精度上低几个百分点。
  • 当有大量的训练样本时,结果则会发生改变。使用大规模数据集进行预训练后,再使用迁移学习的方式应用到其他数据集上,可以达到或超越当前的SOTA水平。

模型结构与实现

ViT算法的整体结构如 图1 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图1 ViT算法结构示意图

1. 图像分块嵌入

考虑到在Transformer结构中,输入是一个二维的矩阵,矩阵的形状可以表示为 ( N , D ) (N,D) (N,D),其中 N N N 是sequence的长度,而 D D D 是sequence中每个向量的维度。因此,在ViT算法中,首先需要设法将 H × W × C H \times W \times C H×W×C 的三维图像转化为 ( N , D ) (N,D) (N,D) 的二维输入。

ViT中的具体实现方式为:将 H × W × C H \times W \times C H×W×C 的图像,变为一个 N × ( P 2 ∗ C ) N \times (P^2 * C) N×(P2C) 的序列。这个序列可以看作是一系列展平的图像块,也就是将图像切分成小块后,再将其展平。该序列中一共包含了 N = H W / P 2 N=HW/P^2 N=HW/P2 个图像块,每个图像块的维度则是 ( P 2 ∗ C ) (P^2*C) (P2C)。其中 P P P 是图像块的大小, C C C 是通道数量。经过如上变换,就可以将 N N N 视为sequence的长度了。

但是,此时每个图像块的维度是 ( P 2 ∗ C ) (P^2*C) (P2C),而我们实际需要的向量维度是 D D D,因此我们还需要对图像块进行 Embedding。这里 Embedding 的方式非常简单,只需要对每个 ( P 2 ∗ C ) (P^2*C) (P2C) 的图像块做一个线性变换,将维度压缩为 D D D 即可。

上述对图像进行分块以及 Embedding 的具体方式如 图2 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图2 图像分块嵌入示意图

ViT(Vision Transformer)中图像分块嵌入(Patch Embedding)的核心步骤。在ViT中,为了将图像输入到Transformer结构中,需要进行以下几步处理:

图像分块:

输入图像通常具有 H×W×C 的形状,其中 H 和 W 分别是图像的高度和宽度,C 是颜色通道数(在RGB图像中通常是3)。
图像被均匀地切分成大小为 P×P 的小块,其中 P 是块的大小。这可以通过在图像的高度和宽度上应用步长为 P 的滑动窗口来实现。
分块后,图像被表示为一个由 N=HW/P 2 个小块组成的集合

展平与连接:

每个 P×P×C 的图像块被展平成一个 P 2 ×C 的一维向量。
所有这些一维向量被连接成一个二维矩阵,其形状为 N×(P 2×C)。

Patch Embedding:

由于Transformer需要固定长度的输入,因此我们需要将每个图像块的维度从 P 2 ×C 转换为 D。

这通过线性变换(也称为嵌入层或全连接层)来实现,该变换将每个 P 2 ×C 的向量映射到一个 D 维的向量上。
结果是一个 N×D 的矩阵,可以直接作为Transformer的输入。

位置编码(可选):

由于Transformer本身不包含任何循环或卷积结构,因此它不知道输入序列中元素的位置信息。

为了解决这个问题,通常会在输入到Transformer之前添加一个位置编码(如正弦和余弦位置编码)。

位置编码与Patch Embedding的输出相加或拼接,以提供位置信息。
Transformer编码器:
经过Patch Embedding处理后的 N×D 矩阵被输入到Transformer编码器中。
Transformer编码器通过自注意力机制和多层前馈神经网络来捕捉图像块之间的依赖关系。

分类头(对于分类任务):

对于图像分类任务,Transformer编码器的输出通常会被送入一个额外的分类头(如全连接层)。

分类头将Transformer编码器的输出映射到类别分数的向量上。

通过上述步骤,ViT能够将图像作为一系列图像块的序列输入到Transformer中,从而利用Transformer强大的序列建模能力来处理图像数据。

具体代码实现如下所示。本文中将每个大小为 P P P 的图像块经过
大小为 P P P 的卷积核来代替原文中将大小为 P P P 的图像块展平后接全连接运算的操作。

# 图像分块、Embedding
class PatchEmbed(nn.Layer):
    def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768):
        super().__init__()
        # 原始大小为int,转为tuple,即:img_size原始输入224,变换后为[224,224]
        img_size = to_2tuple(img_size)
        patch_size = to_2tuple(patch_size)
        # 图像块的个数
        num_patches = (img_size[1] // patch_size[1]) * \
            (img_size[0] // patch_size[0])
        self.img_size = img_size
        self.patch_size = patch_size
        self.num_patches = num_patches
        # kernel_size=块大小,即每个块输出一个值,类似每个块展平后使用相同的全连接层进行处理
        # 输入维度为3,输出维度为块向量长度
        # 与原文中:分块、展平、全连接降维保持一致
        # 输出为[B, C, H, W]
        self.proj = nn.Conv2D(
            in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)

    
Transformer模型之所以在自然语言处理NLP)和计算机视觉CV)任务中大放异彩,关键在于其创新的自注意力(Self-Attention)机制和编码器-解码器(Encoder-Decoder)架构。这使得模型能够并行处理序列数据,极大地提高了计算效率。 参考资源链接:[Transformer模型深度解析:从NLPCV的革命](https://wenku.csdn.net/doc/2n8esevwot?spm=1055.2569.3001.10343)注意力机制允许模型在处理序列中的每个元素时,考虑整个序列的信息,而不是像传统的RNN或LSTM那样顺序地处理。这意味着对于一个序列,模型中的每个元素都可以独立地计算其输出,这就是并行化的关键所在。具体来说,对于序列中的每个元素,自注意力机制计算其与其他所有元素之间的关系,得到一个加权和,这反映了不同元素之间的相互影响。 Transformer的编码器由多个相同的编码器层堆叠而成,每层都包含一个多头自注意力机制和一个前馈神经网络。这些层共同工作,使得模型可以捕捉到序列中的复杂模式。解码器同样由多个解码器层组成,其中每个解码器层不仅包含自注意力机制,还包含编码器-解码器注意力机制,后者帮助模型将编码器的信息和当前解码状态结合起来,生成输出。 在NLP任务中,如机器翻译,Transformer可以并行处理输入序列的所有单词,并产生对应的输出序列。而在CV任务中,比如ViTVision Transformer),图像首先被切割为一系列的patches,每个patch被转换为向量表示,然后这些向量通过自注意力机制进行处理,以捕获图像内部的全局依赖关系。 这种并行化的能力,结合强大的训练效率和表现力,使得Transformer成为了NLPCV任务的主流架构,为各类深度学习应用开辟了新的可能性。如果你希望深入了解Transformer模型NLPCV中的具体应用和原理,推荐阅读《Transformer模型深度解析:从NLPCV的革命》。这本资料深入浅出地讲解了Transformer的每个组件,如何共同工作以及在不同领域应用案例,非常适合希望在AI领域深入研究的读者。 参考资源链接:[Transformer模型深度解析:从NLPCV的革命](https://wenku.csdn.net/doc/2n8esevwot?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EwenWanW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值