ViT | Vision Transformer 回顾(理论+代码)

论文链接:[2010.11929] An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale

参考视频:

ViT论文逐段精读【论文精读】_哔哩哔哩_bilibili  (刚入门可以先看这个,bryanyzhu大佬带读,讲的非常细致,沐神出品,必属精品)

ViT| Vision Transformer |理论 + 代码_哔哩哔哩_bilibili (代码部分解读)

一、提出背景

Vision Transformer (ViT) 的提出背景源于对传统计算机视觉模型(尤其是卷积神经网络,CNN)的局限性的重新思考,以及 Transformer 架构在自然语言处理(NLP)领域成功的启发。

Transformer 的核心特性

  • Transformer 架构基于注意力机制(self-attention),能够捕获输入序列中全局范围的关系,而无需依赖于固定的局部感受野。
  • 它在 NLP 中已经成为事实上的标准架构,尤其是通过预训练与迁移学习(例如 BERT、GPT 系列),Transformer 在处理各种任务(如文本分类、翻译等)上表现出色。

CNN 的局限性:

尽管卷积神经网络(CNN)在计算机视觉领域长期占据主导地位,但其架构也存在一些局限性:

局部感受野

  • CNN 的核心卷积操作依赖于局部感受野,这使其在捕获全局上下文信息时并不高效。
  • 尽管可以通过堆叠多层卷积或引入全局池化来扩大感受野,但这通常会增加计算复杂度。

固定的结构设计

  • CNN 的设计往往遵循固定的层次结构(如 VGG、ResNet 的层次堆叠),难以灵活地捕获不同尺度下的全局特征。

对大规模数据的依赖

  • CNN 在小规模数据集上的表现有限,往往需要借助大规模预训练数据(例如 ImageNet)来提升性能。

 在 ViT 提出之前,注意力机制已经开始在视觉领域尝试与 CNN 进行结合:

结合 CNN 的注意力机制

  • 一些研究(例如 SENet、Non-Local Networks)尝试在 CNN 中引入注意力机制,以增强其对全局依赖关系的建模能力。
  • 这些方法往往是对 CNN 的辅助增强,而非彻底摆脱卷积操作。

局部和全局感受野的折中

  • 视觉模型通常需要在捕获局部精细特征与全局特征之间取得平衡,这为纯注意力模型的应用创造了机会。

 二、如何将2D图像转为1D序列?

简单想法:直接将2d图片按照像素拉直

存在问题:复杂度很高

解决方法:减少序列长度

相关工作:

  • 《Non-local neural network》用特征图当作transformer的输入。
  • 《Stand-alone self-attention in vision model》孤立自注意力。用局部的小窗口作为输入,通过控制窗口大小控制复杂度。
  • 《Axial-deeplab》把2d矩阵拆分成两个1d向量,先在H高度方向做一个自注意力,再从W宽度方向做一个自注意力。

ViT作者认为上述这些自注意力操作虽然理论高效,但属于比较特殊的自注意力操作,没有在现在的硬件上加速,很难训练大模型。

三、ViT的提出

将图像划分为若干图像块(patch),并将这些图像块的线性嵌入序列作为 Transformer 的输入。图像块在这种方法中被视为与 NLP 应用中的标记(token,单词)相同。

存在问题:当在中等规模的数据集(例如 ImageNet)上训练且未使用强正则化时,这些模型的准确率比同等规模的 ResNet 低约几个百分点。这是因为:Transformer 缺乏 CNN 自带的一些归纳偏置(inductive bias),例如平移不变性和局部性,因此在训练数据不足的情况下泛化性能较差。

优势:如果模型在更大规模的数据集(1400 万到 3 亿张图像)上进行训练,情况会发生变化。实验证明,大规模训练可以超越归纳偏置的限制。当 Vision Transformer (ViT) 在足够规模的数据集上预训练并迁移到数据量较少的任务时,可以获得卓越的效果。

什么是归纳偏置 Inductive biases?

答:就是先验知识。平移不变性(Translation Invariance)局部性(Locality) 是卷积神经网络(CNN)固有的归纳偏置。

什么是平移不变性和局部性?缺乏这些特性为什么会导致泛化性能差? 

答:

1. 平移不变性 Translation Invariance

定义:指的是图像中的物体或特征,无论在图像中的位置如何变化,CNN 都能有效地识别它们。例如,一个物体出现在图像的左上角,还是出现在右下角,CNN 都能保持较高的识别能力。

CNN如何实现?:在卷积神经网络中,卷积层的滤波器(或称卷积核)在整个图像上滑动(或“卷积”),从而捕获图像中的局部特征。由于滤波器在图像的每个位置进行相同的计算,因此 CNN 对图像中物体的平移具有不变性。

2.  局部性 Locality

定义:局部性指的是图像中的信息通常是局部的,即相邻像素之间存在较强的相关性。例如,图像中的一只动物的眼睛和鼻子通常在空间上是相邻的,它们的特征也密切相关。

CNN如何利用?:卷积操作通过局部感受野(receptive field)来捕捉相邻像素之间的关系。每个卷积层的滤波器只作用于图像的一小块区域,能够捕获局部的特征(如边缘、角点、纹理等)。这种局部性结构使得 CNN 可以逐步构建出复杂的图像特征,同时保持对相邻区域信息的敏感性。

强正则化 Strong Regularization

正则化的目标是通过限制模型的复杂度或引入某种约束,提升模型的泛化能力,使其在未见过的数据上表现更稳定。

在 ViT 中,正则化起到补偿作用,因为 Transformer 缺乏 CNN 的内在归纳偏置(例如平移等变性和局部性),因此需要额外的方法来提升泛化能力,尤其是在数据量不足的情况下。

常用强正则化手段:

(1) 权重正则化

  • L1 正则化:通过在目标函数中加入权重绝对值的和(稀疏约束),鼓励部分权重为零。

  • L2 正则化:通过在目标函数中加入权重平方的和(也称为权重衰减),限制权重的增长,降低模型复杂度。

(2) Dropout

  • 定义:在训练过程中随机丢弃部分神经元(置为 0),防止网络过度依赖某些特定的特征。

  • 作用:提升模型的鲁棒性,广泛应用于像 ViT 这样的深度网络。

(3) 数据增强

  • 定义:通过对训练数据施加某些变换(如翻转、旋转、裁剪、颜色调整等),生成更多样化的样本。

  • 作用:模拟更多的训练样本,间接减少模型的过拟合。

  • 在 ViT 中的应用:强数据增强(如 RandAugment 或 Mixup)在提升 Transformer 模型的泛化能力方面非常关键。

(4) Stochastic Depth(随机深度)

  • 定义:在训练期间随机跳过一些网络层。

  • 作用:提升深层网络的泛化性能,减少梯度消失问题。

  • 在 ViT 中的应用:ViT 使用随机深度来应对其深层架构的潜在问题。

(5) Label Smoothing(标签平滑)

  • 定义:将训练目标中的标签分布进行平滑处理(即使正确类别的标签概率低于 1,而其他类别概率略高于 0)。

  • 作用:防止模型过度自信地预测特定类别,从而提升泛化性能。

(6) 知识蒸馏(Knowledge Distillation)

  • 定义:通过使用一个预训练好的教师模型(通常更复杂或准确),引导学生模型学习软目标概率分布。

  • 作用:提升学生模型的泛化能力,减轻训练数据不足的影响。

(7) 正则化训练技巧

  • Early Stopping(早停法):在模型性能不再提升时停止训练,避免模型过度拟合。

  • Gradient Clipping(梯度裁剪):限制梯度的最大值,防止梯度爆炸。

四、ViT模型结构

  • 先将图片打成patch(这里是九宫格);
  •  将这些patch变成序列;
  • 每一个patch都会通过线性投射层操作得到一个特征,也就是patch embedding(注意图片是有顺序的,因此要加上位置编码);
  • 因此一个token包含一个patch原本的图片信息+一个位置编码信息;
  •  传入transformer encoder;

选择Encoder的哪一个输出表示类别分类?

借鉴了BETR的extra learnable embedding,也就是特殊字符——分类字符cls;

  •  ViT也加了分类字符,用 * 代替,也有position embedding——0
  •  因为所有的token都在做交互信息,所有class embedding 也能从其他所有的embedding学到有用的信息,从而只用class embedding的输出做判断就可以
  •  最后用传统的分类头去做分类。

 五、消融实验

5.1 Class Token

因为在NLP的分类任务中使用了class Token代表语句理解的一个全局特征,作者想和原始的Transformer保持尽可能的一致,所以也使用了class token。

在Transformer中,输入一维序列输出一维序列,代表着全局图片特征;

但其实在CNN的中,经过多层特征提取得到最后的特征图,经过Global Average Pooling全局池化最后也是一个一维向量,代表着全局的图片的特征;

最后实验效果:

  • 绿色是全局平均池化;
  • 蓝线是class token;
  • 黄线是用class token的相同学习率的平均池化;(黄线是告诉我们得好好调参)

结论:全局平均池化方法和class token 效果都差不多;作者选择使用NLP 中的class token是想表明传统的Transformer也能做视觉任务,而不是因为使用了cv的一些小技巧。 

 5.2 Position Embedding

有三种位置编码方式:
1. 一维坐标表示(1-2-3-4-...-9)
2. 二维的坐标表示(11,12,13,21,22,23,...)
3. 相对位置编码:既可以用绝对距离表示又可以用相对距离表示

实验结果:

不同的位置表示的结果没有区别。

但其实这里是做的分类任务,对目标位置没有要求,在后面研究目标检测等任务时,大多使用的是2D位置编码。

 六、代码实现

6.1 patch embedding

在 Vision Transformer 中,输入是一张图片,需要将其转化为 一维嵌入向量序列,类似于自然语言处理任务中处理文本的 token 序列。ViT 的做法是:

  • 将输入图像划分成固定大小的图像块(patch)。
  • 将每个 patch 展平(flatten),然后通过一个线性变换(或者卷积操作)投射到固定的嵌入维度,形成每个 patch 对应的嵌入。
  • 最后,将嵌入向量序列输入到 Transformer 编码器中。

  • 输入图片224*224
  • 每一个patch大小16*16
  • 所以一共有14*14  196个patch   ( 224/16=14)

 通过卷积实现线性嵌入 并 展平

  • self.proj 是一个 2D 卷积层,作用是将输入图像投影到嵌入空间中。

这里使用了大小为 16×16 的卷积核,步长也为 16,相当于对每个 patch 进行卷积操作,最终将每个 patch 转换为一个固定长度的特征向量。

  • 768为超参数。图片原本是3通道,一个 16×16 × 3 的patch 会被展平成一个长度为 768 的向量。输出为(Batch_size, 768, 14, 14)。

通过展平(flatten)和转置操作,最终将结果变为 (B, 196, 768),其中 196是 patch 数量,768是嵌入维度。

 归一化:

默认是none,使用nn.Identity()即不进行归一化。

 6.2 Class Embedding + Position Embedding

Patch + class token

  • 先生成一个可学习的参数矩阵[1,1,768]表示class token,然后在第0维扩展成[batch_size,1,768]

  • 然后在第一维将class token 和 6.1生成的patch embedding[batch_size,196,768] Concat 拼接,成为[batch_size, 197, 768];

 Patch + Position Embedding

  • 位置编码是一个可学习的参数矩阵,形状为[1,197,768]

  • 将位置编码 和 含class token的patch 相加,这里是[1,197,768] + [batch_size,197,768],过程会有触发广播机制,位置编码会自动广播为[batch_szie,197,768]再和patch逐元素相加。
  • 最后会根据超参数drop_ratio随机dropout,结果为[batch_szie,197,768]

 6.3 Transformer Encoder

Transformer Encoder整个操作是打包在blocks中。

blocks里面是一个for循环,depth=3即表示encoder重复执行了三次。

Block的forward函数只有两部分,第一行表示图中下面框选部分;第二行表示上面框选部分。

Encoder中的Multi-Head Attention

Encoder中的MLP

6.4 Classifier

分类头是一个全连接层,输入维度是768,输出维度是num_classes

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小小老大MUTA️

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

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

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

打赏作者

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

抵扣说明:

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

余额充值