You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

预训练VGG16在ImageNet-V2测试集精度极低的问题排查与解决

问题描述

在PyTorch中用ImageNet-V1预训练的VGG16模型测试ImageNet-V2匹配频率测试集时,精度只有1.14%,远低于预期。代码如下:

import torch
import torchvision.datasets as datasets 
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
from torchvision.models import vgg16

model = vgg16(weights='IMAGENET1K_V1')

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

test_transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

test_dataset = datasets.ImageFolder(root='/kaggle/input/imagenetv2-testset/imagenetv2-matched-frequency-format-val', transform=test_transform)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=100, shuffle=False)

def test(model: nn.Module, loader):
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for i, (inputs, labels) in enumerate(loader):
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            _, predicted = torch.max(outputs, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    
    print(f"Test Accuracy: {100 * correct / total:.2f}%")

model.eval()
test(model, test_loader)

我怀疑问题在test_dataset.class_to_idx的映射上:原映射是{'0': 0, '1': 1, '10': 2, '100': 3,... , '999': 999},改成{'0': 0, '1': 1, '10': 10, '100': 100,... '999': 999}后,精度还是1.14%,预测值和标签也对不上。请问这是不是问题根源?该怎么改才能提升精度?

解决方法

1. 标签映射确实是核心问题,但你的修改方式不对

ImageFolder生成的class_to_idx是按文件夹名称的字典序自动排序的,直接修改这个字典没用——因为数据集加载时已经用原始映射给图片打了标签,改字典只是改了映射表,不会调整已加载的标签值。

你看到的错位是因为文件夹名是字符串格式的数字,字典序排序时'10'会排在'2'前面,导致标签索引和实际ImageNet类别ID不匹配。

2. 正确修正标签映射的步骤

加载数据集时,手动指定正确的class_to_idx,让每个文件夹名(字符串类ID)对应到正确的整数索引:

# 先获取所有文件夹名称,生成正确的映射关系
class_names = test_dataset.classes
class_to_idx = {name: int(name) for name in class_names}
# 重新创建数据集,传入正确的class_to_idx
test_dataset = datasets.ImageFolder(
    root='/kaggle/input/imagenetv2-testset/imagenetv2-matched-frequency-format-val',
    transform=test_transform,
    class_to_idx=class_to_idx
)
# 重新创建DataLoader
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=100, shuffle=False)

这样加载的标签会直接对应ImageNet原始类别ID,和预训练模型的输出索引匹配。

3. 其他可能的排查点

如果改完还是精度不对,检查这几点:

  • 确认ImageNet-V2的文件夹结构正确,每个类别文件夹里的图片确实属于对应ImageNet类别。
  • 确保预训练模型没被误改,vgg16(weights='IMAGENET1K_V1')默认加载的是完整的预训练分类头,别不小心替换了。
  • 你的预处理步骤和模型要求一致,这部分代码是对的(Resize+CenterCrop、归一化参数正确)。

内容的提问来源于stack exchange,提问作者Becker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 18:14:58