视觉Transformer
#2026/01/01 #ai
在前面章节中,我们学会了用Transformer处理文本。现在要问一个问题:能不能用Transformer处理图像?
答案是:能!这就是视觉Transformer(Vision Transformer,ViT)。
目录
- 一、为什么需要视觉Transformer?
- 二、ViT vs 原始Transformer:核心相似性
- 三、核心挑战:图像怎么“分词“?
- 四、ViT的工作流程详解
- 五、ViT的革命性意义
- 六、ViT核心架构图解
- 七、与传统CNN的对比
- 八、实战理解:代码示例
- 九、ViT的三大核心要点
- 十、ViT的应用场景
- 核心要点总结
- 核心启示
一、为什么需要视觉Transformer?
问题背景
我们已经见证了Transformer在语言建模任务中的卓越表现:
- 文本分类
- 聚类
- 搜索生成
- 对话系统
自然的想法:既然 Transformer 在文本领域这么强,能不能用在图像上?
历史里程碑
研究者将Transformer的成功经验迁移到计算机视觉领域,诞生了视觉Transformer(ViT)。
惊人的结果:ViT在图像识别任务中展现出超越传统卷积神经网络(CNN)的性能!
二、ViT vs 原始Transformer:核心相似性
功能对比
如图,两者的核心功能相同:

**图:原始 Transformer 与 ViT 均将非结构化数据转换为数值表示,最终应用于分类等任务
| 维度 | 原始Transformer | 视觉Transformer(ViT) |
|---|---|---|
| 输入 | 非结构化文本 | 非结构化图像 |
| 处理 | 转换为数值表示 | 转换为数值表示 |
| 输出 | 用于分类等任务 | 用于分类等任务 |
形象类比
原始Transformer:
输入:"You have been selected to receive 1.4 million dollars!"
↓ 特征提取
输出:78% 非垃圾信息,22% 垃圾信息
视觉Transformer:
输入:一张猫的图片
↓ 特征提取
输出:98% 猫,2% 狗
关键相似点:都是把非结构化数据(文本/图像)转成数值表示,然后用于分类。
三、核心挑战:图像怎么“分词“?
问题:图像不是文本
# 文本处理很简单
文本:"I love cats"
分词器:["I", "love", "cats"] ← 自然的分割单位
# 图像处理很困难
图像:512×512像素的猫图
分词器:??? ← 没有自然的分割单位
如图所示,文本在进入编码器之前需要分词,但图像并非由“词“构成!

图:文本在被传入一个或多个编码器之前,需要先通过分词器进行分词
解决方案:把图像切成“词“
ViT的核心创新:将图像切割为图像块(patch),把每个图像块当作一个“词元“!
具体而言,ViT 会沿图像的水平方向和垂直方向进行网格化切割
四、ViT的工作流程详解
步骤1:图像分块
如图所示,ViT沿水平和垂直方向将图像切割成网格:

图:图像输入的“分词”处理流程:将完整的图像转换为多个子图像块
原始图像(512×512像素)
↓ 网格化切割
分块图像(比如3×3个小块)
↓ 每个块展平
展平输入(9个"图像词元")
形象理解:
- 就像拼图被拆成小块
- 每个小块就是一个“视觉词元“
- 类比文本的词元,但内容是图像块
步骤2:线性嵌入
问题:图像块无法像文本词元那样直接赋予固定ID
# 文本词元:可以查表
词元"cat" → ID: 1234
# 图像块:每张图都不同,无法查表
图像块[某个像素组合] → ID: ??? ❌ 行不通!
解决方案:对图像块进行线性嵌入操作,转换为数值化的嵌入向量
图像块(原始像素)
↓ 线性投影
嵌入向量(一组数字)
↓
可以输入Transformer编码器
步骤3:输入编码器
如图所示,完整流程:
原始图像
↓
分块处理(比如16×16个块)
↓
展平输入(变成序列)
↓
线性投影(生成嵌入向量)
↓
添加[CLASS]词元(用于分类)
↓
输入Transformer编码器
↓
输出分类结果

图:ViT 核心算法架构。图像经过分块处理和线性投影后,其嵌入向量将以与文本词元相同的方式进入编码器
关键:16×16的秘密
原始论文采用16×16分块,这呼应了论文标题:
"An Image is Worth 16x16 Words"
(一图胜16×16言)
含义:
- 一张图像被切成16×16个块
- 每个块相当于一个“词“
- 总共256个“视觉词元“
五、ViT的革命性意义
1. 模态统一
核心突破:当嵌入向量进入编码器后,视觉与文本的处理路径完全相同!
文本路径:
文本 → 分词 → 嵌入 → Transformer编码器
视觉路径:
图像 → 分块 → 嵌入 → Transformer编码器
↑
完全相同的编码器!
2. 多模态基础
这种架构统一性为多模态模型的构建奠定了重要基础。
典型应用:训练跨模态的联合嵌入模型(后面会详细讲)
六、ViT核心架构图解
完整流程可视化
如图9-5所示:
┌─────────────┐
│ 原始图像 │ (512×512像素的猫)
└──────┬──────┘
↓ 分块
┌─────────────┐
│ 分块图像 │ (16×16个小块)
└──────┬──────┘
↓ 展平
┌─────────────┐
│ 展平输入 │ (256个序列)
└──────┬──────┘
↓ 线性投影
┌─────────────┐
│图像块嵌入向量│
└──────┬──────┘
↓ 添加[CLASS]
┌─────────────┐
│ Transformer │
│ 编码器 │
└──────┬──────┘
↓
┌─────────────┐
│ 分类结果 │ (98%猫,2%狗)
└─────────────┘
七、与传统CNN的对比
CNN vs ViT
| 维度 | 传统CNN | 视觉Transformer |
|---|---|---|
| 基本单元 | 卷积核 | 自注意力 |
| 处理方式 | 局部感受野 | 全局注意力 |
| 并行性 | 一般 | 强(与文本Transformer相同) |
| 性能 | 优秀 | 更优秀 |
| 训练数据 | 较少数据即可 | 需要大量数据 |
八、实战理解:代码示例
虽然原文没有详细代码,但我们可以想象ViT的使用方式:
from transformers import ViTForImageClassification
import torch
from PIL import Image
# 加载预训练的ViT模型
model = ViTForImageClassification.from_pretrained('google/vit-base-patch16-224')
# 加载图像
image = Image.open('cat.jpg')
# 预处理(模型会自动分块、嵌入)
inputs = processor(images=image, return_tensors="pt")
# 前向传播
outputs = model(**inputs)
# 获取预测
predictions = outputs.logits.softmax(dim=-1)
print(f"这是猫的概率: {predictions[0][CAT_ID]:%}")
九、ViT的三大核心要点
1. 分块策略
关键问题:如何把图像变成"词元"?
解决方案:切成16×16的图像块
每个块 = 一个视觉词元
2. 线性嵌入
关键问题:图像块无法像文本一样查ID
解决方案:用线性层投影成嵌入向量
输出向量 = Transformer的标准输入
3. 架构复用
关键优势:不需要重新设计架构
直接使用:现有的Transformer编码器
效果提升:性能超越CNN
十、ViT的应用场景
1. 图像分类
输入:一张猫的图片
ViT处理 →
输出:猫(98%),狗(2%)
2. 多模态嵌入
# ViT常被用作扩展语言模型多模态能力的关键模块
图像 → ViT → 视觉嵌入
文本 → BERT → 文本嵌入
↓
联合嵌入空间
3. 视觉问答
问题:"图片里有几只猫?"
图像 → ViT提取特征
文本 → 文本模型理解问题
↓
综合回答:"有两只猫"
核心要点总结
1. ViT的本质
ViT = 把Transformer从文本搬到图像
核心思想:图像也可以"分词"
分词方法:切成图像块
2. 工作流程
原始图像 → 分块 → 线性嵌入 → Transformer编码器 → 分类
(16×16) (向量化) (与文本完全相同)
3. 革命性意义
| 突破 | 说明 |
|---|---|
| 性能突破 | 超越传统CNN |
| 架构统一 | 视觉与文本处理路径相同 |
| 多模态基础 | 为跨模态模型铺平道路 |
核心启示
ViT的革命性在于:
- 证明了Transformer的通用性
- 不只适用于文本
- 也适用于图像
- 甚至可能适用于任何序列数据
- 统一了处理范式
- 文本和图像用同样的架构
- 为多模态AI奠定基础
- 简化了模型设计
- 开启了新的可能
- 图像理解
- 跨模态检索
- 视觉问答
- 图像生成引导
就像给Transformer装上了“眼睛“——既能读文字,又能看图像!
现在你已经理解了ViT的核心原理,下一节(9.2节)我们将学习如何构建多模态嵌入模型——让图像和文本在同一个向量空间中“对话“!