Pytorch Resnet CNN 仅在测试数据包含所有 类 时才有效
Pytorch Resnet CNN only works when test data contains all classes
希望能解决一个奇怪的 CNN 训练问题。
我正在训练一个 Resnet classifier 来预测来自 ~10k 图像数据集的 4 classes 图像。代码非常简单。这是 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 张图像中的数据进行批处理并打乱测试数据集)和一些时期后的一些准确性结果:
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')
所以奇怪的是,我似乎无法很好地预测单个图像,而只能预测混合 classes 的大批量数据。例如,如果我提供来自 class 1 的 500 张图像,则预测是随机的,但如果我提供来自 4 class 的 500 张混合图像(很像在训练期间),则预测很好(只是就像在训练中一样)。
我似乎对如何在单个图像上使用 ResNet classifier 感到困惑,尽管它似乎确实学会了预测输入数据的各个标签(参见上面的标签和预测输出).或者我的 classifier 不是学习单个图像,而是学习图像组,不确定。
感谢任何帮助或指导(我可以提供更多代码,但不想写太长的消息)。这是预测代码:
# 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
您需要在测试前调用 model.eval()
。 (并在训练前通过调用 model.train()
将其改回)
在训练模式下,BatchNorm
将通过均值和方差对您的特征进行归一化。您可以预期所有 类 均为 1 的批次与混合 类.
的批次具有非常不同的统计数据
希望能解决一个奇怪的 CNN 训练问题。
我正在训练一个 Resnet classifier 来预测来自 ~10k 图像数据集的 4 classes 图像。代码非常简单。这是 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 张图像中的数据进行批处理并打乱测试数据集)和一些时期后的一些准确性结果:
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')
所以奇怪的是,我似乎无法很好地预测单个图像,而只能预测混合 classes 的大批量数据。例如,如果我提供来自 class 1 的 500 张图像,则预测是随机的,但如果我提供来自 4 class 的 500 张混合图像(很像在训练期间),则预测很好(只是就像在训练中一样)。
我似乎对如何在单个图像上使用 ResNet classifier 感到困惑,尽管它似乎确实学会了预测输入数据的各个标签(参见上面的标签和预测输出).或者我的 classifier 不是学习单个图像,而是学习图像组,不确定。
感谢任何帮助或指导(我可以提供更多代码,但不想写太长的消息)。这是预测代码:
# 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
您需要在测试前调用 model.eval()
。 (并在训练前通过调用 model.train()
将其改回)
在训练模式下,BatchNorm
将通过均值和方差对您的特征进行归一化。您可以预期所有 类 均为 1 的批次与混合 类.