【问题标题】:Pytorch tutorial loss is not decreasing as expectedPytorch 教程损失没有像预期的那样减少
【发布时间】:2019-11-20 04:37:37
【问题描述】:

我正在重新实现Pytorch cifar10 tutorial的pytorch教程

但我想使用不同的模型。 我不想使用完全连接的(在 pytorch 线性中)层,我想添加 Batch Normalization。

我的模型如下所示:

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class Net(nn.Module):
  def __init__(self):
      super(Net, self).__init__()
      self.pool = nn.MaxPool2d(2,2)
      self.conv1 = nn.Conv2d(in_channels=3,out_channels=16,kernel_size=3, padding=1, padding_mode='zeros')
      self.conv1_bn = nn.BatchNorm2d(16)
      self.conv2 = nn.Conv2d(in_channels=16,out_channels=32,kernel_size=3, padding=1, padding_mode='zeros')
      self.conv2_bn = nn.BatchNorm2d(32)
      self.conv3 = nn.Conv2d(in_channels=32,out_channels=64,kernel_size=3, padding=1, padding_mode='zeros')
      self.conv3_bn = nn.BatchNorm2d(64)
      self.conv4 = nn.Conv2d(64,64,3, padding=1, padding_mode='zeros')
      self.conv4_bn = nn.BatchNorm2d(64)
      self.conv5 = nn.Conv2d(64,10,2,padding=0)
  def forward(self, x): # x has shape (4,32,32,3)
      x = self.pool(F.relu(self.conv1_bn(self.conv1(x)))) # feature map resolution is now 16*16
      x = self.pool(F.relu(self.conv2_bn(self.conv2(x)))) # resolution now 8*8
      x = self.pool(F.relu(self.conv3_bn(self.conv3(x)))) #resolution now 4*4
      x = self.pool(F.relu(self.conv4_bn(self.conv4(x)))) # now 2*2
      x = F.relu(self.conv5(x)) # The output shape is (batchsize, 1,1,10)

      return x

Batchsize 为 4,图像分辨率为 32*32,因此 inputsize 为 4,32,32,3 由于填充,卷积层不会降低特征图的分辨率大小。 maxpool 层的分辨率减半。 Conv5 得到一个形状为 4,2,2,64 的输入。 现在我使用 filtersize 2 并且没有填充来获得 1*1 的分辨率。 我有 10 个类,所以我使用 10 个过滤器。最后的每个过滤器都应该预测它对应的类。 输出的形状现在是 (4,1,1,10)。 但是当我尝试训练这个模型时,损失并没有减少。教程模型的参数量和我的网差不多,都在~62k左右。

这是其余的代码。这与教程中的代码相同,但我必须重新调整输出以使其适合。 (教程中的输出是(4,10),我的是 4,1,1,10)

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)

net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
for epoch in range(2):  # loop over the dataset multiple times

  running_loss = 0.0
  for i, data in enumerate(trainloader, 0):
      # get the inputs; data is a list of [inputs, labels]
      inputs, labels = data[0].to(device), data[1].to(device)

      # zero the parameter gradients
      optimizer.zero_grad()

      # forward + backward + optimize
      outputs = net(inputs) # I get the values as 4,1,1,10
      outputs_reshaped = outputs.reshape(4,10)
      loss = criterion(outputs_reshaped, labels)
      loss.backward()
      optimizer.step()
      running_loss +=loss.item()
      if i % 2000 == 1999:    # print every 2000 mini-batches
          print('[%d, %5d] loss: %.3f' %
                (epoch + 1, i + 1, running_loss / 2000))
          running_loss = 0.0 

我的损失是这样的。

[1,  2000] loss: 2.348
[1,  2000] loss: 2.477
[1,  4000] loss: 2.482
[1,  6000] loss: 2.468
[1,  8000] loss: 2.471
[1, 10000] loss: 2.482
[1, 12000] loss: 2.485
[2,  2000] loss: 2.486
[2,  4000] loss: 2.470
[2,  6000] loss: 2.479
[2,  8000] loss: 2.481
[2, 10000] loss: 2.474
[2, 12000] loss: 2.470

我的模型似乎没有学到任何东西。有人知道为什么会发生这种情况吗?

【问题讨论】:

  • 我复制了您的示例(稍微调整了代码,这里和那里都有拼写错误),我什至看不到损失的变化:它卡在 2.303。
  • 我改变了意图,所以它可以用 ctrl+c 运行。学习率为 0.01,它停留在 2.303。我改变了学习率,但这似乎不是问题。我在帖子中写的损失是亚当造成的。

标签: python pytorch


【解决方案1】:

你的学习率和动量组合对于这么小的批量来说太大了,试试这些:

optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.0)
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

更新:我刚刚意识到另一个问题是您在网络末端使用 relu 激活。如果你看CrossEntropyLoss的文档,有一个忠告:

输入应包含每个原始的、未归一化的分数 类。

尝试通过从 conv5 中移除最后一个 relu 并保持 lr=0.01 和 Momentum=0.9 来训练您的网络。交叉熵损失之前的 Relu 会丢弃有关班级分数的信息。

【讨论】:

  • 我现在使用 optimizer = optim.Adam(net.parameters(),0.001) 它似乎可以工作,但它的训练速度非常慢。你知道为什么会这样吗?损失:2.270 损失:2.260 损失:2.253 损失:2.250 损失:2.232 而在本教程中损失减少得更快
  • @relot 我刚刚意识到我有另一个建议要给你,我认为它更重要。
  • 有趣的是,我们同时注意到了另一个问题。
【解决方案2】:

所以如果你有类似的问题 我将优化器更改为

 optimizer = optim.Adam(net.parameters(),0.001)

我在 forward() 中的最后一行 是

      x = F.relu(self.conv5(x))

我删除了relu,现在是

x= self.conv5(x)

现在损失正在按预期减少(比具有相同参数数量的教程快得多)

【讨论】:

    猜你喜欢
    • 2020-02-28
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 2020-11-01
    • 1970-01-01
    • 2017-12-19
    • 1970-01-01
    相关资源
    最近更新 更多