news 2026/9/12 8:02:36

DINOv2 实战教程:从零到跑通自监督特征提取的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DINOv2 实战教程:从零到跑通自监督特征提取的完整指南

DINOv2 实战教程:从零到跑通自监督特征提取的完整指南

【免费下载链接】dinov2PyTorch code and models for the DINOv2 self-supervised learning method.项目地址: https://gitcode.com/GitHub_Trending/di/dinov2

DINOv2 是 Meta 开源的自监督视觉模型,它用 1.42 亿张无标注图片学出一套通用图像特征,你无需训练就能直接搭建检索、分类、分割系统。适合想快速接入视觉特征提取器的工程师和研究者。

能力速览:DINOv2 到底是什么

把 DINOv2 理解成一台"通用视觉翻译机":你喂给它一张图,它还你一个 768 维向量(ViT-B 规格)加一组逐块的细粒度特征。不需要标签,也不关心你要做什么任务。最常被拿来做三件事:

  1. 图像检索:图片变成向量,余弦相似度即可找图;
  2. 图像分类:骨干网络冻住,只训一层线性层就能接新任务;
  3. 密集预测:逐 patch 的特征能接分割头、深度头,输出像素级结果。

它的价值在于:特征是在 LVD-142M 无标注数据上"盲练"出来的,迁移到下游任务时几乎不用重新教它看图,省掉的是你从头训 backbone 的时间和数据。

选型速查:四个尺寸怎么选

仓库内置四种规模的骨干网络,每个都有带 register 的_reg增强版:

模型名参数量特征维度层数一句话定位
dinov2_vits1421M38412跑得最快,适合批量处理和低配卡
dinov2_vitb1486M76812默认选择,速度和精度平衡
dinov2_vitl14300M102424显存够就上,精度上限更高
dinov2_vitg141.1B153640只追求极限精度时考虑

_reg后缀的版本多了 4 个 register token——相当于给模型留的"草稿纸",专门吸收 CLS token 上容易溢出的杂散信息,让 patch 级特征更干净。做分割、深度这类密集任务时优先选它。

三条判断标准,对号入座:

  • 没有特殊诉求、第一次用 →vitb14,闭眼选;
  • 输入图很大(1080p 以上)或单卡要跑大批量 →vits14,省下的显存留给 batch;
  • 任务是分割/深度/检测头,对逐像素质量敏感 → 对应尺寸的reg 版

四款的 patch 都是 14、默认输入都是 518,切换尺寸不用改预处理。

⚡ 最快上手:三行加载 + 十行代码跑通特征提取

DINOv2 安装对环境的要求压成一张表:

组件版本要求
Python3.9
PyTorch2.0.0(CUDA 11.7 编译版本)
torchvision0.15.0
xformers0.0.18
GPU 显存推理 ≥8GB,训练建议 ≥16GB

拉代码并建好环境(官方 conda 配置已锁好版本):

git clone https://gitcode.com/GitHub_Trending/di/dinov2 cd dinov2 conda env create -f conda.yaml && conda activate dinov2

下面是能直接跑通的最小片段,一次拿到整图特征:

import torch from PIL import Image from torchvision import transforms model = torch.hub.load('facebookresearch/dinov2', 'dinov2_vitb14').eval() prep = transforms.Compose([transforms.Resize(518), transforms.CenterCrop(518), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]) x = prep(Image.open('cat.jpg').convert('RGB')).unsqueeze(0) with torch.no_grad(): print(model(x).shape) # torch.Size([1, 768])

两个容易踩的点:第一次调用会从服务器下载预训练权重并缓存到~/.cache/torch/hub,所以首跑"卡住"是在下文件,不是死机;model(x)返回的是 CLS token,想要逐块特征时改调model.forward_features(x),从返回字典里取x_norm_patchtokens

模型入口都在 backbones.py,权重枚举和下载逻辑写在一起,想看它怎么拼 URL 可以直接翻这个文件。

特征流水线:一张图怎么变成向量

用人话拆开讲:

  • 先切再译:每张 14×14 的小块被一次线性变换映射成 D 维向量,就是一个 token。整张图从此变成 1369 个 token 的"句子",交给 Transformer 逐层做注意力;
  • CLS token 是"摘要":它不来自图像任何区域,靠每层注意力收集全局信息。所以分类、检索直接用它就够了;
  • patch token 是"逐词注释":顺序和空间位置严格对齐,做分割、检测时就是现成的特征图原料;
  • register token 是草稿纸:注意力计算中的"溢出量"会堆到这几个额外 token 上,CLS 和 patch 特征反而更干净——这就是 reg 版在密集任务上更稳的原因。

上面这张图来自仓库内 Cell-DINO(DINOv2 适配细胞显微成像的版本)的文档,右侧 B 面板画的正是 patch → token → 自注意力这条主线,可以对照流程图看。

🎯 场景实战:三个高频任务各十行以内

图像检索:把图片压成向量再找相似

import torch.nn.functional as F def vec(path): x = prep(Image.open(path).convert('RGB')).unsqueeze(0) with torch.no_grad(): return F.normalize(model(x), dim=-1) q = vec('query.jpg') db = torch.stack([vec(p) for p in gallery]) # (N, 768) print((db @ q).topk(5).indices.tolist()) # 最相似的 5 个编号

L2 归一化之后内积就等于余弦相似度。跑一遍你会发现:返回的第一张图在语义上(同一只猫、同一种构图)而不是逐像素意义上最接近查询图——这正是自监督特征的价值。

图像分类:只训一层线性层

import torch.nn as nn class LinearHead(nn.Module): def __init__(self, dim=768, k=1000): super().__init__() self.fc = nn.Linear(dim, k) head = LinearHead().cuda() opt = torch.optim.LBFGS(head.parameters(), max_iter=20) # backbone 全程 eval(),只有 self.fc 在更新

骨干冻结后待训练参数只有 768×1000 量级,ImageNet-1K 这类线性探测单卡几十分钟能收敛。工程化版本(多层特征拼接、KNN 评估、分布式训练)在 dinov2/eval/linear.py,KNN 评估脚本 也在同一目录,数据少于 1 万张时建议直接跑这两个脚本而不是自己写训练循环。

语义分割:先拿 37×37 的特征图

with torch.no_grad(): patch, cls = model.get_intermediate_layers( x, n=1, return_class_token=True, reshape=True) print(patch[0].shape) # (1, 768, 37, 37),可直接喂给分割头

reshape=True会把 patch token 还原成和输入对齐的空间图,接一个 DPT 解码头就是完整的分割管线。完整实现(骨干 + DPT 头 + 训练循环)在 dinov2/eval/segmentation/,不想读代码的话直接打开 notebooks/semantic_segmentation.ipynb 跟着点。

🛠 微调要点与高频坑

三种策略,一句话对照

  • 线性探测:骨干全冻,只训分类头。数据少于 1 万张、或想先要个基线,就它;
  • 部分微调:解冻最后几层,骨干学习率压到头的 1/10 左右。万级以上数据的中档选择;
  • 全量微调:所有参数都动。数据十万级起,且要盯着验证集防过拟合。

五个高频坑及解法

  1. CUDA 版本不匹配:torch 2.0.0 只和 CUDA 11.7 的 wheel 严格配套。装成 torch 2.1 再配 xformers 0.0.18,报错里会刷一片 undefined symbol——把两者重装回配套版本即可;
  2. xformers 编译失败:九成是版本对不上。优先用 conda 通道里的预编译 wheel(conda env create会直接带上),实在要源码编译时设MAX_JOBS=4降低内存峰值;
  3. 显存不够:vitg14 推理就要 10GB 上下。三步走:降到 vitl14/vitb14、输入从 518 缩到 224、开torch.cuda.amp.autocast()半精度推理;
  4. 分割输出出现花屏或黑边:多半是输入尺寸不是 14 的倍数,位置编码插值没对齐。统一用 518 或 14 的任意整数倍;
  5. 首次运行像卡死:在下载权重。瞄一眼~/.cache/torch/hub里文件大小在涨就是正常的,第二次起直接命中缓存。

📌 收尾:记住这五句就够了

  • DINOv2 = 开箱即用的自监督特征提取器,一行torch.hub.load起步,四尺寸任选。
  • 默认三件套:vitb14、输入 518、ImageNet 归一化,跑不通先从这三样查起。
  • CLS token 管分类和检索,patch token 管密集预测,reg 版让后者更稳。
  • 数据 1 万张以内上线性探测,更多数据再逐层解冻。
  • 想进垂直领域,仓库里现成的 Cell-DINO(细胞成像)和 XRay-DINO 是最好的参考起点。

延伸阅读:

  • 线性 / KNN / 分割 / 深度四类评估脚本全集:dinov2/eval/
  • Cell-DINO 领域适配案例与架构图说明:docs/README_CELL_DINO.md

【免费下载链接】dinov2PyTorch code and models for the DINOv2 self-supervised learning method.项目地址: https://gitcode.com/GitHub_Trending/di/dinov2

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 7:58:57

Vue 3 响应式能力分发:Composable、Provide/Inject 与 globalProperties 选型指南

1. 这不是“全局挂载”,而是 Vue 3 的响应式状态与能力分发体系重构Vue 3 不再是 Vue 2 那套简单的Vue.prototype.$xxx xxx粗暴挂载逻辑。如果你还在用“挂载全局 API”这种说法去理解 Vue 3,那本质上你还没跳出 Vue 2 的思维惯性——这会导致你在实际项…

作者头像 李华
网站建设 2026/9/12 7:56:26

Espresso 核心原理:UI线程协同协议与IdlingResource实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 7:54:41

STM32F103 Standby模式深度解析与可靠唤醒实践

简介:本资源是一套面向嵌入式初学者与STM32项目开发者的低功耗实战例程,聚焦STM32F103系列单片机的Standby(待机)模式应用,适用于电池供电、便携设备等对功耗敏感的物联网终端开发场景。压缩包共73个文件,含…

作者头像 李华
网站建设 2026/9/12 7:54:19

SpringBoot电商平台实战:库存管理与订单状态机设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 7:53:22

ARM Cortex-M嵌入式AI静态评测:从语法层到硅片层的四重穿透法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华