PyTorch: Матрица путаницы для обучения при передаче

#deep-learning #pytorch #transfer-learning

Вопрос:

Я пытался построить матрицу путаницы для приведенной ниже проверки кода def train_alexnet() . Но я продолжаю получать эту ошибку:

 IndexError: only integers, slices (`:`), ellipsis (`...`), None and long or byte Variables are valid indices (got float)
 

Итак, я попытался преобразовать свои тензоры в целочисленный тензор, но затем получил ошибку:

 ValueError: only one element tensors can be converted to Python scalars
 

Может ли кто-нибудь подсказать мне, что можно сделать, чтобы преобразовать тензоры «all_preds» и «source_value» в тензоры, содержащие целочисленные значения? Я нашел факел без градации, но я не знаю, как его использовать, потому что я новичок в pytorch.

Вот ссылка на репозиторий github, с которым я пытаюсь работать: https://github.com/syorami/DDC-transfer-learning/blob/master/DDC.py

 from __future__ import print_function

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1"

import warnings
warnings.filterwarnings('ignore')

import math
import model
import torch
import dataloader
import matplotlib.pyplot as plt
import numpy as np

import seaborn as sns
from sklearn.metrics import confusion_matrix
from plotcm import plot_confusion_matrix

from torch import nn
from torch import optim
from torch.autograd import Variable

cuda = torch.cuda.is_available()


def step_decay(epoch, learning_rate):
    
    # learning rate step decay
    # :param epoch: current training epoch
    # :param learning_rate: initial learning rate
    # :return: learning rate after step decay
    
    initial_lrate = learning_rate
    drop = 0.8
    epochs_drop = 10.0
    lrate = initial_lrate * math.pow(drop, math.floor((1   epoch) / epochs_drop))
    return lrate



def train_alexnet(epoch, model, learning_rate, source_loader):
    
    # train source on alexnet
    # :param epoch: current training epoch
    # :param model: defined alexnet
    # :param learning_rate: initial learning rate
    # :param source_loader: source loader
    # :return:
    
    log_interval = 10
    LEARNING_RATE = step_decay(epoch, learning_rate)
    print(f'Learning Rate: {LEARNING_RATE}')
    optimizer = optim.SGD([
        {'params': model.features.parameters()},
        {'params': model.classifier.parameters()},
        {'params': model.final_classifier.parameters(), 'lr': LEARNING_RATE}
    ], lr=LEARNING_RATE / 10, momentum=MOMENTUM, weight_decay=L2_DECAY)

    # enter training mode
    model.train()

    iter_source = iter(source_loader)
    num_iter = len(source_loader)

    correct = 0
    total_loss = 0
    clf_criterion = nn.CrossEntropyLoss()
    all_preds = torch.tensor([])
    source_value = torch.tensor([])
    for i in range(1, num_iter):
        source_data, source_label = iter_source.next()

          
        # print("source label: ", source_label)
        if cuda:
            source_data, source_label = source_data.cuda(), source_label.cuda()
        source_data, source_label = Variable(source_data), Variable(source_label)

        optimizer.zero_grad()
        

        ##
        
        source_preds = model(source_data)
        
        

        preds = source_preds.data.max(1, keepdim=True)[1]
        correct  = preds.eq(source_label.data.view_as(preds)).sum()
        
        
        #prediction label
        all_preds = torch.cat(
            (all_preds, preds)
            ,dim=0
            )
        
        #actual label
        source_value = torch.cat(
            (source_value,source_label)
            ,dim=0
        )
         
        loss = clf_criterion(source_preds, source_label)
        total_loss  = loss


        loss.backward()
        optimizer.step()

        if i % log_interval == 0:
            print('Train Epoch {}: [{}/{} ({:.0f}%)]tLoss: {:.6f}'.format(
                epoch, i * len(source_data), len(source_loader) * BATCH_SIZE,
                100. * i / len(source_loader), loss.item()))

    total_loss /= len(source_loader)
    acc_train = float(correct) * 100. / (len(source_loader) * BATCH_SIZE)

    # print('all preds= ',int(all_preds))
    # print("source value", int(source_value))
    stacked = torch.stack(
    (
        source_value
        ,(all_preds.argmax(dim=1))
    )
    ,dim=1
    
)   


            
    print("stacked",stacked)
    
    cmt = torch.zeros(3
        ,3, dtype=torch.float64)
    with torch.no_grad():
        for p in stacked:
            tl, pl = p.tolist()
            cmt[tl, pl] = cmt[tl, pl]   1
    print("cmt: ",cmt)
    print('{} set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)'.format(
        SOURCE_NAME, total_loss.item(), correct, len(source_loader.dataset), acc_train))
    
  


def test_alexnet(model, target_loader):
    
    # test target data on fine-tuned alexnet
    # :param model: trained alexnet on source data set
    # :param target_loader: target dataloader
    # :return: correct num
    
    # enter evaluation mode
    clf_criterion = nn.CrossEntropyLoss()

    model.eval()
    test_loss = 0
    correct = 0

    


    
    for data, target in target_test_loader:
        if cuda:
            data, target = data.cuda(), target.cuda()
        data, target = Variable(data, volatile=True), Variable(target)
        target_preds = model(data)
        


        test_loss  = clf_criterion(target_preds, target) # sum up batch loss
        pred = target_preds.data.max(1)[1] # get the index of the max log-probability
        correct  = pred.eq(target.data.view_as(pred)).cpu().sum()
        
        
    stacked = torch.stack(
    (
        target
        ,target_preds.argmax(dim=1)
    )
    ,dim=1
)
    print("stacked target",stacked)    

    test_loss /= len(target_loader)
    print('{} set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)n'.format(
        TARGET_NAME, test_loss.item(), correct, len(target_loader.dataset),
        100. * correct / len(target_loader.dataset)))
    return correct



def compute_confusion_matrix(preds, y):
    #round predictions to the closest integer
    rounded_preds = torch.round(torch.sigmoid(preds))
    return confusion_matrix(y, rounded_preds)



if __name__ == '__main__':

    ROOT_PATH = './v1234_combined/pets'
    SOURCE_NAME = 'v123'
    TARGET_NAME = 'v4'

    BATCH_SIZE = 15
    TRAIN_EPOCHS = 1
    learning_rate = 1e-2
    L2_DECAY = 5e-4
    MOMENTUM = 0.9

    source_loader = dataloader.load_training(ROOT_PATH, SOURCE_NAME, BATCH_SIZE)
    #target_train_loader = dataloader.load_training(ROOT_PATH, TARGET_NAME, BATCH_SIZE)
    target_test_loader = dataloader.load_testing(ROOT_PATH, TARGET_NAME, BATCH_SIZE)
    print('Load data complete')


    alexnet = model.Alexnet_finetune(num_classes=3)
    print('Construct model complete')

    # load pretrained alexnet model
    alexnet = model.load_pretrained_alexnet(alexnet)
    print('Load pretrained alexnet parameters completen')

    

    if cuda: alexnet.cuda()

    for epoch in range(1, TRAIN_EPOCHS   1):
        print(f'Train Epoch {epoch}:')
        train_alexnet(epoch, alexnet, learning_rate, source_loader)
        correct = test_alexnet(alexnet, target_test_loader)
    print(len(source_loader.dataset))
    
    
  


 

Ответ №1:

В одере для преобразования всех элементов тензора от поплавков к входам, вам нужно использовать .to() :

 all_preds_int = all_preds.to(torch.int64)
 

Обратите внимание, что это выглядит так, как будто вы all_preds являетесь прогнозируемыми вероятностями классов, а не фактическими метками. Возможно, вам потребуется torch.argmax выбрать соответствующее измерение. (Кстати, вывод argmax — int — нет необходимости конвертировать).

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

1. привет, спасибо. Но теперь, когда я помещаю sourve_value и all_preds в «сложенные», я продолжаю получать все значения для all_preds как 0. Это почему?

2. @hot_rod если вы преобразуете прогнозируемые вероятности из поплавков в int, все значения будут преобразованы в ноль, потому (0,1) что значения с плавающей точкой находятся только в диапазоне.

3. все преды= тензор([[1], [1], [0], …, [2], [1], [2]]) Это то, что я получаю, когда печатаю тензор all_preds. Но в сложенном виде все значения равны нулю. Вот так: сложенный тензор([[2, 0], [2, 0], [2, 0], …, [2, 0], [2, 0], [2, 0]]) Я в замешательстве? Не могли бы вы объяснить, почему это происходит?

4. Кроме того, для преобразования значений из float в in при декальцинации all_preds и source_value я использовал это — all_preds = torch.tensor ([], dtype=torch.int64) и то же самое для source_value

5. Кроме того, какие изменения я должен внести, чтобы этого не произошло?