预训练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
相关产品推荐
相关产品推荐

