在Python中如何使用PyTorch实现视觉变换器Vision Transformer?

老磊姑娘_6611

老磊姑娘_6611

2026-06-17

464人浏览

原创

pytorch官方torchvision直到2.3版仍无内置vision transformer类,需自行搭建或使用timm;timm支持500+视觉模型、灵活配置与预训练权重加载,且正确处理cls token、位置编码、droppath及finetune流程。

在python中如何使用pytorch实现视觉变换器vision transformer?

PyTorch官方不提供vision_transformer类,得自己搭或用timm

PyTorch核心库(torch 和 torchvision)直到 2.3 版本仍**没有内置 Vision Transformer 模型类**。你查 torchvision.models 会发现只有 ResNet、ViT 等名字——但注意:torchvision.models.vit_b_16 这类是 2022 年后才加入的轻量封装,底层仍是手动拼的模块,且只覆盖有限预训练权重(如 ImageNet-1k),不支持自定义 patch size 或 hybrid backbone。

更常见也更灵活的做法是用 timm(PyPI 包名 timm):
– 它统一管理了 ViT、DeiT、MAE、FlexiViT 等 500+ 视觉模型
– 支持一行加载预训练权重、自动适配输入尺寸、导出 ONNX 等
– 不依赖 torchvision 的硬编码结构,参数可调性高

安装与最简加载示例:

pip install timm
# 加载一个 ViT-Base/16,自动下载预训练权重
import timm
model = timm.create_model('vit_base_patch16_224', pretrained=True)

patch embedding层不能直接用nn.Conv2d,必须对齐cls token和pos embedding

ViT 的核心是把图像切成 patch 后线性投影。新手常误用 nn.Conv2d(in_channels=3, out_channels=768, kernel_size=16, stride=16) ——这看似等价,但会漏掉两个关键点:
– 缺少 [CLS] token:ViT 输入序列开头必须加一个可学习向量,用于最终分类
– 位置编码(pos embedding)维度必须严格匹配总 token 数(patch 数 + 1)

正确做法(以 timm 为例,其 vit_base_patch16_224 内部逻辑):

  • 输入 224×224×3 → 切成 (224//16)² = 196 个 patch → 加上 [CLS] 后共 197 个 token
  • pos embedding 是一个 nn.Parameter,shape 为 (197, 768),不可动态缩放
  • 若你改输入为 384×384,patch 数变成 (384//16)² = 576,此时原 pos embedding 尺寸不匹配,会报错 size mismatch for pos_embed

解决方法:
– 用 timm 的 interpolate_pos_encoding=True(仅部分模型支持)
– 或手动双线性插值重采样 pos embedding:F.interpolate(pos_embed.unsqueeze(0), size=(new_n_tokens, dim), mode='bilinear')

forward时别忘了处理attention mask和training模式下的dropout

ViT 的 MultiheadAttention 层默认不接受 attn_mask(不像 NLP 中常用),但如果你做下游任务(如目标检测中的特征图 ViT 编码),可能需要掩码无效区域。此时不能直接传 attn_mask 给 nn.MultiheadAttention,因为 ViT 的 attention 是在 patch token 序列上做的,而标准 PyTorch MultiheadAttention 要求 mask shape 为 (N×num_heads, L, S),容易维数错乱。

python-parallelization
python-parallelization

将顺序 Python 代码转换为并行/并发实现,用于在需要并行化 Python 代码、提升性能时使用。

下载

更实际的问题是训练/推理模式切换:
– ViT 主干中大量使用 DropPath(stochastic depth)和 Dropout
– 若你冻结 backbone 做迁移学习,但没设 model.eval(),DropPath 仍会随机丢弃路径,导致输出不稳定
– timm 中对应模块叫 timm.models.layers.DropPath,它**只在 training=True 时生效**,这点和 nn.Dropout 一致,但容易被忽略

建议写法:

model = timm.create_model('vit_base_patch16_224', pretrained=True)
model.eval()  # 确保 DropPath / Dropout 关闭
with torch.no_grad():
    out = model(img_tensor)  # img_tensor: [1, 3, 224, 224]

finetune时class token输出不是最终logits,要过head再归一化

很多人取 model.forward_features(x)[:, 0](即 cls token)就直接接 nn.Linear 分类,结果准确率远低于预期。问题在于:
– timm 的 ViT 默认 head 是 nn.Sequential(nn.LayerNorm(dim), nn.Linear(dim, num_classes))
– 如果你替换 head,必须保留 LayerNorm;否则 cls token 的分布偏移会让 Linear 层难以收敛
– 更隐蔽的坑:ViT 的预训练 head 权重(如 ImageNet 的 1000 类)和你新任务类别数不同时,model.reset_classifier(num_classes=10) 才会重置 head,而不是简单 model.head = nn.Linear(...)

正确 finetune 流程要点:

  • 用 model.reset_classifier(num_classes=N) 替换 head(自动初始化)
  • 冻结前几层(如 for p in model.blocks[:8].parameters(): p.requires_grad = False)
  • 确保 model.head 的 weight 和 bias 在优化器参数列表中
  • 如果用混合精度训练(amp),确认 LayerNorm 的 eps 不太小(1e-6 安全,1e-12 可能溢出)

ViT 对 head 初始化和归一化敏感,cls token 不是“拿来就能用”的特征向量,它高度依赖后续 norm 和 linear 的协同校准。

Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1731

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4384

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1709

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

25637

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3127

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3147

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1183

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2443

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程