Kornia VisionTransformer 实战指南:预训练 ViT 编码器加载、Token 推理与分类头扩展

发布时间:2026/10/10 11:49:53
Kornia VisionTransformer 实战指南:预训练 ViT 编码器加载、Token 推理与分类头扩展
计算机视觉深度学习人工智能图像处理【免费下载链接】kornia 空间人工智能的几何计算机视觉库项目地址https://gitcode.com/kornia/kornia点击查看免费下载本指南围绕 Kornia 在 kornia/models/vit.py 中提供的VisionTransformer纯编码器实现展开讲解如何把一张图片切分为 patch、编码为 token 序列如何一键加载 AugReg ImageNet-21k 预训练权重vit_ti/16、vit_s/16、vit_s/32、vit_b/16、vit_b/32、vit_l/16以及在编码器之上构建分类头、多任务头或密集预测头。读完本文你将掌握 Kornia 版 ViT 的完整调用链、各配置参数与默认值、源码级结构原理并了解其测试约束与输入输出约定。一、模型定位无分类头的纯 ViT 编码器Kornia 的VisionTransformer是一个“朴素”的 ViT 编码器plain encoder其处理流程在 vision transformer 编码器实现 中清晰可见输入图片(B, C, H, W)被切割为patch_size × patch_size的方形 patch每个 patch 经卷积嵌入后变成一个 token在序列最前面拼接一个 class token分类 token一叠 transformer encoder block 对这些 token 做全局自注意力混合最终输出每个 token 的嵌入向量形状为(B, 1 N, embed_dim)其中 class token 排在第一位。需要特别强调的是该模型没有分类头。它只输出 token 嵌入属于特征提取器backbone定位分类、分割、检测等下游任务头需要由使用者自行叠加。这也是它能作为通用视觉骨干、被 SAM、MobileViT 等 Kornia 其他模型模块复用见 README 模型清单的原因。输入输出形状约定来自文档与 构造函数 docstring输入(B, 3, 224, 224)float 且取值在[0, 1]输出(1, 197, 768)—— 197 1 个 class token 14 × 14 196个 patch token224 / 16 14默认embed_dim 768base 规模。二、快速上手加载预训练权重并推理原始文档给出了最小可运行的推理示例下面结合 Kornia 的图像读写与几何变换模块完整展开import torch from kornia.io import load_image from kornia.geometry import resize from kornia.models.vit import VisionTransformer # 读取图片并缩放到 224x224(1, 3, 224, 224)float 且取值在 [0, 1] image resize(load_image(panda.jpg)[None], (224, 224)) # 加载 vit_b/16 的 AugReg ImageNet-21k 预训练权重并切换到推理模式 vit VisionTransformer.from_config(vit_b/16, pretrainedTrue).eval() with torch.no_grad(): tokens vit(image) # (1, 197, 768)class token 14×14 patch tokens # 拆分 class token 与 patch tokens cls, patches tokens[:, 0], tokens[:, 1:] # (1, 768) 与 (1, 196, 768)要点说明load_image来自 kornia/io/io.py返回[0, 1]的 float 张量[None]用于补出 batch 维度resize来自 kornia/geometry/transform这里统一缩放到模型的默认image_size 224.eval()关闭 Dropout 等训练期行为配合torch.no_grad()避免梯度图占用显存输出张量第一维是 batch第二维是 token 序列第 0 个是 class token第三维是嵌入维度该维度等于配置中的embed_dim。预训练变体与默认结构参数from_config的变体命名格式为vit_{size}/{patch_size}例如vit_b/16表示 ViT-Base、patch 尺寸 16×16。当前支持预训练权重的变体以及各自的结构参数来源from_config 配置表 与 可用权重列表变体embed_dimdepth层数num_heads注意力头数patch_size输出 token 形状224 输入vit_ti/1619212316(B, 197, 192)vit_s/1638412616(B, 197, 384)vit_s/3238412632(B, 50, 384)vit_b/16768121216(B, 197, 768)vit_b/32768121232(B, 50, 768)vit_l/161024241616(B, 197, 1024)注意源码中还定义了vit_hembed_dim1280、depth32、num_heads16的配置但不在_AVAILABLE_WEIGHTS列表中即没有对应预训练权重只能随机初始化使用。pretrainedTrue时权重由 load_state_dict_from_url 从 HuggingFace 的kornia组织仓库下载URL 由 _get_weight_url 按{model_type}{patch_size}_augreg_i21k_r224规则拼接。三、在预训练编码器上添加分类头ViT 编码器本身不输出类别概率标准做法是读取 class token再接一个线性层完成图像级分类。原文档示例import torch.nn as nn from kornia.models.vit import VisionTransformer class Classifier(nn.Module): def __init__(self, num_classes: int 1000) - None: super().__init__() self.backbone VisionTransformer.from_config(vit_b/16, pretrainedTrue) self.head nn.Linear(768, num_classes) # 768 是 base 模型的 embed_dim def forward(self, x): return self.head(self.backbone(x)[:, 0]) # (B, num_classes)从 class token 出发几点实战提示head 输入维度要与 embed_dim 对齐不同变体 embed_dim 不同ti 为 192、s 为 384、l 为 1024换成其他变体时要同步修改nn.Linear的第一个维度class token 索引是 0backbone(x)[:, 0]取出每个样本的 class token(B, embed_dim)这正是编码器把 class token 放在序列首位的设计用意微调策略预训练权重加载后既可以直接冻结 backbone 只训练 head也可以全量微调两种方式下from_config(..., pretrainedTrue)都直接可用。扩展为多任务头与密集预测头同一个模式可以扩展到多任务与密集任务图像级输出继续读 class token检测、分割等需要空间信息的任务则把 196 个 patch token 重新 reshape 回14 × 14的特征图再接分割/检测 neck。例如B tokens.shape[0] patch_tokens tokens[:, 1:] # (B, 196, 768) feat_map patch_tokens.permute(0, 2, 1).reshape(B, 768, 14, 14) # (B, 768, 14, 14)reshape 回H/16 × W/16空间网格的前提是使用 patch_size16 且输入为 224 的方图patch_size32 的变体vit_s/32、vit_b/32对应的是7 × 7网格224/32 7。四、从零构建任意规模的模型如果不想用预训练权重VisionTransformer的构造函数直接暴露了完整的布局参数默认值见 构造函数签名vit VisionTransformer( image_size224, # 输入图片边长forward 时会校验 patch_size16, # 每个 patch 的边长同时作为嵌入卷积的 kernel/stride in_channels3, # 输入通道数 embed_dim768, # token 嵌入维度 depth12, # transformer encoder 层数 num_heads12, # 注意力头数 dropout_rate0.0, # MLP/投影后的 dropout 比例 dropout_attn0.0, # 注意力权重的 dropout 比例 backboneNone, # 自定义 patch 嵌入骨干默认是 stridepatch_size 的 Conv2d )参数背后的实现细节patch 嵌入默认用nn.Conv2d(in_channels, out_channels, kernel_sizepatch_size, stridepatch_size)一次完成切块与线性投影见 PatchEmbedding 实现class token 与位置编码cls_token和positions都是可学习参数nn.Parameter位置编码长度是feat_size 1patch 数 1 个 class token并直接以加法方式注入自定义 backbone传入任意nn.Module可替换默认卷积例如换成 CNN 特征提取器此时输出通道与特征网格尺寸通过 _compute_feats_dims 对全零输入做一次前向自动推断位置编码长度会随之适配——测试用例 test_backbone 就用一个输出(1, 128, 14, 14)的 mock backbone 验证了这一点维度约束embed_dim必须能被num_heads整除否则构造时直接抛出ValueError见 MultiHeadAttention 校验forward还会校验输入张量类型与(B, in_channels, image_size, image_size)形状见 forward 校验。五、源码级原理编码器的内部结构Kornia 的 ViT 编码器拆分为四个可独立理解的组件全部位于 kornia/models/vit.py1. TransformerEncoderBlock标准 Pre-LN 块每个 block 由两个ResidualAdd残差子模块串联见 TransformerEncoderBlock第一个残差支路LayerNorm → MultiHeadAttention → Dropout第二个残差支路LayerNorm → FeedForward → Dropout。采用 Pre-LayerNorm 顺序先归一化再进入子层LayerNorm 的 eps 取1e-6。ResidualAdd实现以函数式传入子模块并在内部完成x fn(x)的加和。2. FeedForwardGELU 激活的 MLPFeedForward 是Linear → GELU → Dropout → Linear → Dropout的顺序容器隐藏层宽度固定为embed_dim * 4即 MLP 放大 4 倍并且与 timm 实现一致在第二个 Linear 之后额外加了一次 Dropout。3. MultiHeadAttention融合 QKV 的自注意力MultiHeadAttention 的实现要点Q、K、V 通过单个nn.Linear(emb_size, emb_size * 3)融合计算再 reshape 拆分到num_heads个头缩放因子为head_size ** -0.5head_size emb_size // num_heads注意力得分用einsum(bhqd, bhkd - bhqk)计算并做 softmax随后是注意力 dropout 与输出投影。4. TransformerEncoder 与中间层特征TransformerEncoder 用nn.Sequential串起depth个 block同时维护一个results列表记录每一层 block 的输出。通过VisionTransformer.encoder_results属性定义可以拿到每一层的 token 嵌入形状统一为(B, 1 N, D)。该能力常用于特征金字塔、层级特征融合或可视化中间表示——测试用例 test_smoke 明确断言了encoder_results的长度等于depth且每个元素形状正确。六、测试验证与使用约束仓库中的 tests/models/test_vision_transformer.py 给出了可靠的行为契约测试验证点test_smoke不同 batch/头数/维度/图像尺寸组合下输出形状恒为(B, T, D)其中T (image_size/patch_size)² 1且encoder_results长度为 depth、形状与输出一致test_exceptionembed_dim不能被num_heads整除时抛出ValueErrortest_backbone自定义 backbone 输出(1, 128, 14, 14)时最终输出为(1, 197, 128)encoder_results长度正确由此可总结出三条使用红线尺寸匹配输入H、W必须等于image_size默认 224且通道数等于in_channels默认 3整除约束embed_dim % num_heads 0必须成立token 数推导224/1614得到 14×14 patch因此任何依赖空间网格的下游模块都要按image_size / patch_size计算实际分辨率。七、论文背景该实现对应的原始论文为《An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale》Dosovitskiy 等ICLR 2021Apache-2.0。论文的核心结论是将图像切分为 patch 序列后直接用纯 Transformer 建模即可在 ImageNet、CIFAR-100、VTAB 等基准上取得与卷积网络相当甚至更好的结果且预训练数据规模越大优势越明显。Kornia 提供的预训练权重即采用 AugReg 训练策略、在 ImageNet-21k 上预训练得到对应原文档中针对分类、细粒度分类、文档图像分类等任务的用法。八、延伸阅读模型文档docs/source/models/vit.rst核心实现kornia/models/vit.py单元测试tests/models/test_vision_transformer.py图像加载与缩放kornia/io/io.py、kornia/geometry/transform权重下载基础工具kornia/core/download.py赞分享计算机视觉深度学习人工智能图像处理【免费下载链接】kornia 空间人工智能的几何计算机视觉库项目地址https://gitcode.com/kornia/kornia点击查看免费下载相关推荐Kornia Vision TransformerViT实战指南从加载预训练编码器到定制分类头Kornia Vision TransformerViT实战指南从加载预训练编码器到定制分类头 导读 Kornia 在 kornia.models.vit计算机视觉人工智能深度学习图像处理Vorssaint免费菜单栏十合一工具Vorssaint免费菜单栏十合一工具 Mac 上想单独调 App 音量、看温度、找回复制过的内容往往要装好几个付费小工具。Vorssaint 是免费的 m桌面应用TorchVision VisionTransformer 模型全解析五款 ViT 构建器、预训练权重与源码级实现指南TorchVision VisionTransformer 模型全解析五款 ViT 构建器、预训练权重与源码级实现指南 本文围绕 torchvision 中计算机视觉深度学习图像处理数据集上一篇终极AMD Ryzen处理器调试指南5步掌握硬件调优下一篇Terminals Are Sexy远程终端全解析Mosh、SSH客户端与终端聊天工具实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考