DINOv3以及DINOv3 + KNN实现猫狗分类的python实现
DINOv3+KNN实现猫狗分类的demo
摘要 (Abstract)
自监督学习(SSL)有望消除对人工数据标注的需求,使模型能够轻松扩展到海量数据集和更大的架构。由于不针对特定任务或领域,这种训练范式有潜力使用单一算法从自然图像到航空图像等各种来源学习通用的特征。本论文介绍了 DINOv3,这是通过简单而有效的策略实现这一愿景的重要里程碑。 首先,我们通过精细的数据准备、设计和优化,利用了扩大数据集和模型规模的优势。 其次,我们引入了一种名为 Gram Anchoring(格拉姆锚定) 的新方法,有效解决了众所周知但在长训练周期中未被解决的密集特征图退化问题。 最后,我们应用了事后(post-hoc)策略,进一步增强了模型在分辨率、模型大小和文本对齐方面的灵活性。 结果是,我们提出了一个通用的视觉基础模型,无需微调即可在广泛的设置中超越专门的 SOTA 模型。DINOv3 生成的高质量密集特征在各种视觉任务上取得了出色的性能,显著超越了以前的自监督和弱监督基础模型。我们还发布了 DINOv3 视觉模型套件,旨在通过为不同的资源限制和部署场景提供可扩展的解决方案,推动广泛任务和数据的最先进水平 。
论文总结
1. 核心贡献与创新点
DINOv3 是 Meta AI 推出的最新一代自监督学习(SSL)视觉基础模型。其核心目标是解决自监督学习在扩大规模(Scaling)时遇到的瓶颈,特别是密集特征(Dense Features)退化的问题。
-
规模与性能的突破:DINOv3 将模型参数扩展到了 70亿 (7B),并通过蒸馏技术生成了一系列高效的小模型(ViT-S 到 ViT-H+ 及 ConvNeXt 系列)。它在密集预测任务(如分割、深度估计)上大幅超越了现有的弱监督(如 SigLIP 2)和自监督模型(如 DINOv2)。
-
解决特征坍塌的 "Gram Anchoring":论文发现,当模型规模变大且训练时间延长时,虽然全局分类能力提升,但 Patch-level 的局部特征会退化。作者提出了 Gram Anchoring(格拉姆锚定) 损失函数,强制当前模型的特征相关性矩阵(Gram Matrix)与训练早期的优质特征保持一致,成功解决了这一难题 。
-
高质量的数据策略:构建了 LVD-1689M 数据集,结合了聚类(Clustering)和检索(Retrieval)两种自动化清洗策略,并混合了少量 ImageNet-1k 数据,实现了多样性与质量的平衡 。
-
通用的视觉编码器:DINOv3 不需要微调(Fine-tuning),仅凭 Frozen Backbone 配合简单的线性层,就能在目标检测、语义分割、深度估计等任务上达到 State-of-the-Art (SOTA) 水平 。
2. 核心技术细节
-
模型架构:基于 ViT 架构,引入了 Axial RoPE (旋转位置编码) 和 Register Tokens (寄存器令牌),消除了高范数伪影(Artifacts),提高了高分辨率下的稳定性 。
-
训练策略:
-
阶段一:标准的 DINO + iBOT 损失函数,使用 Sinkhorn-Knopp 聚类和 KoLeo 正则化 。
-
阶段二(Refinement):引入 Gram Anchoring 目标函数,修复密集特征 。
-
阶段三:高分辨率适应训练(High-Resolution Adaptation),支持高达 4096 像素的输入 。
-
-
高效蒸馏:开发了一种新的多学生(Multi-student)蒸馏流程,允许一个巨大的 7B 教师模型同时训练多个不同架构的学生模型(如 ViT 和 ConvNeXt),极大降低了计算成本 。
3. 实验结果亮点
-
语义分割 (ADE20k):DINOv3 7B 线性探测达到 55.9 mIoU,远超 DINOv2 (49.5) 和 AM-RADIO (53.0) 。
-
单目深度估计 (NYUv2):RMSE 降至 0.309,优于所有对比基线 。
-
视频分割跟踪 (DAVIS):在未针对视频训练的情况下,J&F 得分达到 83.3,展现了极强的时间一致性 。
-
地理空间应用:将 DINOv3 应用于卫星图像(Sat-493M 数据集),在树冠高度估计等任务上刷新了 SOTA 。
DINOv3 + KNN实现猫狗分类
- DINOv3模型下载地址:链接: https://pan.baidu.com/s/1cAXqf3IOuU8SEXupQbmVHQ 提取码: v5mh
- 猫狗数据集下载地址:链接: https://pan.baidu.com/s/1WWdtyDcICWwhvJvF0Eh5cg 提取码: 8nxf
- python代码:
- 测试单张图像:
import os
import time
from transformers import AutoImageProcessor, AutoModel
from sklearn.neighbors import KNeighborsClassifier
import torch
from PIL import Image
import joblib
from tqdm import tqdm
## 验证集地址,下面每种分类只使用20张
val_img_path = "cat_vs_dog_class/val"
## 类别标识
classify = {"cats": 0, "dogs": 1}
# 加载模型
model_path = "facebook/dinov3-vitb16-pretrain-lvd1689m"
processor = AutoImageProcessor.from_pretrained(model_path)
model = AutoModel.from_pretrained(model_path)
device = torch.device('cuda:0' if torch.cuda.is_available() else "cpu")
model.to(device)
model.eval()
def get_features(images):
'''特征提取'''
with torch.no_grad():
inputs = processor(images=images, return_tensors="pt").to(device)
outputs = model(**inputs)
image_features = outputs.last_hidden_state
image_features = image_features.mean(dim=1)
return image_features[0].cpu()
def build_knn(knn_cache_model="knn_model.joblib"):
'''构建KNN模型'''
if os.path.exists(knn_cache_model):
return joblib.load(knn_cache_model)
knn = KNeighborsClassifier(n_neighbors=5, metric='cosine')
features, labels = [], []
for cl in os.listdir(val_img_path):
label = classify[cl]
for img_name in tqdm(os.listdir(os.path.join(val_img_path, cl))[:20], desc="Build:" + cl):
image = Image.open(os.path.join(val_img_path, cl, img_name))
feature = get_features(image)
features.append(feature)
labels.append(label)
knn.fit(features, labels)
# 保存KNN结构
joblib.dump(knn, knn_cache_model, compress=3)
return knn
def main():
## 构建 KNN
t = time.time()
knn = build_knn()
print(f"构建KNN耗时:{(time.time() - t)}s")
## 使用单个图像测试
test_image_path = 'img/dog.png'
test_image = Image.open(test_image_path)
test_features = get_features(test_image)
prediction = knn.predict([test_features])
print(f"{test_image_path} --> 预测类别: {list(classify.keys())[prediction[0]]}")
if __name__ == '__main__':
main()
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)