При обучении многоклассового CNN с помощью PyTorch отображаются необычайно большие потери

#machine-learning #deep-learning #computer-vision #pytorch #conv-neural-network

#машинное обучение #глубокое обучение #компьютерное зрение #pytorch #conv-нейронная сеть

Вопрос:

В настоящее время я пытаюсь обучить CNN с помощью PyTorch, чтобы предсказать возраст субъекта. Возрастная группа варьируется от 0 до 116 лет. Я использовал ту же модель для обучения его гендерной классификации с двумя вариантами: мужской или женский.

Я перенес тот же код для возрастной классификации, я получал ошибки. Ошибка была вызвана тем, что наш последний полностью подключенный слой не возвращал достаточно большой результат (с точки зрения размера матрицы он изначально возвращал матрицу размером 50 x 2 из-за нашего гендерного классификатора, но я переключил его на 50 x 117 для возрастной классификации на основе параметров общего возраста.)

Сейчас моя проблема заключается в том, что цикл обучения печатает эпохи с огромными потерями (~ 3,5, в то время как раньше, при обучении гендерной классификации, оно было ниже нуля.)

Ниже приведен мой код:

Класс загрузчика данных:

 class MyDataset(Dataset):
    def __init__(self, root_directory, csv_file, image_path, transform = None):
        annotated_path = os.path.relpath(csv_file)   # Path to UTKFace Dataset and Annotations 
        self.read_in_csv = pd.read_csv(annotated_path, index_col=False)
        self.image_path = os.path.join(root_directory, image_path)
        self.transform = transform
        self.labels = np.asarray(self.read_in_csv.loc[:,'age'])

    def __getitem__(self, index):
        attr = self.labels[index]
        image_name = str(self.read_in_csv.loc[index, 'file'])
        image = Image.open(image_name)

        if self.transform:
            image = self.transform(image)

        dict = {'image':image, 'label':attr}

        return dict 
        
    def __len__(self):

        return len(self.read_in_csv.index)
 

Архитектура CNN:

 class ConvolutionalNN(nn.Module):
    def __init__(self):
        super(ConvolutionalNN,self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(3,96,kernel_size=7,stride=4),
            nn.BatchNorm2d(96), # Number of Features                        
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3,stride=2))
        self.layer2 = nn.Sequential(
            nn.Conv2d(96,256,kernel_size=5,padding=2),
            nn.BatchNorm2d(256),
            nn.ReLU(), # Default = False
            nn.MaxPool2d(kernel_size=3,stride=2))
        self.layer3 = nn.Sequential(
            nn.Conv2d(256,384,kernel_size=3,padding=1),
            nn.BatchNorm2d(384),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=3,stride=2))
        self.fc1 = nn.Linear(384*6*6,512)
        self.fc2 = nn.Linear(512,512)
        self.fc3 = nn.Linear(512,117)

    def forward(self,x):
        out = self.layer1(x)
        out = self.layer2(out)
        out = self.layer3(out)
        out = out.view(out.size(0),-1)
        #print out.size()
        out = F.dropout(F.relu(self.fc1(out)))
        out = F.dropout(F.relu(self.fc2(out)))
        out = self.fc3(out)

        return out
 

Цикл обучения:

 def training_loop(checkpoint = None, best=False):
    current_epoch = 1
    num_epochs = 50
    train_acc_history = []
    val_acc_history = []
    epoch_history = []
    learning_rate = 0.001
    best_val_acc = 0.0
    is_best = False
    criterion = nn.CrossEntropyLoss()
    ## Predict the Age and Gender of the Human in the Image 
    optimizer = torch.optim.SGD(cnn.parameters(),lr=0.001,momentum=0.9)
    if checkpoint is not None:
        is_best = best
        current_epoch = checkpoint['epoch']
        train_acc_history = checkpoint['train_acc_history']
        val_acc_history = checkpoint['val_acc_history']
        best_val_acc = checkpoint['best_val_acc']
        optimizer.load_state_dict(checkpoint['optimizer'])
        epoch_history = checkpoint['epoch_history']

    print('Uploading our images now...')
    for epoch in range(current_epoch, num_epochs   current_epoch):
        print('Starting epoch %d / %d' % (epoch   1, num_epochs   current_epoch))
        print('Learning Rate for this epoch: {}'.format(learning_rate))

        for i, batch in enumerate(train_loader):
            images, labels = batch['image'], batch['label']
            images = images.clone().detach()
            labels = labels.clone().detach()
            if use_gpu:
                images = images.cuda()
                labels = labels.cuda()
            
            optimizer.zero_grad()
            pred_labels = cnn(images)
            loss = criterion(pred_labels,labels)
            loss.backward()
            optimizer.step()
 

Итак, это мой код. Похоже, что он плохо обучается.

Пожалуйста, дайте мне знать, что можно сделать, чтобы исправить это.

Комментарии:

1. Это не настоящая проблема, величина кросс-энтропийных потерь зависит от количества классов, большего количества классов, больших максимальных потерь.

2. @Dr.Snoopy Хорошо! Я понимаю. Означает ли это также, что наша точность проверки будет низкой в течение многих эпох? Наша точность обучения составляет около 11%, а точность проверки составляет 0,0%. Мне просто интересно, нормально ли это при больших размерах классов.