【问题标题】:ResNet50 torchvision implementation gives low accuracy on CIFAR-10ResNet50 torchvision 实现在 CIFAR-10 上的准确性较低
【发布时间】:2020-09-06 02:44:02
【问题描述】:

我是深度学习和 PyTorch 的新手。我在 cifar10 的 torchvision 模块中使用 resnet-50 模型。我已经从 torchvision 导入了 CIFAR-10 数据集。测试的准确性非常低,我尝试配置分类层,但准确性没有变化。我的代码有问题吗?我在计算准确性时犯了错误吗?

import torchvision
import torch
import torch.nn as nn
from torch import optim
import os
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import numpy as np
from collections import OrderedDict
import matplotlib.pyplot as plt

transformations=transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])])
trainset=torchvision.datasets.CIFAR10(root='./CIFAR10',download=True,transform=transformations,train=True)

testset=torchvision.datasets.CIFAR10(root='./CIFAR10',download=True,transform=transformations,train=False)

trainloader=DataLoader(dataset=trainset,batch_size=4)
testloader=DataLoader(dataset=testset,batch_size=4)

inputs,labels=next(iter(trainloader))
labels=labels.float()
inputs.size()

print(labels.type())
resnet=torchvision.models.resnet50(pretrained=True)

if torch.cuda.is_available():
  resnet=resnet.cuda()
  inputs,labels=inputs.cuda(),torch.Tensor(labels).cuda()

outputs=resnet(inputs)
outputs.size()

for param in resnet.parameters():
  param.requires_grad=False

numft=resnet.fc.in_features
print(numft)
resnet.fc=torch.nn.Sequential(nn.Linear(numft,1000),nn.ReLU(),nn.Linear(1000,10))
resnet.cuda()
resnet.train(True)
optimizer=torch.optim.SGD(resnet.parameters(),lr=0.001,momentum=0.9)
criterion=nn.CrossEntropyLoss()

for epoch in range(5):
    resnet.train(True)

    trainloss=0
    correct=0
    for x,y in trainloader:
        x,y=x.cuda(),y.cuda()
        optimizer.zero_grad()

        yhat=resnet(x)
        loss=criterion(yhat,y)

        loss.backward()
        optimizer.step()
        trainloss+=loss.item()



    print('Epoch: {} Loss: {}'.format(epoch,(trainloss/len(trainloader))))

    accuracy=[]
    running_corrects=0.0
    for x_test,y_test in testloader:

        x_test,y_test=x_test.cuda(),y_test.cuda()
        yhat=resnet(x_test)
        _,z=yhat.max(1)
        running_corrects += torch.sum(y_test == z)

    accuracy.append(running_corrects/len(testloader))

print(running_corrects/len(testloader))
accuracy=max(accuracy)
print(accuracy)

训练/测试后的输出

Epoch: 0 Loss: 1.9808503997325897
Epoch: 1 Loss: 1.7917569598436356
Epoch: 2 Loss: 1.624434965057373
Epoch: 3 Loss: 1.4082191940283775
Epoch: 4 Loss: 1.1343850775527955
tensor(1.1404, device='cuda:0')
tensor(1.1404, device='cuda:0')

【问题讨论】:

    标签: machine-learning neural-network pytorch resnet torchvision


    【解决方案1】:

    我的一些观察:

    1. 您可能需要微调学习率、时期数和批量大小。例如,目前您只训练了五个 epoch 的模型,这可能不足以实现高精度。您可以尝试使用更大的 epoch 值。
    2. 您是否尝试通过设置 `param.requires_grad=True 来调整 CIFAR10 数据集的主干(特征提取器)模型?因为原始模型是在可能需要适应 CIFAR10 的 imagenet 上训练的。
    3. 在评估/测试之前,您可以设置resnet.train(False)resnet.eval() 让模型知道您处于评估模式。此外,您可能希望使用 with torch.no_grad():no_grad() 范围内评估您的模型,这将加快推理时间并减少内存使用量。
    4. [CIFAR-10 是一个平衡数据集,因此它是一个可选的 (EDA) 任务。] 您是否检查过 CIFAR10 的类分布是否为不平衡数据集?如果它是一个不平衡的数据集,您可能需要使用加权交叉熵来计算损失。还有其他策略可以解决类不平衡问题,例如过采样或欠采样。

    关于测试准确性,您需要将正确预测的总数除以数据集中的样本总数,len(testloader.dataset) 而不是len(testloader)。如果您希望准确度在 [0,100] 范围内,只需乘以 100。您可以打印每个 epoch 的测试准确度,以检查它在当前显示最大准确度时的变化情况。

    【讨论】:

    • 根据 OP 的输出,准确率为 1.1404,即 114%。那绝对不行。真正的准确率大约是 0.285 (28.5%),因为len(testloader) = len(testset) / batch_sizeCIFAR-10 也是平衡的(每类 6000 张图像)。除此之外,这是一个很好的建议,尽管我会将 epoch 数和批量大小排名更高。
    • 感谢@bit01 的建议。我觉得答案很有帮助。让我试试看,如果我有任何进一步的问题,我会告诉你。非常感谢您抽出时间阅读我的代码并解决我的问题。
    • 也感谢@MichaelJungo 的见解!
    猜你喜欢
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-07-20
    相关资源
    最近更新 更多