ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DINOv2 多头注意力机制是怎么算的?一篇读透 ViT 注意力代码

DINOv2 多头注意力机制是怎么算的?一篇读透 ViT 注意力代码 DINOv2 多头注意力机制是怎么算的一篇读透 ViT 注意力代码【免费下载链接】dinov2PyTorch code and models for the DINOv2 self-supervised learning method.项目地址: https://gitcode.com/GitHub_Trending/di/dinov2你有没有好奇过同样一张图DINOv2 跑完 ViT 之后只接一层线性层ImageNet 分类就能过 80%关键不在训练技巧而在每个 Transformer 块里反复出现的那份多头注意力。这篇文章直接从代码入手把 DINOv2 ViT 注意力机制的原理与实现一次讲完不需要数学基础。不用多头注意力瓶颈在哪先看三个传统做法的具体短板卷积的长程依赖贵CNN 的 receptive field感受野一层层扩大图像里相隔很远的两个区域比如被遮挡的主体和远处的同类部件要“碰面”得堆很多层中间还会丢信息。单通道注意力只有一套尺度如果只做一次 Q/K/V 投影整张图只能用同一把“相似度尺子”衡量。图里同时存在边缘、纹理、布局好几种结构关系时互相干扰都做得一般。算力被平均掉局部细节和全局布局在不同时刻都很重要像素被一视同仁地处理模型只能花容量去平均噪声。多头注意力就是冲着这三条去的把注意力计算拆成多条“独立车道”每条车道专注一类关系最后再汇总。DINOv2 注意力机制原理一场评审会想象每张图先被切成 14×14 像素的小块patch代码里叫 patch token。每个小块各发一张“座位卡”然后开一场评审会每个 token 先生成三组数QQuery是“我想问的问题”KKey是“我手头内容的目录”VValue是“我手头内容的正文”。白话讲Q 是问题K 是索引号V 是答案本身。任意两个 token 之间算 Q 与 K 的相似度分数越高对方的 V 就越被拉进自己的更新结果里。这一轮就叫“一次注意力”。关键动作来了DINOv2 不派一个人算完而是把 768 维特征空间拆成 12 个注意力头代码里embed_dim768, num_heads12的默认值每个头独占 64 维各算各的最后 12 条车道的结果拼接、再过一个线性投影合并。为什么要拆车道因为每个头有自己独立的投影权重训练后会各自偏向有的头比较会比对颜色有的擅长匹配形状有的盯着空间位置。最终由一次线性投影把 12 个头的“结论”融合成统一表示。所谓“多头”本质是并行不是串行。看一眼代码注意力块是怎么写的 最核心的代码不在注意力函数里而在它被挂进 Transformer 的方式。看 dinov2/layers/block.py 中Block.forward的推理分支# dinov2/layers/block.py —— Block.forward 推理分支 else: x x attn_residual_func(x) # 注意力先 LayerNorm再算注意力最后加回原输入 x x ffn_residual_func(x) # 前馈注意力 MLP 两段组成一个 Transformer 块就两行有效代码三个写法细节值得注意attn_residual_func内部先过norm1LayerNorm再进注意力。先归一化再算注意力分数不容易失控。开头的x 是残差连接注意力输出的不是新特征而是“对原特征的修正量”梯度因此可以一路穿到浅层。每个块 一次注意力 一次 MLP纵向叠depth层DinoVisionTransformer构造函数里默认depth12。也就是说同一批 patch token 会被“评审”很多次多头注意力在每一层都重新算一遍。而真正的“拆头”逻辑在 dinov2/layers/attention.pyAttention.__init__里用head_dim dim // num_heads算出每头宽度一个 Linear 同时产出 Q/K/Vforward里一行reshape就把大矩阵拆成 12 份。三步快速上手 DINOv2 注意力特征 想亲手看效果三步就够拿代码git clone https://gitcode.com/GitHub_Trending/di/dinov2装好torch加载模型唯一的必要依赖建议装 CUDA 版。加载预训练骨干torch.hub.load(facebookresearch/dinov2, dinov2_vits14)拿到 21M 参数的小模型喂进一张图就能拿到 CLS token 和每个 patch 的特征。看特征干活直接打开 notebooks/semantic_segmentation.ipynb可以看到这套注意力特征接上解码头后的像素级输出notebooks/depth_estimation.ipynb里还有深度估计的同类演示。上图是仓库 Cell-DINO 衍生模型在细胞显微图像上的特征可视化能看到注意力特征明显聚集在细胞结构区域而不是均匀铺满背景。效果对比只接一层线性能差多少仓库 README 的预训练模型表里有一组官方数据直接引用模型参数量ImageNet k-NNImageNet linearViT-S/14 distilled21 M79.0%81.1%ViT-B/14 distilled86 M82.1%84.5%ViT-L/14 distilled300 M83.5%86.3%ViT-g/141,100 M83.5%86.5%数据出处仓库 README “Pretrained models” 表格。注意这组数字的含义骨干权重不做微调只在特征上训练一个线性层linear或用最近邻检索k-NN分类21M 参数的小模型就拿到 81.1%。为什么可行根源还是多头注意力每个 patch token 从第一层起就能和其他所有 token 交换信息CLS token 被逐层“评审”携带的信息足够完整一层线性就能切开类别。这也是同一套特征能直接迁移到分割、深度估计等下游任务的原因——仓库里就附带了现成的解码头dinov2/eval/segmentation/、dinov2/eval/depth/。局限与建议用之前要知道的三件事显存随 token 数平方增长注意力要算所有 token 对的相似度矩阵。224×224 输入、patch 为 14 时是 16×16256 个 patch换到 518×518 高分辨率就是 1369 个 patch矩阵膨胀 5 倍以上。仓库的MemEffAttention基于 xFormers是工程上的缓解手段若还要更省稀疏注意力、窗口注意力等方向值得关注。num_heads不能乱改代码里是head_dim dim // num_heads头数必须整除特征维度。embed_dim768配 12 头成立因为 768÷1264改了头数又忽略这个约束要么直接报错要么得到无意义的结果。通用特征 ≠ 任务最优特征自监督特征面广但在某个专门的小数据集上未必比从头完整微调的模型更好。建议顺序先做 linear probe / k-NN 验证特征质量再决定要不要微调正好对应上表的两列。一句话收尾多头注意力是 DINOv2 的“多视角评审会”把一份特征空间拆成若干独立车道各自算注意力融合后得到全局稳健的视觉表示。想继续深入可以先跑一遍 notebooks/semantic_segmentation.ipynb再对照 dinov2/models/vision_transformer.py 看这些块是怎么组装成完整模型的两个文件都不长。【免费下载链接】dinov2PyTorch code and models for the DINOv2 self-supervised learning method.项目地址: https://gitcode.com/GitHub_Trending/di/dinov2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表