DINO 系列(v1/v2/v3)之二:DINOv2 原理的详细介绍

本文是「DINO 系列」的第二篇:

  • 第一篇:DINOv1 原理的详细介绍(self-distillation with no labels)
  • 第二篇:DINOv2 原理的详细介绍(你现在看到的这篇)
  • 第三篇:DINOv3 原理的详细介绍(下一篇

DINOv2 这篇工作可以直接理解成:把 DINOv1、iBOT 等一堆自监督技巧「凑成一个最强配方」,然后在「超大干净数据集 + 超大 ViT」上把配方拉满,从而得到一套「啥都能用、跨任务泛化很强」的视觉基础特征(visual foundation features)。

本文尽量站在工程实践视角来讲清楚:

  • DINOv2 想解决什么问题?
  • LVD-142M 数据集是怎么自动构建出来的?
  • 模型结构、损失函数到底长啥样?
  • 训练时为了「能训得动」做了哪些工程优化?
  • 在下游项目(分类 / ReID / 检索 / 分割 / 深度估计)里该怎么用?
  • 和 DINOv1 相比,选型上有什么差异?

0. 从 DINO 到 DINOv2:问题背景

0.1 DINOv1 回顾(超简)

在第一篇里我们已经说过:DINOv1 的核心是 Student--Teacher 自蒸馏 + 多视角增强

  • Student 和 Teacher 结构基本一致(通常是 ViT);
  • Teacher 参数是 Student 的 指数滑动平均(EMA)
  • 给同一张图片做多种增强(global / local crop),送入 Student 和 Teacher;
  • 让 Student 在不同视角下的输出对齐 Teacher 的输出(交叉熵);
  • 再配合 Centering、Temperature 等 trick,避免塌缩。

DINOv1 的几个关键现象:

  • 无需监督就能学出清晰的语义分割 / 部件掩码
  • ViT 特征在 kNN / 线性评估上表现非常强;
  • 但整体还是在 ImageNet 这类中等规模数据 上验证,规模和「基础模型」还有距离。

0.2 DINOv2 想进一步做到什么?

DINOv2 的目标可以一句话概括:

用纯自监督,在大规模「干净」图像上预训练 ViT,得到一套「冻住就能直接用」的视觉基础特征。

具体来说,它要同时满足:

  1. 高性能 & 高鲁棒性

    • ImageNet 线性评估接近甚至追平强监督 / OpenCLIP 等;
    • 各种 ImageNet 变种(ImageNet-V2/-A/-R/-Sketch 等)上 OOD 性能很强;
    • 对下游数据分布变化不过分敏感。
  2. 多任务通吃

    • 图像级:分类、检索、动作识别等;
    • 像素级:语义分割、深度估计等;
    • 最好是 冻住 backbone,只训一个简单 head 就能打遍天下。
  3. 规模可扩展

    • 数据:从传统的 ImageNet-1K/22K 跳到 1.4 亿级别 LVD-142M
    • 模型:从 ViT-S/B/L 拉到 ViT-g(10 亿参数量级)
    • 训练:要能在合理时间和资源内训完。

DINOv2 的一系列设计,基本都围绕这三个目标展开。


1. 数据:自动构建的大规模无监督数据集 LVD-142M

DINOv2 提出了一条数据管线,构建一个约 1.42 亿张图片 的无标签数据集,称为 LVD-142M 。核心思想:从多源图像中「自动」筛出高质量、多样、去重的数据。大致步骤:

  1. 数据来源多样化

    • 已有的高质量标注数据集(例如 ImageNet-22K、ADE20K、Places 等);
    • 海量 Web 抓取的未标注图像(噪声大,但覆盖面广)。
  2. 先用现有模型做特征提取

    • 选一个已经训练好的强特征模型(例如旧版自监督模型);
    • 对所有候选图片提取全局 embedding。
  3. 去重与数据清洗

    • 在 embedding 空间做近邻搜索:
      • 去除几乎相同的图片(如重复抓取、轻微缩放/裁剪版);
      • 严格去掉与各种公开评测集(ImageNet val/test、下游基准等)的重叠,防止泄漏。
  4. 基于检索的「自动扩充」

    • 把高质量小数据集的图片当作 query;
    • 从海量 web 图片 embedding 库中检索相似图片;
    • 类似于「用已有干净数据当种子,从 web 里拉一圈相似分布的图」。
  5. 多任务 / 多域覆盖

    • 通过选取不同 seed 数据集 + 检索策略,刻意让数据覆盖:
      • 分类、细粒度分类、场景理解;
      • 分割 / 深度相关场景;
      • 不同风格(照片、插画、艺术品等)、不同拍摄条件。

这条 pipeline 有几个工程上的好处:

  • 不依赖文本描述或人工标注,完全靠视觉 embedding 构建;
  • 和「随便抓 web 图 + 自监督」相比,
    • 更容易控制 分布和难度(比如细粒度 / 城市场景等);
    • 更容易做数据去重和隐私控制;
  • 也为后来的视觉基础模型(SAM、Depth Anything 等)提供了一个通用套路:先搞一个大而干净的视觉预训练集

2. 模型结构:ViT + Student--Teacher + patch 预测

2.1 Backbone:一整族 ViT 模型

DINOv2 主要使用 ViT / ViT with registers 作为 backbone:

  • Patch size 通常是 14×14(S/B/L/g 全家桶);
  • 输入图像先被切成 patch,线性投影后加上位置编码;
  • Transformer Encoder 输出:
    • CLS token / register token(做全局表示);
    • 所有 patch token(做局部 / 像素级任务)。

实际开源模型包括:

  • ViT-S/14、ViT-B/14、ViT-L/14、ViT-g/14;
  • 每个又有「带 register」和「不带 register」两个版本。

从工程视角看,你可以简单把它当成:一套用自监督训练好的 ViT backbone,不同规模的模型适配不同算力预算。

2.2 Student--Teacher 框架 & EMA 更新

DINOv2 延续了 DINOv1 / iBOT 的套路:使用 Student--Teacher 自蒸馏框架:

  • Student:负责反向传播和参数更新;
  • Teacher:用来提供稳定的「软标签」;
  • Teacher 的参数是 Student 的 EMA

ablahetastudentL    ext用于更新Student abla_{ heta_{\mathrm{student}}} L \;\; ext{用于更新 Student}ablahetastudentLext用于更新Student

hetateacher←mhetateacher+(1−m)hetastudent heta_{\mathrm{teacher}} \leftarrow m heta_{\mathrm{teacher}} + (1 - m) heta_{\mathrm{student}}hetateacher←mhetateacher+(1−m)hetastudent

其中:

  • ( heta_{\mathrm{student}} ):学生网络参数;
  • ( heta_{\mathrm{teacher}} ):教师网络参数;
  • ( m ):动量系数(接近 1,且随训练进度缓慢增大)。

这样一来:

  • Student 每次都朝着一个 「平滑历史平均」的 Teacher 学习;
  • Teacher 自身不接受梯度,因此比 Student 更稳定;
  • 在大规模训练中,有利于避免训练震荡和模式塌缩。

3. 自监督目标:图像级 + Patch 级 + 正则项

DINOv2 的损失可以理解为三个部分:

  1. 图像级 DINO loss(global);
  2. Patch 级 iBOT 风格 masked prediction(local);
  3. 防止特征塌缩 / 促进多样性的正则项。

3.1 图像级 DINO loss

和 DINOv1 类似,图像级目标是对齐 Student 与 Teacher 的「类别分布」,但这里的「类别」是自监督学出来的 prototype,不是真实标签。

设:

  • ( p^{\mathrm{teacher}} \in \mathbb{R}^{K} ):Teacher 对某个全局视角的 softmax 输出;
  • ( p^{\mathrm{student}} \in \mathbb{R}^{K} ):Student 对另一个视角的 softmax 输出;

则 DINO loss 为:

LDINO=−∑k=1Kpkteacherlog⁡pkstudentL_{\mathrm{DINO}} = - \sum_{k=1}^{K} p^{\mathrm{teacher}}_k \log p^{\mathrm{student}}_kLDINO=−k=1∑Kpkteacherlogpkstudent

  • 实际训练时,会对同一张图片构造多种 global view(大 crop);
  • Teacher 只看部分视角,Student 看所有视角;
  • 对所有「视角对」的 cross-entropy 求平均。

3.2 Patch 级目标:iBOT 风格 masked prediction

相比 DINOv1,DINOv2 的另一大升级是:加入 patch 级目标(iBOT 思路)

  • 对 Student 输入的 patch 序列做随机 mask(比如 mask 掉 40% patch);
  • Teacher 看到的是 没被 mask 掉 的完整图像;
  • 对于被 mask 掉的位置:
    • Student 仍会输出一个 token 表示这个位置;
    • 让 Student 的该 token 去匹配 Teacher 对应位置 token 的 cluster 分布。

设:

  • ( M ):被 mask 的 patch 数量;
  • ( qmteacherq^{\mathrm{teacher}}_{m}qmteacher ):Teacher 在第 ( m ) 个 mask 位置的 soft 分布;
  • ( qmstudentq^{\mathrm{student}}_{m}qmstudent ):Student 在对应位置的预测分布;

则 patch 级 loss:
LiBOT=−1M∑m=1M∑k=1Kqm,kteacherlog⁡qm,kstudentL_{\mathrm{iBOT}} = - \frac{1}{M} \sum_{m=1}^{M} \sum_{k=1}^{K} q^{\mathrm{teacher}}{m,k} \log q^{\mathrm{student}}{m,k}LiBOT=−M1m=1∑Mk=1∑Kqm,kteacherlogqm,kstudent

直观理解

  • 把「预测被遮挡 patch」这个任务,从像素级重建(MAE)变成了「预测语义 cluster」;
  • 和 MAE 相比,更关注语义层面的一致性,而不是低层细节;
  • 又保留了 MAE 那种「通过遮挡促使模型理解上下文」的能力。

3.3 Centering:防止输出塌缩

像 DINOv1 一样,DINOv2 在 Teacher 端也做了 在线 centering

  • 维护一个缓慢更新的全局中心向量 ( c );
  • 对 Teacher 的 logits 做平移:

zteacher←zteacher−cz^{\mathrm{teacher}} \leftarrow z^{\mathrm{teacher}} - czteacher←zteacher−c

中心更新:

c←λc+(1−λ)1B∑b=1Bg(vb)c \leftarrow \lambda c + (1 - \lambda)\frac{1}{B} \sum_{b=1}^{B} g(v_b)c←λc+(1−λ)B1b=1∑Bg(vb)

其中:

  • ( B ):batch size;
  • ( g(v_b) ):Teacher 对第 ( b ) 张图片的某个中间表示的函数(论文中采用简单的线性映射);
  • ( lambda ):动量系数。

Centering 的作用:

  • 避免所有样本都被挤到同一个原型(cluster)上;
  • 在大规模训练下保持输出分布的多样性。

3.4 KoLeo 正则:让特征空间「铺开」

DINOv2 还加入了一个叫 KoLeo regularizer 的东西,目的同样是防止特征挤在一起:

  • 对 batch 内每个特征向量 ( x_i ),找到它与其它样本的最近邻距离 ( d_i );
  • 惩罚这些最近邻距离太小的情况:

LKoLeo=−1n∑i=1nlog⁡diL_{\mathrm{KoLeo}} = -\frac{1}{n} \sum_{i=1}^{n} \log d_iLKoLeo=−n1i=1∑nlogdi

其中 ( n ) 是 batch 大小。

直观上,相当于:

  • 鼓励最近邻距离变大;
  • 让样本在特征空间中更加均匀地铺开,避免「一团糊」。

3.5 总损失

综合起来,DINOv2 的整体损失可以写成:

L=λimgLDINO+λpatchLiBOT+λKoLeoLKoLeoL = \lambda_{\mathrm{img}} L_{\mathrm{DINO}} + \lambda_{\mathrm{patch}} L_{\mathrm{iBOT}} + \lambda_{\mathrm{KoLeo}} L_{\mathrm{KoLeo}}L=λimgLDINO+λpatchLiBOT+λKoLeoLKoLeo

其中每个 ( \lambda ) 是对应 loss 的权重,实际训练中通过经验和 ablation 调整。


4. 训练技巧与工程细节

DINOv2 的一个重要贡献是:把各种工程 trick 系统性地整合起来,让「大模型 + 大数据」变得可训练

4.1 Multi-crop & 高分辨率收尾

和 DINOv1 一样,DINOv2 也使用了多视角 / 多尺度 crop:

  • 若干个 global crop(例如 224×224);
  • 若干个 local crop(例如 96×96);
  • Student 看所有 crop,Teacher 只看部分 global crop。

除此以外,DINOv2 还引入了一个 高分辨率收尾阶段

  • 大部分训练在标准分辨率(如 224×224)上进行;
  • 在训练的最后一小段 iteration(比如总 625k 中最后 10k),提升到高分辨率(如 518×518);
  • 主要目的是提升 像素级任务(分割 / 深度) 的表现,而避免从头就用高分辨率带来的巨大算力消耗。

4.2 高效 Attention 与序列打包

为了解决 ViT 在大分辨率下 attention 太吃显存 / 时间的问题,DINOv2 使用了:

  • FlashAttention:更高效的 attention kernel,实现 O(N²) 时间、O(N) 近似显存;
  • Sequence Packing:把不同分辨率的 patch 序列打包成一个长序列,在同一 batch 中处理;
  • Efficient Stochastic Depth:对被 drop 的 residual branch 直接跳过计算,节省算力。

这些改动本身不改变算法,只是 engineering 层面把训练速度提升到了一个可接受的范围。

4.3 大模型并行:FSDP + 混合精度

DINOv2 的最大模型 ViT-g/14 有接近 10 亿参数,如果用常规 Data Parallel 很难塞进显存。论文采用:

  • FSDP(Fully-Sharded Data Parallel)

    • 参数、梯度和优化器状态在多卡之间切分;
    • 训练时动态加载需要的 shard。
  • 混合精度训练(FP16 / BF16)

    • 降低显存占用;
    • 在不牺牲太多精度的情况下加速训练。

搭配前面的高效 attention 和序列打包,使得在若干台大卡机器上训练 ViT-g / ViT-L 变得可行。

4.4 Teacher 冻结蒸馏:从 ViT-g 到 ViT-S/B/L

一个有趣的设计是:

  • 先用完整的 SSL 框架训练一个 最大号 ViT-g/14
  • 然后把它当作 Frozen Teacher ,对小模型(ViT-S/B/L)再做一轮蒸馏:
    • Teacher 不再更新,只负责给出目标分布;
    • Student 用和自监督类似的损失去拟合 Teacher。

这样可以:

  • 让小模型「继承」大模型的表现;
  • 比直接从头训小模型效果更好、收敛更稳。

5. 实验结果与「Emerging Properties」

5.1 图像级任务:线性评估 & 下游分类

在 ImageNet-1K 线性评估上:

  • DINOv2 的 ViT-B/L/g 在不微调 backbone 的前提下,线性分类可以达到 80%+ 甚至更高 的 top-1;
  • 在 ImageNet-ReaL / ImageNet-V2 等分布偏移数据集上,性能优于多数自监督与弱监督模型;
  • 在 iNaturalist、Places 这类细粒度 / 场景分类任务上,也能保持领先。

这说明:DINOv2 提取的特征确实比较「通用」,而不是只对 ImageNet 这种单一分布 overfit。

5.2 检索 / 匹配任务:Instance Retrieval & Dense Matching

在 Oxford / Paris 等经典 instance retrieval benchmark 上:

  • 直接用 DINOv2 的 patch / global 特征做检索,就能打平或超越大量专门为检索设计的模型;
  • Dense matching(图像间像素级匹配)上,DINOv2 提取的 patch 特征可以很自然地对应到物体部位,跨视角对齐能力很强。

这些性质对于你做:

  • ReID(行人 / 车辆 / 室内人脸-人体多模态匹配);
  • 多视角几何 / SfM / SLAM;
  • 跨模态图像匹配;

都非常有参考价值。

5.3 像素级任务:分割 & 深度估计

在 ADE20K、Cityscapes 等语义分割,NYU / KITTI 等深度估计数据集上,论文展示了:

  • 冻住 DINOv2 backbone,只在上面接一个线性 / 简单解码头;
  • 即可达到接近或优于专门模型的性能;
  • 特别是深度估计任务,受益于 patch-level 预测和高分辨率收尾策略,结果非常亮眼。

对于工程上想做 单目深度 + 语义分割 的场景,可以直接把 DINOv2 当作 encoder。

5.4 Emerging Properties:语义显式化

类似 DINOv1,DINOv2 的 patch 特征也存在非常漂亮的「Emerging Properties」:

  • 对一段视频或多张图片,做 patch 特征的 PCA,可视化成伪色:
    • 同一物体的不同部件会显现出稳定的颜色区域;
    • 不同帧里,头 / 躯干 / 四肢等部位会被持续关注;
  • 不同物种 / 不同风格(真实照片 / 卡通 / 雕塑)的图片中,对应的物体部位在特征空间里可以对齐。

这进一步证明了:DINOv2 不只是「搞定分类」,而是真正在学习「视觉世界的结构」


6. 工程实践:如何在项目中使用 DINOv2?

下面这一节更偏「工程落地」视角,结合你的日常工作场景(ReID、检索、特征抽取等),讲讲怎么用。

6.1 用 PyTorch Hub 加载 DINOv2 backbone

最简单的方式是使用官方 PyTorch Hub:

python 复制代码
import torch

# 加载 DINOv2 backbone(ViT-B/14 为例)
model = torch.hub.load('facebookresearch/dinov2', 'dinov2_vitb14', pretrained=True)
model.eval()

通常这个 model 会输出一个 全局特征向量(比如 CLS / register token 经过投影之后)。

如果你想获取中间 patch 特征,可以:

  • 查看官方仓库中 dinov2/models 的源码,找到 forward 的返回结构;
  • 或者自己包装一个小模块,从中间层把 patch token 抠出来。

6.2 特征抽取 + L2Norm + 简单 Head

典型的下游使用方式:

python 复制代码
import torch
from torchvision import transforms
from PIL import Image

# 预处理,与 DINOv2 预训练时保持一致
transform = transforms.Compose([
    transforms.Resize(256, interpolation=transforms.InterpolationMode.BICUBIC),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=[0.485, 0.456, 0.406],
        std=[0.229, 0.224, 0.225],
    ),
])

def extract_feat(model, img_path, device='cuda'):
    img = Image.open(img_path).convert('RGB')
    x = transform(img).unsqueeze(0).to(device)
    with torch.no_grad():
        feat = model(x)          # (1, C)
        feat = torch.nn.functional.normalize(feat, dim=-1)  # L2Norm
    return feat.squeeze(0).cpu()

对于 ReID / 检索 / 相似图搜索:

  1. 用上面的函数抽取所有图库图片的特征;
  2. 存成矩阵,离线做 L2Norm;
  3. 在线查询时抽取 query 特征,做余弦/欧氏距离检索即可。

6.3 冻住 DINOv2 + 训练一个轻量分类头

对于分类 / 属性识别 / 行为识别等任务:

  1. 冻住 DINOv2 backbone:
python 复制代码
for p in model.parameters():
    p.requires_grad = False
  1. 在 DINOv2 输出之上接一个两层 MLP 或单层线性:
python 复制代码
import torch.nn as nn

class DinoLinearHead(nn.Module):
    def __init__(self, in_dim, num_classes):
        super().__init__()
        self.fc = nn.Linear(in_dim, num_classes)
    def forward(self, x):
        return self.fc(x)
  1. 只训练 head,即可在少量标注数据上获得不错的效果。

你也可以:

  • 在 ReID 任务中,把 DINOv2 当 backbone + embedding head(ArcFace / CircleLoss);
  • 在室内多姿态 ReID 中,把 patch 特征 reshape 成 feature map,再做局部池化 / 注意力(和你现在的局部注意力思路可以直接结合)。

6.4 像素级任务:把 DINOv2 当 Encoder

如果要做分割 / 单目深度等:

  • 把 DINOv2 视作 encoder,输出 patch token;
  • reshape 成 H×W×C 的 feature map;
  • 接一个简单的 U-Net / FPN 风格 decoder;
  • 前期可以完全冻住 encoder,只训 decoder,观察上限;
  • 如果有足够标注,再对前几层 encoder 做少量微调。

实务上,对你目前在做的「室内摄像头人物检测 / ReID / 姿态相关任务」,DINOv2 适合用在:

  • 初始化一个更强的 backbone;
  • 对小数据集上的多任务头进行微调;
  • 甚至直接把开源 DINOv2 作为特征提取器 + 自家小模型做轻量 distillation 到端侧。

7. DINOv1 vs DINOv2:如何在项目里选型?

下面用一个简化对比来总结:

维度 DINOv1 DINOv2
核心思路 Student--Teacher 自蒸馏,global 对齐 DINOv1 + iBOT:global + patch 预测
主干结构 CNN / ViT ViT-S/B/L/g(支持 register)
数据规模 以 ImageNet 为主(百万级) LVD-142M(亿级,无标签、自动构建)
训练目标 图像级 DINO loss 图像级 DINO + patch 级 iBOT + 正则
工程优化 多 crop + EMA + centering 再加 FlashAttention / FSDP / 高分辨率收尾等
强项 ViT 上的自监督分割能力、简洁框架 泛化强、任务覆盖面广、真正意义上的视觉基础特征
适用场景 中小规模数据上自监督预训练 希望直接用现成 backbone 做各种任务

工程选型建议(个人向):

  • 如果你自己要在 自家数据 上从头预训练一个 SSL 模型:

    • 想要 框架简单、参数少,可以参考 DINOv1;
    • 想要更强的 patch 表征和 dense task 支持,可以参考 DINOv2 的 iBOT 部分。
  • 如果你更关心 下游任务效果 / 交付时间

    • 直接 把官方 DINOv2 当 backbone,搭个 head 上去用就行;
    • 对于室内多姿态 ReID / 特殊人群检测 / 车辆重识别等任务,非常值得一试。

8. 小结与 DINOv3 预告

本文我们从三个层面把 DINOv2 拆开来看:

  1. 数据层:通过 LVD-142M 数据 pipeline,把「大而干净」的视觉预训练数据集自动构建出来;
  2. 算法层:把 DINOv1 的自蒸馏和 iBOT 的 masked patch prediction 结合起来,再加上 centering、KoLeo 正则等稳定训练;
  3. 工程层:借助 FlashAttention、FSDP、sequence packing 等一系列技巧,让 ViT-g/14 级别的大模型在亿级数据上训得动。

最终得到的 DINOv2:

  • 在图像分类、检索、分割、深度估计等 30+ benchmark 上表现强势;
  • 在 OOD 和细粒度、多域任务中鲁棒性很高;
  • 对我们这种「想直接拿来当特征抽取器 / backbone 的工程场景」非常友好。

在下一篇 「DINO 系列(v1/v2/v3)之三:DINOv3 原理的详细介绍」 中,我们可以继续聊:

  • DINOv3 如何在 DINOv2 基础上继续演进;
  • ViT registers / 文本对齐(vision-language)等新特性;
  • 以及和 SAM、CLIP 等大模型之间的生态关系。
相关推荐
_codemonster38 分钟前
深度学习实战(基于pytroch)系列(四十)长短期记忆(LSTM)从零开始实现
人工智能·深度学习·lstm
问知AI1 小时前
InsightMatrix:问知AI的核心基座大模型
人工智能·科技·ai写作·内容运营
深圳佛手1 小时前
实例说明大模型参数到底是什么
人工智能
OpenCSG1 小时前
智源Emu3.5发布:34B参数的世界模型基座,以“下一状态预测”重塑多模态Scaling范式
人工智能·开源
leo_2321 小时前
SMP(软件制作平台)到底是什么?--小视频番外篇之一
人工智能·科技创新·smp(软件制作平台)·中国语言
youcans_1 小时前
【DeepSeek 论文精读】15. DeepSeek-V3.2:开拓开源大型语言模型新前沿
论文阅读·人工智能·语言模型·智能体·deepseek
_Twink1e1 小时前
【HCIA-AIV4.0】2025题库+解析(二)
人工智能·深度学习·机器学习
新知图书1 小时前
FastGPT的特点与优势
人工智能·ai agent·智能体·大模型应用开发·大模型应用
serve the people1 小时前
PQ+IVF组合解决海量向量内存占用高和检索慢的问题
人工智能·python