深度学习进阶(五)Vision Transformer有哪些应用?

摘要:在上一篇,我们已经完整介绍了原始 Transformer 的结构和整体传播逻辑。 从结果上看,Transformer 在 NLP 领域带来了范式级的突破:通过自注意力机制实现了对序列的全局建模能力。 然而,实际上,原始 Transforme
在上一篇,我们已经完整介绍了原始 Transformer 的结构和整体传播逻辑。 从结果上看,Transformer 在 NLP 领域带来了范式级的突破:通过自注意力机制实现了对序列的全局建模能力。 然而,实际上,原始 Transformer 依然只是一个面向序列数据的模型。 自然而然地,这种全新的建模方式引起了相关的思潮,首当其冲的便是: 既然自注意力机制本质上是一种全局依赖建模方法,它是否真的只适用于“序列”这一种数据形式? 换句话说,如果我们不再局限于文本,而是将目光投向更广泛的数据类型,例如图像这种天然具有二维结构的信息,Transformer 是否依然能够发挥作用? 于是 Vision Transformer 应运而生。它尝试回答的问题便是: 如果抛开卷积结构,仅依赖注意力机制,能否完成视觉任务的建模? 我们以此为出发点,展开 Vision Transformer,即 ViT 的逻辑。 1. ViT 的核心思想 ViT 提出于 2020 年的论文:An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale,它首次证明了纯 Transformer(无卷积)可以在视觉任务上达到 SOTA 。 你会发现 ViT 的提出距离原始 Transformer 的发表已经过去三年了,但这并不意味着Transformer 的发展进入了停滞期。 实际上,这三年正是 Transformer 爆炸式扩展的阶段,只不过主要发生在 NLP 内部,在语言任务中完成充分验证之后,Transformer 逐渐被视为一种通用的序列建模框架。在此基础上,向视觉等其他模态的扩展,才成为顺理成章的下一步。 再回到 ViT 自身,其核心思路不难理解,可以一句话概括: 把图像切成“块(Patch)”,然后当作 token 序列送入 Transformer 的 encoder 。 2.ViT 的数据处理 要说明的是:对标 CV 任务,ViT 只使用了 Transformer 的 encoder 逻辑,因此,其重点其实是在对数据的处理上。 2.1 Patch 划分 首先,我们要把图像分割成一个个等大不重叠的块,即 Patch : 原始 ViT 设计输入图像大小为 \(224 \times 224 \times 3\),而 patch 大小是 \(16 \times 16\) 。 于是,最终得到 patch 数量即为: \[N = \frac{224 \times 224}{16 \times 16} = 14 \times 14 = 196 \] 很好理解,再简单推广一下,对于输入图像: \[\mathbf{X} \in \mathbb{R}^{H \times W \times C} \] 如果设计每个 patch 大小为 \(P \times P\),那么得到的 patch 数量就是: \[N = \frac{HW}{P^2} \] 2.2 展平 现在,我们已经把一张二维图像拆成了 \(N\) 个小块。但仍然存在问题:Transformer 并不能直接处理二维结构的数据,它只能接收“向量序列”。 因此,接下来要做的事情就很明确了:把每一个 Patch 转换为一个向量。 而转换方法就是最基本的展平: 即对于每一个 patch,其原始形状为: \[P \times P \times C \] 我们将其按通道展开为一个一维向量: \[\mathbf{x}_p \in \mathbb{R}^{P^2 \cdot C} \] 以 ViT 中的配置 \(P = 16\)、\(C = 3\) 为例,则: \[\mathbf{x}_p \in \mathbb{R}^{16 \times 16 \times 3 = 768} \] 现在,每一个 patch 已经变成了一个固定长度的向量表示。 但是,我们在很早之前的图像处理基础中就提到过:展平会带来空间信息的损失。 在这一步处理后,数据就无法再提供类似“鼻子要在嘴巴上面”的空间信息了,这也是我们在卷积内容中提到的用全连接网络处理图像的弊端之一。 显然,ViT 会采用别的措施来弥补这个问题,我们继续: 2.3 线性映射 完成展开后,我们已经得到了每个 patch 的序列表示,但这里还有一个细节问题:展平后的向量维度是 \(P^2C\),而 Transformer 的输入维度通常是一个统一的隐藏维度 \(D\)。 因此,我们将每个 patch 展平后的向量通过一个线性变换映射到目标维度: \[\mathbf{z}^i = \mathbf{x}^i \mathbf{W} + \mathbf{b} \] 现在,一个 patch 就变成了一个 token。 不过显然,一个明显的问题就是:如果 \(P^2C=D\) ,那这一步是不是就没有必要了? 答案当然是否定的,在这里,我们不仅要看维度关系,还要想到线性层本身在这里的语义作用: 如果我们不对原始二维信息“序列化”,那么在一个常见的卷积网络中,我们会使用卷积层来进行特征提取,其运算逻辑本身仍是可学习参数下的加权求和。 而现在,我们把 patch 转换为 token ,输入线性层本身仍然是特征提取的过程,类比来说:patch 就相当于感受野,而权重就是卷积核。 而我们最终得到的向量,其实就相当于完成了对 patch 的词嵌入过程。 2.4 [CLS] token 在正式进入模型前,我们对输入的处理仍没有结束,我们把一幅图像转变为一组 token ,那么一个问题是: 在分类任务中,我们应该使用哪一个 token 来代表整张图像? 如果发散来想,可能的做法包括对所有 token 做平均或拼接所有 token 后再融合等。 但 ViT 的选择是: 引入一个专门用于“汇聚全局信息”的 token,即 [CLS] token。 在更广的应用任务中,也叫全局 token 。 展开来说:对于原本划分为 \(N\) 个 token 的图像: \[[\mathbf{z}^1, \mathbf{z}^2, \dots, \mathbf{z}^N] \] 我们在最前面拼接一个 [CLS] token: \[[\mathbf{x}_{cls}, \mathbf{z}^1, \mathbf{z}^2, \dots, \mathbf{z}^N] \] 这里的 \(\mathbf{x}_{cls}\) 是一个随机初始化的可学习参数,与其他 token 具有完全相同的维度。 要强调的是,[CLS] token 是一个可学习参数,所以这里的“汇聚全局信息”是我们为其赋予的语义并在之后的逻辑里实现的。 我们先继续传播过程,在下面就会展开其具体逻辑: 2.5 位置编码 PE 现在,我们还有一个遗留问题: 由patch 转换得到 token 失去了彼此之间的“位置信息”。 不像 CNN ,现在模型并不知道哪个 patch 在左上角、哪个 patch 在右下角、哪些 patch 是相邻的。 这显然是不合理的, 因为在视觉任务中位置本身就是一种极其重要的信息。 因此,ViT 延续了 NLP 中的机制:位置编码。 \[\mathbf{X}_{input} = \mathbf{E}_{embedding} + \mathbf{E}_{pos} \] 但和原始 Transformer 的正余弦固定编码不同,ViT 使用的是可学习位置编码: 展开来说,在 ViT 中,位置编码被建模为一组可学习的参数矩阵,模型为每一个 token 位置都分配一个对应的向量表示,这些向量在训练过程中与模型参数一起被优化。 假设输入序列包含 \(N+1\) 个 token(其中包含 1 个 [CLS] token 和 \(N\) 个 patch token),则位置编码可以表示为: \[\mathbf{E}_{pos} \in \mathbb{R}^{(N+1) \times D} \] 其中,每一行都对应一个位置的可学习向量,以此完成 PE 的注入。 到这里,我们就完成了数据的所有处理,我们留下了两个问题没有详细展开: ViT 究竟如何弥补空间信息的损失? [CLS] token 如何“汇聚全局信息”? 二者在 ViT 的 Transformer 逻辑便可以被解答。 3. ViT 的 Transformer 逻辑 就像最开始说的,ViT 只使用了 Transformer 的 encoder ,我们在前面的内容里已经详细展开过了,这里我们摆一下原论文中的完整传播图: 网络结构本身十分清晰,我们从刚刚的问题出发,展开这部分里要理解的内容: 3.1 ViT 究竟如何弥补空间信息的损失? 对于这个问题,可能在刚刚的位置编码可能会有所启发: 既然 PE 是可学习的,那难道空间信息是训练出来,体现在 PE 中的吗? 如果只停留在这里,就片面,甚至错误了。 实际上,真正完成“空间关系建模”的,是自注意力机制。 展开来说:首先,我们已经不只一次提到过自主力机制的全局建模能力了,也就是说,当patch 转换成的 token 序列输入自注意力中后, 每一个 patch token,都可以直接和所有其他 patch 建立联系。 通过注意力我们可以学习得到不同 patch 间的相关性,但是仅仅知道这个不够的,如果向量里没有位置信息,我们就无法学习到位置上的关联,因此 PE 仍然必不可少。 二者结合,虽然模型不知道“左上角”这个概念,但它可以学到: 哪些 patch 经常一起出现(例如:眼睛和鼻子)。 哪些 patch 存在相对结构(例如:天空通常在地面上方)。 到这里,关键点就出现了:ViT 不同于卷积让空间结构作为已知信息加入训练,空间信息其实是 ViT 的统计学习结果。 其实从直觉角度,对这种逻辑先想到的应该是它的局限:对数据量的高要求。 但它的优势在于全局建模能力:CNN 想看到全局,必须叠很多层或者用大卷积核,但 ViT 一步到位:第一层注意力,就已经是全局感受野。 最终,对这个问题的答案是: ViT 并没有“恢复”空间结构,而是用“位置编码 + 自注意力”在数据中重新学习空间结构。 3.2 [CLS] token 如何“汇聚全局信息”? 接下来我们看第二个问题: 为什么一个随机初始化的向量,最后可以代表整张图像? 其核心仍然是自注意力机制:首先在 Transformer 中,每一层的注意力都会做一件事情: 每个 token 都会从“所有 token”那里收集信息(加权求和)。 因此,[CLS] token 在每一层都会执行: \[\mathbf{x}_{cls}^{(l+1)} = \sum_{j} \alpha_{cls,j} \mathbf{z}_j^{(l)} \] 到这里,我们知道了 [CLS] token 会逐层提炼信息,但问题依然存在: 不仅 [CLS] token 在提炼,其他 token 也都在提炼,为什么只有你能代表全局? 没错,从计算上讲:所有 token 都在做全局信息融合,也就是说每个 patch token 都能“看到全局”, 最终其实都包含了一定程度的全局信息。 实际上,这是因为在设计里只有 CLS 被当作“最终输出”来使用。 在分类任务中,ViT 的最终输出是: \[\text{logits} = \text{MLP}(\mathbf{x}_{cls}^{(L)}) \] 也就是说:只有 [CLS] token 会被送入输出层完成分类,并直接参与损失函数计算。 因此,从反向传播来说:只有 [CLS] token 会被“强制要求”去学习对分类最有用的全局信息。 这才是它能汇聚全局语义的原因,是我们手动设计的监督驱动,让其在反向传播中不断学习全局语义。 同样给个较官方的答案: [CLS] token 并不是天然具备“全局语义”的特殊结构,而是由于它是唯一直接参与监督训练的 token,因此被优化为一个能够表达整张图像语义的表示。 4.总结 ViT 的核心作用可以概括为:将图像转化为 token 序列,并在统一的 Transformer 框架下完成全局建模。 相比传统 CNN,它最关键的突破在于:不再依赖局部感受野与平移不变性等空间先验,而是通过自注意力机制直接在全局范围内建立 patch 之间的联系。这使得模型从一开始就具备全局感受野,无需通过多层堆叠逐步扩展,从而在表达能力上具备更高的灵活性。 同时,ViT 并没有显式“恢复”图像的空间结构,而是通过位置编码(PE)与自注意力机制的结合,在数据中学习空间关系。 总体来看,ViT 的核心意义在于:它将 Transformer 从“序列建模框架”推广为“通用感知建模框架”。 这种从“结构先验驱动”到“数据驱动建模”的转变,不仅重新定义了视觉任务的建模方式,也为后续多模态模型的发展奠定了统一的基础。 但是,ViT 仍有其局限,那就是需要超大规模的训练数据,自然,也就出现了针对这一问题的改进,我们在下一篇再展开介绍。