Pytorch 关于Batch_Size的大小及BatchNorm设置对测试结果的影响

这篇里面没图片

BatchNorm的affine=True的情况下,如果训练和测试的时候Batch_Size设置成不同的数字,比如训练的时候Batch_Size=16,测试的时候单张测试(Batch_Size=1),则测试结果会很差,必须在测试的时候Batch_Size=16(也就是测试和训练使用同样的Batch_Size),才会有合理的结果

这样的情况是因为BatchNorm的affine=True的情况下,BatchNorm的参数也会进入训练,但这个时候BatchNorm的参数是适合Batch_Size=16的时候使用的,一旦Batch_Size变化,这个训练出来的参数就会变得不适用。

解决方法是,将BatchNorm的affine=False,这样训练和测试的时候Batch_Size的大小就没有关系了,缺点是会导致训练速度变慢

以上是手写的情况下,但是在pytorch中不需要这样做,只需要在验证的时候加入 model.eval() 就可以了

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
这个错误通常是因为你的模型的最后一层输出的维度不匹配标签的维度导致的。在这个示例代码中,我们的模型的最后一层输出的是一个大小为5的张量,表示5个类别的概率,而标签是一个大小为1的张量,表示样本属于哪个类别。因此,需要将标签转换为大小为5的张量。 在PyTorch中,有一个函数叫做`torch.nn.functional.one_hot`可以将标签转换为one-hot编码的张量,即每个样本的标签被转换为一个大小为类别数的张量,其中标签对应的位置为1,其余位置为0。我们可以将标签转换为one-hot编码的张量,然后在计算损失函数时使用这个张量。具体修改如下: ```python # 在定义数据加载器时,将标签转换为one-hot编码 train_dataset = datasets.ImageFolder('./data/train', transform=transform, target_transform=lambda x: torch.nn.functional.one_hot(torch.tensor(x), num_classes=5)) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True) test_dataset = datasets.ImageFolder('./data/test', transform=transform, target_transform=lambda x: torch.nn.functional.one_hot(torch.tensor(x), num_classes=5)) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False) # 在模型的最后一层使用LogSoftmax函数 # 在计算损失函数时使用NLLLoss函数,它的输入是LogSoftmax函数的输出和one-hot编码的标签 class FlowerNet(nn.Module): def __init__(self): super(FlowerNet, self).__init__() self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1) self.bn1 = nn.BatchNorm2d(32) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) self.bn2 = nn.BatchNorm2d(64) self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1) self.bn3 = nn.BatchNorm2d(128) self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1) self.bn4 = nn.BatchNorm2d(256) self.fc1 = nn.Linear(256 * 7 * 7, 1024) self.fc2 = nn.Linear(1024, 5) self.dropout = nn.Dropout(0.5) def forward(self, x): x = nn.functional.relu(self.bn1(self.conv1(x))) x = nn.functional.max_pool2d(x, 2) x = nn.functional.relu(self.bn2(self.conv2(x))) x = nn.functional.max_pool2d(x, 2) x = nn.functional.relu(self.bn3(self.conv3(x))) x = nn.functional.max_pool2d(x, 2) x = nn.functional.relu(self.bn4(self.conv4(x))) x = nn.functional.max_pool2d(x, 2) x = x.view(-1, 256 * 7 * 7) x = nn.functional.relu(self.fc1(x)) x = self.dropout(x) x = self.fc2(x) x = nn.functional.log_softmax(x, dim=1) return x model = FlowerNet() criterion = nn.NLLLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 在训练过程中,需要将one-hot编码的标签转换为大小为1的张量,以便计算损失函数 for epoch in range(10): running_loss = 0.0 for i, (inputs, labels) in enumerate(train_loader): optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, torch.argmax(labels, dim=1)) loss.backward() optimizer.step() running_loss += loss.item() if i % 20 == 19: print('[%d, %d] loss: %.3f' % (epoch+1, i+1, running_loss/20)) running_loss = 0.0 # 在测试过程中,也需要将one-hot编码的标签转换为大小为1的张量 correct = 0 total = 0 with torch.no_grad(): for inputs, labels in test_loader: outputs = model(inputs) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == torch.argmax(labels, dim=1)).sum().item() print('Accuracy on test set: %d %%' % (100 * correct / total)) ``` 在这个修改后的代码中,我们将标签转换为one-hot编码的张量,并在模型的最后一层使用了`nn.functional.log_softmax`函数将输出转换为对数概率。在计算损失函数时,我们使用了`nn.NLLLoss`函数,它的输入是对数概率和标签的索引。在训练和测试过程中,我们将one-hot编码的标签转换为标签的索引。这样修改后,应该就可以解决这个错误了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值