为什么ViT需要Patch Embedding?从卷积到Transformer的视觉特征提取演变

为什么ViT需要Patch Embedding?从卷积到Transformer的视觉特征提取演变

如果你在2020年之前问任何一位计算机视觉研究者,处理图像最核心的架构是什么,答案几乎毫无悬念会是卷积神经网络。从AlexNet到ResNet,卷积层通过其固有的局部连接权重共享特性,成为了理解图像世界的标准语言。然而,当Transformer架构在自然语言处理领域掀起革命后,一个大胆的问题被提了出来:我们能否用同样的方式“阅读”图像?Vision Transformer的诞生给出了肯定的答案,而这场变革的起点,正是Patch Embedding这个看似简单的操作。

Patch Embedding远不止是将图像切成小块然后线性映射。它是连接像素世界与序列化理解之间的桥梁,是让Transformer这种为序列设计的架构能够“看见”图像的关键设计。理解它,不仅是为了看懂ViT的代码,更是为了洞察计算机视觉模型设计思想的一次根本性转向——从基于局部归纳偏好的卷积,转向基于全局关系建模的注意力机制。这篇文章将带你穿越这段思想演变的历史,剖析Patch Embedding背后的设计动机,对比它与传统卷积特征提取的异同,并探讨这一设计如何重塑了我们处理视觉数据的方式。

1. 卷积的黄金时代:局部感知与层次化特征提取

在Transformer进入视觉领域之前,卷积神经网络统治了近十年。要理解Patch Embedding的必要性,我们必须先回到卷积的设计哲学中。

卷积操作的核心思想基于两个关键的归纳偏好:局部性和平移等变性。局部性意味着每个神经元只感受输入图像的一小片区域(感受野),这模拟了生物视觉系统的工作原理。平移等变性则保证了一个特征检测器(比如边缘检测器)在图像的不同位置都能以相同的方式工作。这些偏好并非凭空而来,它们极大地减少了模型的参数数量,让网络能够从有限的数据中高效学习。

一个典型的CNN特征提取流程是这样的:输入图像经过多层卷积、池化操作,特征图的空间尺寸逐渐减小,而通道数(即特征的丰富程度)逐渐增加。早期层捕捉边缘、颜色等低级特征,后期层则组合这些低级特征形成更复杂的概念,如物体部件乃至整个物体。

# 一个简化的CNN特征提取过程示意
import torch.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self):
        super().__init__()
        # 第一层卷积:从原始像素中提取边缘等基础特征
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1)
        # 池化层:降低空间分辨率,增加感受野
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        # 更深层的卷积:组合基础特征形成更复杂的模式
        self.conv2 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        
    def forward(self, x):
        # 输入x形状: [batch, 3, 224, 224]
        x = self.pool1(torch.relu(self.conv1(x)))  # -> [batch, 64, 112, 112]
        x = self.pool2(torch.relu(self.conv2(x)))  # -> [batch, 128, 56, 56]
        return x

这种层次化、局部化的处理方式取得了巨大成功,但也存在一些固有的限制。卷积核的大小限制了感受野的范围,要获取全局信息必须依赖深层网络的堆叠。更重要的是,卷积的权重在图像的不同位置是共享的,这虽然带来了平移等变性,但也意味着网络对图像内容的空间结构假设较强——它默认图像的不同区域应该用相同的方式处理。

注意:卷积的这些特性在小到中等规模数据集上表现优异,因为它们提供了强烈的先验,减少了过拟合的风险。但在数据量爆炸式增长的今天,这些先验是否反而成为了限制模型表达能力的瓶颈?这是ViT设计者们思考的起点。

2. Transformer的序列化世界观:从文本到图像的挑战

当我们将目光转向Transformer时,会发现它处理信息的方式与CNN截然不同。Transformer最初为序列数据(如句子)设计,其核心是自注意力机制,允许序列中的每个元素直接与所有其他元素交互,无论它们之间的距离有多远。

在自然语言处理中,输入通常已经是离散的token序列(单词或子词)。但对于图像,我们面对的是连续的、高维的像素网格。直接将每个像素视为一个token会带来灾难性的计算复杂度——对于一张224×224的图像,序列长度将达到50176,自注意力的计算成本与序列长度的平方成正比,这完全不可行。

这就是Vision Transformer面临的根本挑战:如何将二维的、连续的图像数据转化为适合Transformer处理的序列形式,同时保持计算可行性?

早期的尝试大致分为两类:

  1. 在CNN中引入注意力模块作为补充(如SENet、CBAM)
  2. 使用局部注意力或稀疏注意力来近似全局交互

但这些方法都没有完全摆脱CNN的骨架。直到ViT论文提出,研究者们才意识到,也许我们可以采取更激进的方式:完全抛弃卷积,但首先需要对图像进行一种“序列化预处理”。这个预处理就是Patch Embedding。

下表对比了CNN、早期混合方法以及ViT在处理图像时的核心差异:

特性 传统CNN CNN+注意力混合模型 Vision Transformer (ViT)
核心操作 卷积、池化 卷积+注意力 自注意力
感受野 局部,随深度增大 局部+受限全局 全局(从第一层开始)
归纳偏好 强(局部性、平移等变) 中等 弱(最小化先验)
输入形式 原始像素网格 原始像素网格 图像块序列
计算复杂度 O(H×W×C×K²) O(H×W×C×K²) + O(N²×D) O(N²×D)
数据需求 相对较少 中等 大量

注:H,W为图像高宽,C为通道数,K为卷积核尺寸,N为patch数量,D为嵌入维度

3. Patch Embedding的设计哲学:平衡信息保留与计算效率

Patch Embedding的精妙之处在于,它在信息保留和计算效率之间找到了一个优雅的平衡点。让我们深入分析这个设计的每个方面。

3.1 图像分块:从像素网格到视觉“单词”

将图像分割成固定大小的非重叠块,这看似简单的操作背后有深刻的考量。每个patch(例如16×16像素)可以看作是一个“视觉单词”,就像NLP中的token一样。这个大小的选择不是随意的:

  • 16×16像素:足够包含有意义的局部结构(如眼睛的一部分、车轮的一段),但又不会太大以至于失去局部性
  • 非重叠分割:确保每个像素只属于一个patch,避免冗余计算
  • 固定大小:简化了后续的线性投影操作,所有patch被映射到相同维度的向量空间

对于一张224×224的图像,使用16×16的patch会得到196个视觉单词。与50176个像素相比,序列长度减少了256倍,这使得全局自注意力变得可行。

# Patch Embedding的直观理解:将图像视为视觉单词的集合
import torch
import torch.nn as nn

def visualize_patching(image_tensor, patch_size=16):
    """
    展示图像如何被分割成patch
    image_tensor: [1, 3, 224, 224]
    """
    B, C, H, W = image_tensor.shape
    # 计算patch数量
    num_patches_h = H // patch_size  # 14
    num_patches_w = W // patch_size  # 14
    num_patches = num_patches_h * num_patches_w  # 196
    
    # 将图像分割成patch网格
    patches = image_tensor.unfold(2, patch_size, patch_size).unfold(3, patch_size, patch_size)
    # patches形状: [1, 3, 14, 14, 16, 16]
    
    # 重新排列维度,将每个patch展平
    patches = patches.permute(0, 2, 3, 1, 4, 5).contiguous()
    patches = patches.view(B, num_patches, C * patch_size * patch_size)
    # 现在patches形状: [1, 196, 768],每个patch是768维向量
    
    return patche
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值