为什么我的神经网络的准确性没有提高?

Why the accuracy of my neural network does not increase?

我尝试在 python 中使用 pytorch 从头开始​​实现基于 AlexNet 结构的卷积神经网络使用CIFAR10 数据集,但我的准确性非常非常低 (10%)。我怎样才能提高我的准确性?是否存在结构性问题,或者我只需要更改超参数?很抱歉有一些小错误,但我是神经网络的初学者。

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

from collections import OrderedDict

import torchvision.datasets as datasets
import torchvision.transforms as transforms
from torchvision.datasets import CIFAR10
import os

class Config:
  def __init__(self):
    self.random_seed = 42
    self.n_epochs = 50
    self.batch_size_train = 256
    self.batch_size_test = 1000
    self.learning_rate = 0.0001
    self.momentum = 0.5
    self.log_interval = 500
    self.dropout_probability = 0.5


conf = Config()

torch.manual_seed(conf.random_seed)
torch.cuda.manual_seed(conf.random_seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
np.random.seed(conf.random_seed)

train_loader = torch.utils.data.DataLoader(
    torchvision.datasets.CIFAR10('/files/', train=True, download=True,
                               transform=torchvision.transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ])),
                               batch_size=conf.batch_size_train,
                               shuffle=True
)

test_loader = torch.utils.data.DataLoader(
    torchvision.datasets.CIFAR10('/files/', train=False, download=True,
                               transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)
                             )
    ])),
                               batch_size=conf.batch_size_test,
                               shuffle=True
)
examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)

example_data.shape
class AlexNet(nn.Module):
  def __init__(self):
    super(AlexNet,self).__init__()
    self.feature_extraction = nn.Sequential(
        nn.Conv2d(3, 96, kernel_size=11,stride = 4,padding = 2),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=3,stride=2),
        nn.Conv2d(96, 256, kernel_size = 5, padding=2),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=3,stride=2),
        nn.Conv2d(256, 384, kernel_size = 3, padding=1),
        nn.ReLU(),
        nn.Conv2d(384, 384, kernel_size = 3, padding=1),
        nn.ReLU(),
        nn.Conv2d(384, 256, kernel_size = 3, padding=1),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=3,stride=2)
        )
    self.classifier = nn.Sequential (
        nn.Dropout(p=0.5, inplace=True),
        nn.Linear(3072, out_features=4096),
        nn.ReLU(),
        nn.Dropout(p=0.5, inplace=True),
        nn.Linear(in_features=4096, out_features=4096),
        nn.ReLU(),
        nn.Linear(in_features=4096, out_features=1000)
    )
  def forward(self,x):
      x = x.view(x.size(0),-1)
      return self.classifier(x)
network = AlexNet()

model_parameters = filter(lambda p: p.requires_grad, network.parameters())
params = sum([np.prod(p.size()) for p in model_parameters])
print("The model has {} parameters.".format(f'{params:,}'))

optimizer = optim.Adam(
    network.parameters(),
    lr=conf.learning_rate
)

train_losses = []
train_counter = []
test_losses = []
test_counter = [i*len(train_loader.dataset) for i in range(conf.n_epochs + 1)]

for epoch in range(2):  # loop over the dataset multiple times

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

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = network(inputs)
        loss = F.nll_loss(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
        if i % 256 == 255:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 256))
            running_loss = 0.0

print('Finished Training')

correct = 0
total = 0
# since we're not training, we don't need to calculate the gradients for our outputs
with torch.no_grad():
    for data in test_loader:
        images, labels = data
        # calculate outputs by running images through the network
        outputs = network(images)
        # the class with the highest energy is what we choose as prediction
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

您可能已经注意到,任何深度学习包中都有大量损失函数。您必须根据问题标准选择合适的,例如 multiclass/binary、multilabel/simple、log_logits、已经 softmaxed logits,以及... . nll_loss 通常与 log_softmax logits 一起使用,但您已将其与原始 logits 一起使用。根据所说,将 log_softmax 添加到转发路径即可完成工作。所以模型会变成这样:

  def forward(self,x):
      x = x.view(x.size(0),-1)
      x = self.classifier(x)
      return torch.nn.functional.log_softmax(x, 1)

这样我在一个epoch后得到了Accuracy of the network on the 10000 test images: 43 %