【问题标题】:Pytorch Resnet CNN only works when test data contains all classesPytorch Resnet CNN 仅在测试数据包含所有类时才有效
【发布时间】:2021-04-07 04:46:23
【问题描述】:

希望能解决一个奇怪的 CNN 训练问题。

我正在训练一个 Resnet 分类器,以从大约 10k 图像数据集中预测 4 类图像。代码非常简单。这是 Resnet/CNN 设置部分:

####################################
########### LOAD RESNET ############
####################################
device = torch.device("cuda" if torch.cuda.is_available() 
                                  else "cpu")
model = models.resnet50(pretrained=True)

# 
for param in model.parameters():
    param.requires_grad = False
    
# 
model.fc = nn.Sequential(nn.Linear(2048, 512),
                                 nn.ReLU(),
                                 #nn.Dropout(0.2),
                                 nn.Linear(512, 10),
                                 nn.LogSoftmax(dim=1))

# 
criterion = nn.NLLLoss()

# 
optimizer = optim.Adam(model.fc.parameters(), lr=0.003)

# move model to gpu
model.to(device) 

这是训练阶段(它对 500 张图像中的数据进行批处理,并对测试数据集进行混洗)和一些 epoch 后的一些准确度结果:

   trainloader, testloader, n_batches = make_trainloader(all_data, 
                                                          vals, 
                                                          batch_size=500,
                                                          randomize=True)
    ...
    for inputs, labels in trainloader:
        ...
        inputs, labels = inputs.to(device), labels.to(device)
        
        ...
        # PREDICT;
        outputs = model(inputs)

...

epoch #:  12
Loss: 0.1689 Acc: 0.9400
labels:       tensor([0, 0, 1, 0, 3, 0, 0, 2, 1, 2], device='cuda:0')
predictions:  tensor([0, 0, 1, 0, 3, 0, 0, 2, 1, 2], device='cuda:0') 

所以奇怪的是,我似乎无法很好地预测单个图像,而只能预测具有混合类的大批量数据。例如,如果我提供来自第 1 类的 500 张图像,则预测是随机的,但如果我提供来自 4 类的 500 张混合图像(很像在训练期间),则预测很好(就像在训练期间一样)。

我似乎对如何在单个图像上使用 ResNet 分类器感到困惑,尽管它似乎确实学会了预测输入数据的各个标签(请参阅上面的标签和预测输出)。或者我的分类器不是在学习单个图像,而是图像组,不确定。

感谢任何帮助或指导(我可以提供更多代码,但不想让消息太长)。这是预测代码:

# Predict
randomize = False

# load data from above
inputs = test_data[:2000]
vals_inputs = test_vals[:2000]

print ("test data size: ", vals_inputs.shape)

trainloader, testloader, n_batches = make_trainloader(inputs, 
                                                      vals_inputs, 
                                                      batch_size=500,
                                                      randomize=randomize)
for inputs, labels in trainloader:
    # load to device
    inputs, labels = inputs.to(device), labels.to(device)

    # PREDICT;
    outputs = model(inputs)
    _, preds = torch.max(outputs, 1)

    print ("prediction: ", preds[:10])
    print ("labels: ", labels[:10])
    ...

test data size:  torch.Size([2000])
prediction:  tensor([1, 1, 2, 1, 2, 3, 2, 3, 2, 3], device='cuda:0')
labels:      tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], device='cuda:0')
0 Loss: 3.2936 Acc: 0.1420

prediction:  tensor([1, 3, 3, 3, 3, 1, 2, 1, 1, 2], device='cuda:0')
labels:      tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], device='cuda:0')
0 Loss: 2.1462 Acc: 0.2780

prediction:  tensor([3, 3, 1, 2, 0, 1, 2, 1, 3, 2], device='cuda:0')
labels:      tensor([2, 2, 2, 2, 2, 2, 2, 2, 2, 2], device='cuda:0')
0 Loss: 2.1975 Acc: 0.2560

与我简单地打乱数据相比,准确性非常高:

# Predict
randomize = True
...
test data size:  torch.Size([2000])
prediction:  tensor([0, 0, 3, 2, 0, 2, 0, 3, 0, 2], device='cuda:0')
labels:      tensor([0, 0, 3, 2, 0, 2, 0, 3, 0, 2], device='cuda:0')
0 Loss: 0.1500 Acc: 0.9580

prediction:  tensor([0, 3, 3, 3, 0, 0, 3, 2, 3, 3], device='cuda:0')
labels:      tensor([0, 2, 3, 0, 0, 0, 3, 2, 0, 3], device='cuda:0')
0 Loss: 0.1714 Acc: 0.9340

prediction:  tensor([3, 3, 2, 2, 3, 1, 3, 0, 2, 2], device='cuda:0')
labels:      tensor([3, 3, 2, 2, 3, 1, 3, 0, 2, 2], device='cuda:0')
0 Loss: 0.1655 Acc: 0.9400

【问题讨论】:

  • 能否提供make_trainloader的代码?

标签: machine-learning pytorch conv-neural-network prediction resnet


【解决方案1】:

您需要在测试前致电model.eval()。 (并在训练前致电model.train() 将其改回)

在训练模式下,BatchNorm 将通过均值和方差对您的特征进行归一化。您可以预期,所有类都为 1 的批次与具有混合类的批次具有非常不同的统计数据。

【讨论】:

猜你喜欢
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 2019-09-20
  • 1970-01-01
相关资源
最近更新 更多