资讯详情

无需训练 DINOv3 + KNN 快速构建自监督图像分类模型

📅 2026/10/27 1:21:57 | 华诺云谱 👁 阅读
无需训练 DINOv3 + KNN 快速构建自监督图像分类模型
一、DINOv3 KNN 构建自监督图像分类模型DINOv3是Meta2025年8月推出的视觉开源模型。核心优势在于通过大规模无监督预训练获得高度通用且语义丰富的图像表征能力。最大的亮点是DINOv3的骨干网络在完全冻结的情况下仅通过添加轻量级任务头就能在多种任务上取得优异表现无需微调即可直接应用。这一特性可以改变传统视觉任务的开发流程。以往面对一个新的视觉任务开发者通常需要准备大量带标签的数据并投入计算资源对预训练模型进行微调以使其适应特定的数据分布和类别。现在依据DINOv3骨干网络强达的语义特征提取能力无需骨干网络额外的训练仅结合简易的线性任务头 或KNN、SVM、朴素贝叶斯等下游算法即可快速构建效果良好的模型进一步简化了模型构建的流程和复杂度还减少了对标注数据的依赖。如下图所示展示了DINOv3提取特征获得的余弦相似度图每张图中都呈现了被红叉标记的区域与其他区域的相似程度Github 地址https://github.com/facebookresearch/dinov3本文就基于DINOv3强大的特征提取能力构建DINOv3 KNN的图像分类模型整个过程无需对模型进行任何微调训练仅提供少量样本由DINOv3提取语义特征然后使用KNN构建空间聚类模型后续预测图像同样先由DINOv3提取语义特征然后由KNN依据余弦相似度找到最相似样品进而预测目标的类别KNN构建时间基本在秒级所以开发过程几乎没有训练等待时长另外就算遇到预测错误的情况仅需增加样本添加至KNN即可而不像传统做法要重新训练模型。该过程在下面猫狗分类的场景中在各种自然背景以及各种角度下仅提供猫狗各20张共40张图像即可在测试集图像共2000张上达到99%的准确率。下面实验整体处理过程如下图所示本次实验使用dinov3-vitb16-pretrain-lvd1689m模型huggleface地址https://huggingface.co/facebook/dinov3-vitb16-pretrain-lvd1689m如果网络连接不通也可以使用ModelScope地址如下https://modelscope.cn/models/facebook/dinov3-vitb16-pretrain-lvd1689m以下是使用DINOv3模型提取图像特征的示例过程。模型会为每张输入图像生成一个768维的向量作为其语义表征。fromtransformersimportAutoImageProcessor,AutoModelimporttorchfromPILimportImagedefmain():# 加载模型model_pathfacebook/dinov3-vitb16-pretrain-lvd1689mprocessorAutoImageProcessor.from_pretrained(model_path)modelAutoModel.from_pretrained(model_path)devicetorch.device(cuda:0iftorch.cuda.is_available()elsecpu)model.to(device)model.eval()## 特征提取imagesImage.open(img/dog.png)withtorch.no_grad():inputsprocessor(imagesimages,return_tensorspt).to(device)outputsmodel(**inputs)image_featuresoutputs.last_hidden_state image_featuresimage_features.mean(dim1)image_featuresimage_features[0]print(len(image_features))print(image_features)if__name____main__:main()运行效果二、实验数据集介绍实验数据集使用ModelScope上公开的猫狗二分类数据集包含各种自然场景、各种角度下的猫和狗的图像具有很好的多样性和挑战性。数据集地址如下https://modelscope.cn/datasets/XCsunny/cat_vs_dog_class数据集包括 训练集6000张验证集2000张测试集2000张由于我们无需模型训练本次直接取验证集下的猫和狗分别前20张共40张图像作为样本构建KNN然后对测试集的2000张图像进行预测和评估。三、构建 KNN 特征空间模型这里使用scikit-learn库中的KNeighborsClassifier来实现并选择余弦相似度作为距离度量。importosimporttimefromtransformersimportAutoImageProcessor,AutoModelfromsklearn.neighborsimportKNeighborsClassifierimporttorchfromPILimportImageimportjoblibfromtqdmimporttqdm## 验证集地址下面每种分类只使用20张val_img_pathcat_vs_dog_class/val## 类别标识classify{cats:0,dogs:1}# 加载模型model_pathfacebook/dinov3-vitb16-pretrain-lvd1689mprocessorAutoImageProcessor.from_pretrained(model_path)modelAutoModel.from_pretrained(model_path)devicetorch.device(cuda:0iftorch.cuda.is_available()elsecpu)model.to(device)model.eval()defget_features(images):特征提取withtorch.no_grad():inputsprocessor(imagesimages,return_tensorspt).to(device)outputsmodel(**inputs)image_featuresoutputs.last_hidden_state image_featuresimage_features.mean(dim1)returnimage_features[0].cpu()defbuild_knn(knn_cache_modelknn_model.joblib):构建KNN模型ifos.path.exists(knn_cache_model):returnjoblib.load(knn_cache_model)knnKNeighborsClassifier(n_neighbors5,metriccosine)features,labels[],[]forclinos.listdir(val_img_path):labelclassify[cl]forimg_nameintqdm(os.listdir(os.path.join(val_img_path,cl))[:20],descBuild:cl):imageImage.open(os.path.join(val_img_path,cl,img_name))featureget_features(image)features.append(feature)labels.append(label)knn.fit(features,labels)# 保存KNN结构joblib.dump(knn,knn_cache_model,compress3)returnknndefmain():## 构建 KNNttime.time()knnbuild_knn()print(f构建KNN耗时{(time.time()-t)}s)## 使用单个图像测试test_image_pathimg/dog.pngtest_imageImage.open(test_image_path)test_featuresget_features(test_image)predictionknn.predict([test_features])print(f{test_image_path}-- 预测类别:{list(classify.keys())[prediction[0]]})if__name____main__:main()运行效果构建KNN模型只需4.5s图像预测测试为了直观地展示模型的预测效果这里从测试集中抽取部分图像进行预测并可视化。importosfromtransformersimportAutoImageProcessor,AutoModelimporttorchfromPILimportImageimportjoblibimportrandomimportmatplotlib.pyplotasplt# 测试集test_img_pathcat_vs_dog_class/testclassify[cat,dog]# 加载模型model_pathfacebook/dinov3-vitb16-pretrain-lvd1689mprocessorAutoImageProcessor.from_pretrained(model_path)modelAutoModel.from_pretrained(model_path)devicetorch.device(cuda:0iftorch.cuda.is_available()elsecpu)model.to(device)model.eval()defget_features(images):特征提取withtorch.no_grad():inputsprocessor(imagesimages,return_tensorspt).to(device)outputsmodel(**inputs)image_featuresoutputs.last_hidden_state image_featuresimage_features.mean(dim1)returnimage_features[0].cpu()defget_knn(knn_cache_modelknn_model.joblib):直接读取上一步创建好的KNNreturnjoblib.load(knn_cache_model)defmain():knnget_knn()## 准备测试数据test_images[]forclinos.listdir(test_img_path):forimg_nameinos.listdir(os.path.join(test_img_path,cl))[:8]:test_images.append(Image.open(os.path.join(test_img_path,cl,img_name)))## 随机打乱random.shuffle(test_images)## 预测# 分成四个一组test_imageslist(zip(*[iter(test_images)]*4))forgintest_images:plt.figure(figsize(8,8))fori,imageinenumerate(g):plt.subplot(2,2,i1)featureget_features(image)predictionclassify[knn.predict([feature])[0]]plt.imshow(image)plt.title(prediction)plt.show()if__name____main__:main()预测效果四、大规模测试集测试主要观察模型在测试集2000张图像上的准确率、精确率、召回率、以及F1分数importosfromtransformersimportAutoImageProcessor,AutoModelimporttorchfromPILimportImageimportjoblibfromtqdmimporttqdmfromsklearn.metricsimportf1_score,precision_score,recall_score# 测试集test_img_pathcat_vs_dog_class/testclassify{cats:0,dogs:1}# 加载模型model_pathfacebook/dinov3-vitb16-pretrain-lvd1689mprocessorAutoImageProcessor.from_pretrained(model_path)modelAutoModel.from_pretrained(model_path)devicetorch.device(cuda:0iftorch.cuda.is_available()elsecpu)model.to(device)model.eval()defget_features(images):特征提取withtorch.no_grad():inputsprocessor(imagesimages,return_tensorspt).to(device)outputsmodel(**inputs)image_featuresoutputs.last_hidden_state image_featuresimage_features.mean(dim1)returnimage_features[0].cpu()defget_knn(knn_cache_modelknn_model.joblib):直接读取上一步创建好的KNNreturnjoblib.load(knn_cache_model)defmain():knnget_knn()# 用于存储所有预测和真实标签predictions[]true_labels[]forclinos.listdir(test_img_path):labelclassify[cl]forimg_nameintqdm(os.listdir(os.path.join(test_img_path,cl)),descPrediction:cl):imageImage.open(os.path.join(test_img_path,cl,img_name))featureget_features(image)predictionknn.predict([feature])[0]predictions.append(prediction)true_labels.append(label)# 计算各项指标totallen(true_labels)oksum([1foriinrange(total)ifpredictions[i]true_labels[i]])accuracyok/total*100# 计算F1分数f1f1_score(true_labels,predictions)# 额外计算精确率和召回率precisionprecision_score(true_labels,predictions)recallrecall_score(true_labels,predictions)# 输出结果print(评估结果)print(*50)print(f总样本数 (Total):{total})print(f正确数 (Correct):{ok})print(f准确率 (Accuracy):{accuracy:.2f}%)print(f精确率 (Precision):{precision:.4f})print(f召回率 (Recall):{recall:.4f})print(fF1分数 (F1-Score):{f1:.4f})if__name____main__:main()运行效果如下准确率达到99%实测如果提供更多样本可以达到更高的准确率
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑