【问题标题】:accuracy is not increasing in classification images分类图像的准确性没有增加
【发布时间】:2020-11-15 02:43:15
【问题描述】:

我尝试使用 dropout 使用贝叶斯 CNN 实现图像分类。
我定义了两个类:

  1. 在训练阶段退出
  2. 考试不辍学(考试不辍学?请确认)

当我启动程序时,我重新制作了训练/测试准确度保持稳定,它们不会增加。我不明白问题出在哪里。
不知道是因为卷积和池化层参数的原因还是什么?请有任何想法。

class Net(nn.Module):
   
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5, padding=2)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5, padding=2)
        self.fc1 = nn.Linear(16 * 8 * 8, 1024)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 192 * 8 * 8)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

            # Lenet with MCDO
    class Net_MCDO(nn.Module):
        def __init__(self):
            super(Net_MCDO, self).__init__()
            self.conv1 = nn.Conv2d(3, 6, 5, padding=2)
            self.pool = nn.MaxPool2d(2, 2)
            self.conv2 = nn.Conv2d(16, 192, 5, padding=2)
            self.fc1 = nn.Linear(16 * 8 * 8, 120)
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 10)
            self.dropout = nn.Dropout(p=0.3)

    def forward(self, x):
            x = self.pool(self.dropout(self.conv1(x)))
            x = self.pool(self.dropout(self.conv2(x)))
            x = x.view(-1, 192 * 8 * 8)
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(self.dropout(x)))
            x = F.softmax(self.fc3(self.dropout(x)),dim=1)
            return x
    net=Net()
    mcdo=Net_MCDO()
    
    CE = nn.CrossEntropyLoss()
    learning_rate=0.001
    optimizer=optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9)
    epoch_num = 30
    train_accuracies=np.zeros(epoch_num)
    test_accuracies=np.zeros(epoch_num)
    for epoch in range(epoch_num):
        average_loss = 0.0
        total=0
        success=0
        
        for i, data in enumerate(trainloader, 0):
            inputs, labels = data
            inputs, labels = Variable(inputs), Variable(labels)
            
            optimizer.zero_grad()
            outputs = mcdo(inputs)
            loss=CE(outputs, labels)
            loss.backward()
            optimizer.step()
 
            average_loss += loss.item()
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            success += (predicted==labels.data).sum()
 
        train_accuracy = 100.0*success/total
        succes=0
        total=0

        for (inputs, labels) in testloader:
            inputs, labels = Variable(inputs), Variable(labels)
            outputs = net(inputs)
            _,predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            success += (predicted==labels.data).sum()

        test_accuracy = 100.0*success/total
        print(u"epoch{}, average_loss{}, train_accuracy{},                 
          test_accuracy{}".format(
          epoch,
          average_loss/n_batches,
          train_accuracy,
          100*success/total
          ))
            #save
            train_accuracies[epoch] = train_accuracy
            test_accuracies[epoch] = 100.0*success/total

    plt.plot(np.arange(1, epoch_num+1), train_accuracies)
    plt.plot(np.arange(1, epoch_num+1), test_accuracies)
    plt.show()

【问题讨论】:

  • 完成了,我想现在更清楚了,谢谢
  • 什么是CE?你没有展示你是如何初始化它的。
  • 我也不明白你为什么使用mcdo 处理训练数据和net 处理测试数据?它们是独立初始化的,训练一个将如何改进另一个?
  • 我刚刚编辑过,
  • 是的,我意识到这没有任何意义,我不知道如何使用一个模型测试模型而不会丢失,

标签: deep-learning pytorch classification bayesian conv-neural-network


【解决方案1】:

是的,你是对的:测试时不要使用 dropout(也不要使用 batchnorm)。但是您不必为此创建不同的模型。您可以在训练模式和测试模式之间进行选择。只需创建一个模型,例如“net”:

# when training
outputs = net.train()(inputs)

# when testing:
outputs = net.eval()(inputs)

但无论如何,您不应该真正将 dropout 与 conv-layers 一起使用。就在最后的密集层上。这可能是它没有改善的原因。 而且你的建筑很小。你的图片有多大?如果它们超过 32x32,您可以尝试再添加一层。您也可以尝试从大约 0.001 的学习率开始,然后每次在某些时期的准确性没有提高时将其除以 2。希望这会对你有所帮助:)

编辑 我刚刚看到您在第二个模型(带有 dropout)上缺少 relu 激活,这应该会导致问题。

【讨论】:

  • 是的,我使用的是 32x32 这是 Cifar10 图像,我如何在训练模式和测试模式之间进行选择?我只创建了一个模型(带有 dropout )之后我应该怎么做?我是深度学习和 PyTorch 的新手,谢谢
  • 我在我的回答中展示了它:当你有一个模型时,即model = Model(),然后在训练模式下你做outputs = model.train()(inputs),当你想测试你做outputs = model.eval()(inputs),就是这样! eval 代表“评估”,所以 dropout 会被自动忽略
  • 好的,我去看看,非常感谢
【解决方案2】:

Pytorch 将 Softmax 合并到 CrossEntroplyLoss 中,以实现数值稳定性(以及更好的训练)。因此,您应该删除模型的 softmax 层。 (在此处查看文档:https://pytorch.org/docs/stable/nn.html#crossentropyloss)。在模型中保留Sofmax 层会导致训练速度变慢,并且可能会导致指标变差,这是因为您挤压梯度两次,因此权重更新的意义不大。

将您的代码更改为:

 class Net_MCDO(nn.Module):
        def __init__(self):
            super(Net_MCDO, self).__init__()
            self.conv1 = nn.Conv2d(3, 6, 5, padding=2)
            self.pool = nn.MaxPool2d(2, 2)
            self.conv2 = nn.Conv2d(16, 192, 5, padding=2)
            self.fc1 = nn.Linear(16 * 8 * 8, 120)
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 10)
            self.dropout = nn.Dropout(p=0.3)

    def forward(self, x):
            x = self.pool(F.relu(self.dropout(self.conv1(x))))  # recommended to add the relu
            x = self.pool(F.relu(self.dropout(self.conv2(x))))  # recommended to add the relu
            x = x.view(-1, 192 * 8 * 8)
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(self.dropout(x)))
            x = self.fc3(self.dropout(x)) # no activation function needed for the last layer
            return x 

此外,我建议您在每个卷积层或线性层之后使用激活函数,例如 ReLU()。否则你只是在执行一堆可以在一个层中学习的线性操作。

希望对你有帮助 =)

【讨论】:

    猜你喜欢
    • 2019-09-27
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 2020-09-12
    • 2020-07-11
    • 1970-01-01
    • 2012-04-18
    相关资源
    最近更新 更多