def test_mini_batch(): # Small input output = torch.FloatTensor([[0.1, 0.0], [0.1, 0.0]]) target = torch.LongTensor([0, 0]) assert accuracy(output, target)[0].cpu().numpy() == 100.0 # A bit larger input output = torch.FloatTensor([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6], [0.1, 0.7, 0.3, 0.4, 0.5, 0.6], [0.1, 0.2, 0.8, 0.4, 0.5, 0.6], [0.1, 0.2, 0.3, 0.9, 0.5, 0.6], [0.1, 0.2, 0.3, 0.4, 1.0, 0.6], [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]]) target = torch.LongTensor([5, 1, 2, 3, 4, 5]) assert accuracy(output, target)[0].cpu().numpy() == 100.0 # A bit larger input - with not 100% output = torch.FloatTensor([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6], [0.1, 0.7, 0.3, 0.4, 0.5, 0.6], [0.1, 0.2, 0.8, 0.4, 0.5, 0.6], [0.1, 0.2, 0.3, 0.9, 0.5, 0.6], [0.1, 0.2, 0.3, 0.4, 1.0, 0.6], [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]]) target = torch.LongTensor([1, 1, 1, 1, 1, 1]) np.testing.assert_almost_equal( accuracy(output, target)[0].cpu().numpy(), 100 / 6.0)
def test_no_batch(): # Sanity check output = torch.FloatTensor([0.0, 0.0]).unsqueeze(0) target = torch.LongTensor([0]) assert accuracy(output, target)[0].cpu().numpy() == 0.0 output = torch.FloatTensor([0.0, 1.0]).unsqueeze(0) target = torch.LongTensor([1]) assert accuracy(output, target)[0].cpu().numpy() == 100.0 output = torch.FloatTensor([0.2, 0.5, 0.7]).unsqueeze(0) target = torch.LongTensor([2]) assert accuracy(output, target)[0].cpu().numpy() == 100.0
def train_one_mini_batch(model, criterion, optimizer, input_var, target_var, loss_meter, acc_meter, multi_crop, bs, ncrops): """ This routing train the model passed as parameter for one mini-batch Parameters ---------- model : torch.nn.module The network model being used. criterion : torch.nn.loss The loss function used to compute the loss of the model. optimizer : torch.optim The optimizer used to perform the weight update. input_var : torch.autograd.Variable The input data for the mini-batch target_var : torch.autograd.Variable The target data (labels) for the mini-batch loss_meter : AverageMeter Tracker for the overall loss acc_meter : AverageMeter Tracker for the overall accuracy multi_crop : bool Set to True if multi-crops are used. bs : int Batch size ncrops : int Number of crops. Returns ------- acc : float Accuracy for this mini-batch loss : float Loss for this mini-batch """ # Compute output output = model(input_var) if multi_crop: output = output.view(bs, ncrops, -1).mean(1) # Compute and record the loss loss = criterion(output, target_var) loss_meter.update(loss.data[0], len(input_var)) # Compute and record the accuracy acc = accuracy(output.data, target_var.data, topk=(1, ))[0] acc_meter.update(acc[0], len(input_var)) # Reset gradient optimizer.zero_grad() # Compute gradients loss.backward() # Perform a step by updating the weights optimizer.step() return acc, loss
def train_one_mini_batch(model, criterion, optimizer, input_var, target_var, loss_meter, acc_meter): """ This routing train the model passed as parameter for one mini-batch Parameters ---------- model : torch.nn.module The network model being used. criterion : torch.nn.loss The loss function used to compute the loss of the model. optimizer : torch.optim The optimizer used to perform the weight update. input_var : torch.autograd.Variable The input data for the mini-batch target_var : torch.autograd.Variable The target data (labels) for the mini-batch loss_meter : AverageMeter Tracker for the overall loss acc_meter : AverageMeter Tracker for the overall accuracy Returns ------- acc : float Accuracy for this mini-batch loss : float Loss for this mini-batch """ # Compute output output = model(input_var) # Compute and record the loss # for inception combine the two losses if isinstance(output, tuple): loss1 = criterion(output[0], target_var) loss2 = criterion(output[1], target_var) loss = loss1 + 0.4 * loss2 output = output[0] else: loss = criterion(output, target_var) loss_meter.update(loss.data[0], len(input_var)) loss_meter.update(loss.data[0], len(input_var)) # Compute and record the accuracy acc = accuracy(output.data, target_var.data, topk=(1, ))[0] acc_meter.update(acc[0], len(input_var)) # Reset gradient optimizer.zero_grad() # Compute gradients loss.backward() # Perform a step by updating the weights optimizer.step() return acc, loss
def evaluate_one_mini_batch(model, criterion, input_var, target_var, loss_meter, acc_meter): # Compute output output = model(input_var) # Compute and record the loss loss = criterion(output, target_var) loss_meter.update(loss.data[0], len(input_var)) # Compute and record the accuracy acc1 = accuracy(output.data, target_var.data, topk=(1, ))[0] acc_meter.update(acc1[0], len(input_var)) return acc1, loss
def train_one_mini_batch(model, criterion, optimizer, input_var, target_var, loss_meter, acc_meter): # Compute output output = model(input_var) # Compute and record the loss loss = criterion(output, target_var) loss_meter.update(loss.data[0], len(input_var)) # Compute and record the accuracy acc1 = accuracy(output.data, target_var.data, topk=(1,))[0] acc_meter.update(acc1[0], len(input_var)) # Reset gradient optimizer.zero_grad() # Compute gradients loss.backward() # Perform a step by updating the weights optimizer.step() return acc1, loss
def _evaluate(data_loader, model, criterion, writer, epoch, logging_label, no_cuda=False, log_interval=10, **kwargs): """ The evaluation routine Parameters ---------- data_loader : torch.utils.data.DataLoader The dataloader of the evaluation set model : torch.nn.module The network model being used criterion: torch.nn.loss The loss function used to compute the loss of the model writer : tensorboardX.writer.SummaryWriter The tensorboard writer object. Used to log values on file for the tensorboard visualization. epoch : int Number of the epoch (for logging purposes) logging_label : string Label for logging purposes. Typically 'test' or 'valid'. Its prepended to the logging output path and messages. no_cuda : boolean Specifies whether the GPU should be used or not. A value of 'True' means the CPU will be used. log_interval : int Interval limiting the logging of mini-batches. Default value of 10. Returns ------- top1.avg : float Accuracy of the model of the evaluated split """ multi_run = kwargs['run'] if 'run' in kwargs else None # Instantiate the counters batch_time = AverageMeter() losses = AverageMeter() top1 = AverageMeter() data_time = AverageMeter() # Switch to evaluate mode (turn off dropout & such ) model.eval() # Iterate over whole evaluation set end = time.time() # Empty lists to store the predictions and target values preds = [] targets = [] multi_run = False pbar = tqdm(enumerate(data_loader), total=len(data_loader), unit='batch', ncols=150, leave=False) for batch_idx, (input, target) in pbar: # todo: how to you implement sliding window accross batches if len(input.size()) == 5: multi_run = True # input [64, 5, 3, 299, 299] bs, ncrops, c, h, w = input.size() # input.view leaves the 3rd 4th and 5th dimension as is, but multiplies the 1st and 2nd together # result [320, 3, 299, 299] # result = input.view(-1, c, h, w) # fuse batch size and ncrops # result_avg = input.view(bs, -1, c, h, w).mean(1) input = input.view(-1, c, h, w) # If you are using tensor.max(1) then you get a tupel with two tensors, choose the first one # which is a floattensor and what you need. # input = result_avg[0] # Measure data loading time data_time.update(time.time() - end) # Moving data to GPU if not no_cuda: input = input.cuda(async=True) target = target.cuda(async=True) # Convert the input and its labels to Torch Variables # todo: check them out in debugger input_var = torch.autograd.Variable(input, volatile=True) target_var = torch.autograd.Variable(target, volatile=True) # Compute output output = model(input_var) if multi_run: output = output.view(bs, ncrops, -1).mean(1) # Compute and record the loss loss = criterion(output, target_var) losses.update(loss.data[0], input.size(0)) # Compute and record the accuracy acc1 = accuracy(output.data, target, topk=(1, ))[0] top1.update(acc1[0], input.size(0)) # Get the predictions _ = [ preds.append(item) for item in [np.argmax(item) for item in output.data.cpu().numpy()] ] _ = [targets.append(item) for item in target.cpu().numpy()] # Add loss and accuracy to Tensorboard if multi_run is None: writer.add_scalar(logging_label + '/mb_loss', loss.data[0], epoch * len(data_loader) + batch_idx) writer.add_scalar(logging_label + '/mb_accuracy', acc1.cpu().numpy(), epoch * len(data_loader) + batch_idx) else: writer.add_scalar(logging_label + '/mb_loss_{}'.format(multi_run), loss.data[0], epoch * len(data_loader) + batch_idx) writer.add_scalar( logging_label + '/mb_accuracy_{}'.format(multi_run), acc1.cpu().numpy(), epoch * len(data_loader) + batch_idx) # Measure elapsed time batch_time.update(time.time() - end) end = time.time() if batch_idx % log_interval == 0: pbar.set_description(logging_label + ' epoch [{0}][{1}/{2}]\t'.format( epoch, batch_idx, len(data_loader))) pbar.set_postfix( Time='{batch_time.avg:.3f}\t'.format(batch_time=batch_time), Loss='{loss.avg:.4f}\t'.format(loss=losses), Acc1='{top1.avg:.3f}\t'.format(top1=top1), Data='{data_time.avg:.3f}\t'.format(data_time=data_time)) # Make a confusion matrix try: cm = confusion_matrix(y_true=targets, y_pred=preds) confusion_matrix_heatmap = make_heatmap(cm, data_loader.dataset.classes) except ValueError: logging.warning('Confusion Matrix did not work as expected') confusion_matrix_heatmap = np.zeros((10, 10, 3)) # Logging the epoch-wise accuracy and confusion matrix if multi_run is None: writer.add_scalar(logging_label + '/accuracy', top1.avg, epoch) # ERROR: save_image_and_log_tensorboard() got an unexpected keyword argument 'image_tensore' # changed 'image_tensor=confusion_matrix_heattmap' to 'image=confusion_mastrix_heatmap' save_image_and_log_to_tensorboard(writer, tag=logging_label + '/confusion_matrix', image=confusion_matrix_heatmap, global_step=epoch) else: writer.add_scalar(logging_label + '/accuracy_{}'.format(multi_run), top1.avg, epoch) save_image_and_log_to_tensorboard( writer, tag=logging_label + '/confusion_matrix_{}'.format(multi_run), image=confusion_matrix_heatmap, global_step=epoch) logging.info( _prettyprint_logging_label(logging_label) + ' epoch[{}]: ' 'Acc@1={top1.avg:.3f}\t' 'Loss={loss.avg:.4f}\t' 'Batch time={batch_time.avg:.3f} ({data_time.avg:.3f} to load data)'. format(epoch, batch_time=batch_time, data_time=data_time, loss=losses, top1=top1)) # Generate a classification report for each epoch _log_classification_report(data_loader, epoch, preds, targets, writer) return top1.avg
def train(train_loader, model, criterion, optimizer, writer, epoch, no_cuda=False, log_interval=25, **kwargs): """ Training routine Parameters ---------- :param train_loader : torch.utils.data.DataLoader The dataloader of the train set. :param model : torch.nn.module The network model being used. :param criterion : torch.nn.loss The loss function used to compute the loss of the model. :param optimizer : torch.optim The optimizer used to perform the weight update. :param writer : tensorboardX.writer.SummaryWriter The tensorboard writer object. Used to log values on file for the tensorboard visualization. :param epoch : int Number of the epoch (for logging purposes). :param no_cuda : boolean Specifies whether the GPU should be used or not. A value of 'True' means the CPU will be used. :param log_interval : int Interval limiting the logging of mini-batches. Default value of 10. :return: None """ multi_run = kwargs['run'] if 'run' in kwargs else None # Instantiate the counters batch_time = AverageMeter() losses = AverageMeter() top1 = AverageMeter() data_time = AverageMeter() # Switch to train mode (turn on dropout & stuff) model.train() # Iterate over whole training set end = time.time() pbar = tqdm(enumerate(train_loader), total=len(train_loader), unit='batch', ncols=150, leave=False) for batch_idx, data in pbar: # pmu is_sequence = True if len(data) == 3 else False if is_sequence: in_data, length, target = sort_sequences_desc_order(data) else: in_data, target = data # Measure data loading time data_time.update(time.time() - end) # Moving data to GPU if not no_cuda: in_data = in_data.cuda(async=True) target = target.cuda(async=True) # pmu length = length.cuda(async=True) if is_sequence else None # pmu del # Convert the input and its labels to Torch Variables input_var = in_data # torch.autograd.Variable(input) target_var = target # torch.autograd.Variable(target) # Compute output # pmu if is_sequence: model.zero_grad() output = model((input_var, length)) # output = output.view(output.size(0), 2) # target_var = target_var.view(output.size(0)) else: output = model(input_var) # Compute and record the loss loss = criterion(output, target_var) losses.update(loss.item(), input_var.size(0)) # Compute and record the accuracy # acc1, acc5 = accuracy(output.data, target, topk=(1, 5)) acc1 = accuracy(output.data, target_var, topk=(1, ))[0] top1.update(acc1[0], input_var.size(0)) # top5.update(acc5[0], input.size(0)) # Add loss and accuracy to Tensorboard if multi_run == None: writer.add_scalar('train/mb_loss', loss.item(), epoch * len(train_loader) + batch_idx) writer.add_scalar('train/mb_accuracy', acc1.cpu().numpy(), epoch * len(train_loader) + batch_idx) else: writer.add_scalar('train/mb_loss_{}'.format(multi_run), loss.item(), epoch * len(train_loader) + batch_idx) writer.add_scalar('train/mb_accuracy_{}'.format(multi_run), acc1.cpu().numpy(), epoch * len(train_loader) + batch_idx) # Reset gradient optimizer.zero_grad() # Compute gradients loss.backward() # Perform a step by updating the weights optimizer.step() # Measure elapsed time batch_time.update(time.time() - end) end = time.time() # Log to console if batch_idx % log_interval == 0: pbar.set_description('train epoch [{0}][{1}/{2}]\t'.format( epoch, batch_idx, len(train_loader))) pbar.set_postfix( Time='{batch_time.avg:.3f}\t'.format(batch_time=batch_time), Loss='{loss.avg:.4f}\t'.format(loss=losses), Acc1='{top1.avg:.3f}\t'.format(top1=top1), Data='{data_time.avg:.3f}\t'.format(data_time=data_time))
def _evaluate(data_loader, model, criterion, observer, observer_criterion, writer, epoch, logging_label, no_cuda=False, log_interval=10, **kwargs): """ The evaluation routine Parameters ---------- :param data_loader : torch.utils.data.DataLoader The dataloader of the evaluation set :param model : torch.nn.module The network model being used :param criterion: torch.nn.loss The loss function used to compute the loss of the model :param writer : tensorboardX.writer.SummaryWriter The tensorboard writer object. Used to log values on file for the tensorboard visualization. :param epoch : int Number of the epoch (for logging purposes) :param logging_label : string Label for logging purposes. Typically 'test' or 'valid'. Its prepended to the logging output path and messages. :param no_cuda : boolean Specifies whether the GPU should be used or not. A value of 'True' means the CPU will be used. :param log_interval : int Interval limiting the logging of mini-batches. Default value of 10. :return: None """ multi_run = kwargs['run'] if 'run' in kwargs else None # Instantiate the counters batch_time = AverageMeter() losses = AverageMeter() observer_loss_meter = AverageMeter() top1 = AverageMeter() observer_acc_meter = AverageMeter() data_time = AverageMeter() # Switch to evaluate mode (turn off dropout & such ) model.eval() # Iterate over whole evaluation set end = time.time() # Empty lists to store the predictions and target values preds = [] targets = [] pbar = tqdm(enumerate(data_loader), total=len(data_loader), unit='batch', ncols=150, leave=False) for batch_idx, (input, target) in pbar: # Measure data loading time data_time.update(time.time() - end) # Moving data to GPU if not no_cuda: input = input.cuda(async=True) target = target.cuda(async=True) # Convert the input and its labels to Torch Variables input_var = torch.autograd.Variable(input, volatile=True) target_var = torch.autograd.Variable(target, volatile=True) # Compute output output = model(input_var) # Get the features from second last layer input_features_var = torch.autograd.Variable( model.module.features.data) # Use observer on the features observer_acc, observer_loss = evaluate_one_mini_batch( observer, observer_criterion, input_features_var, target_var, observer_loss_meter, observer_acc_meter) # Compute and record the loss loss = criterion(output, target_var) losses.update(loss.data[0], input.size(0)) # Compute and record the accuracy acc1 = accuracy(output.data, target, topk=(1, ))[0] top1.update(acc1[0], input.size(0)) # Get the predictions _ = [ preds.append(item) for item in [np.argmax(item) for item in output.data.cpu().numpy()] ] _ = [targets.append(item) for item in target.cpu().numpy()] # Add loss and accuracy to Tensorboard if multi_run is None: writer.add_scalar(logging_label + '/mb_loss', loss.data[0], epoch * len(data_loader) + batch_idx) writer.add_scalar(logging_label + '/mb_accuracy', acc1.cpu().numpy(), epoch * len(data_loader) + batch_idx) writer.add_scalar(logging_label + '/obs_mb_loss', observer_loss.data[0], epoch * len(data_loader) + batch_idx) writer.add_scalar(logging_label + '/obs_mb_accuracy', observer_acc.cpu().numpy(), epoch * len(data_loader) + batch_idx) else: writer.add_scalar(logging_label + '/mb_loss_{}'.format(multi_run), loss.data[0], epoch * len(data_loader) + batch_idx) writer.add_scalar( logging_label + '/mb_accuracy_{}'.format(multi_run), acc1.cpu().numpy(), epoch * len(data_loader) + batch_idx) writer.add_scalar( logging_label + '/obs_mb_loss_{}'.format(multi_run), observer_loss.data[0], epoch * len(data_loader) + batch_idx) writer.add_scalar( logging_label + '/obs_mb_accuracy_{}'.format(multi_run), observer_acc.cpu().numpy(), epoch * len(data_loader) + batch_idx) # Measure elapsed time batch_time.update(time.time() - end) end = time.time() if batch_idx % log_interval == 0: pbar.set_description(logging_label + ' epoch [{0}][{1}/{2}]\t'.format( epoch, batch_idx, len(data_loader))) pbar.set_postfix( Time='{batch_time.avg:.3f}\t'.format(batch_time=batch_time), Loss='{loss.avg:.4f}\t'.format(loss=losses), Acc1='{top1.avg:.3f}\t'.format(top1=top1), Data='{data_time.avg:.3f}\t'.format(data_time=data_time)) # Make a confusion matrix try: cm = confusion_matrix(y_true=targets, y_pred=preds) confusion_matrix_heatmap = make_heatmap(cm, data_loader.dataset.classes) except ValueError: logging.warning('Confusion Matrix did not work as expected') confusion_matrix_heatmap = np.zeros((10, 10, 3)) # Logging the epoch-wise accuracy and confusion matrix if multi_run is None: writer.add_scalar(logging_label + '/accuracy', top1.avg, epoch) writer.add_scalar(logging_label + '/obs_accuracy', observer_acc_meter.avg, epoch) save_image_and_log_to_tensorboard( writer, tag=logging_label + '/confusion_matrix', image_tensor=confusion_matrix_heatmap, global_step=epoch) else: writer.add_scalar(logging_label + '/accuracy_{}'.format(multi_run), top1.avg, epoch) writer.add_scalar(logging_label + '/obs_accuracy_{}'.format(multi_run), observer_acc_meter.avg, epoch) save_image_and_log_to_tensorboard( writer, tag=logging_label + '/confusion_matrix_{}'.format(multi_run), image_tensor=confusion_matrix_heatmap, global_step=epoch) logging.info( _prettyprint_logging_label(logging_label) + ' epoch[{}]: ' 'Acc@1={top1.avg:.3f}\t' 'Loss={loss.avg:.4f}\t' 'Batch time={batch_time.avg:.3f} ({data_time.avg:.3f} to load data)'. format(epoch, batch_time=batch_time, data_time=data_time, loss=losses, top1=top1)) # Generate a classification report for each epoch _log_classification_report(data_loader, epoch, preds, targets, writer) return top1.avg
def _evaluate(data_loader, model, criterion, writer, epoch, logging_label, no_cuda=False, log_interval=10, **kwargs): """ The evaluation routine Parameters ---------- :param data_loader : torch.utils.data.DataLoader The dataloader of the evaluation set :param model : torch.nn.module The network model being used :param criterion: torch.nn.loss The loss function used to compute the loss of the model :param writer : tensorboardX.writer.SummaryWriter The tensorboard writer object. Used to log values on file for the tensorboard visualization. :param epoch : int Number of the epoch (for logging purposes) :param logging_label : string Label for logging purposes. Typically 'test' or 'valid'. Its prepended to the logging output path and messages. :param no_cuda : boolean Specifies whether the GPU should be used or not. A value of 'True' means the CPU will be used. :param log_interval : int Interval limiting the logging of mini-batches. Default value of 10. :return: None """ multi_run = kwargs['run'] if 'run' in kwargs else None # Instantiate the counters batch_time = AverageMeter() losses = AverageMeter() top1 = AverageMeter() data_time = AverageMeter() # Switch to evaluate mode (turn off dropout & such ) model.eval() # Iterate over whole evaluation set end = time.time() # Empty lists to store the predictions and target values preds = [] targets = [] pbar = tqdm(enumerate(data_loader), total=len(data_loader), unit='batch', ncols=150, leave=False) for batch_idx, data in pbar: # pmu is_sequence = True if len(data) == 3 else False if is_sequence: in_data, length, target = sort_sequences_desc_order(data) else: in_data, target = data # Measure data loading time data_time.update(time.time() - end) # Moving data to GPU if not no_cuda: in_data = in_data.cuda(async=True) target = target.cuda(async=True) # pmu length = length.cuda(async=True) if is_sequence else None # pmu # Convert the input and its labels to Torch Variables input_var = in_data # torch.autograd.Variable(input, volatile=True) target_var = target # torch.autograd.Variable(target, volatile=True) # Compute output # pmu if is_sequence: model.zero_grad() output = model((input_var, length)) output = output.view(output.size(0), 2) target_var = target_var.view(output.size(0)) else: output = model(input_var) # Compute and record the loss loss = criterion(output, target_var) losses.update(loss.item(), input_var.size(0)) # Compute and record the accuracy acc1 = accuracy(output, target_var, topk=(1, ))[0] top1.update(acc1[0], target_var.size(0)) # Get the predictions _ = [ preds.append(item) for item in [np.argmax(item) for item in output.data.cpu().numpy()] ] _ = [targets.append(item) for item in target_var.cpu().numpy()] # Add loss and accuracy to Tensorboard if multi_run is None: writer.add_scalar(logging_label + '/mb_loss', loss.item(), epoch * len(data_loader) + batch_idx) writer.add_scalar(logging_label + '/mb_accuracy', acc1.cpu().numpy(), epoch * len(data_loader) + batch_idx) else: writer.add_scalar(logging_label + '/mb_loss_{}'.format(multi_run), loss.item(), epoch * len(data_loader) + batch_idx) writer.add_scalar( logging_label + '/mb_accuracy_{}'.format(multi_run), acc1.cpu().numpy(), epoch * len(data_loader) + batch_idx) # Measure elapsed time batch_time.update(time.time() - end) end = time.time() if batch_idx % log_interval == 0: pbar.set_description(logging_label + ' epoch [{0}][{1}/{2}]\t'.format( epoch, batch_idx, len(data_loader))) pbar.set_postfix( Time='{batch_time.avg:.3f}\t'.format(batch_time=batch_time), Loss='{loss.avg:.4f}\t'.format(loss=losses), Acc1='{top1.avg:.3f}\t'.format(top1=top1), Data='{data_time.avg:.3f}\t'.format(data_time=data_time))