示例#1
0
def train():
    save_flag = True
    trainloader = get_dataset(r'H:/DataSet_All/猫狗识别/gpu/train',
                              batch_size=64,
                              imageindex=0)
    validationloader = get_dataset(r'H:/DataSet_All/猫狗识别/gpu/test',
                                   batch_size=64,
                                   imageindex=0)

    save_dir = 'output/'
    my_model = LeNet()
    my_model = model_init(my_model)
    criterion = nn.CrossEntropyLoss().to(device)
    optimizer = optim.Adam(my_model.parameters(), lr=0.001)
    epochs = 300
    # 训练

    for epoch in range(epochs):
        loss_list = []
        acc_list = []
        set_learning_rate(optimizer, epoch)

        learning_rate = optimizer.param_groups[0]['lr']
        tq = tqdm.tqdm(trainloader, desc='train')
        tq.set_description('train Epoch{}    lr{}'.format(
            epoch, learning_rate))

        for images, labels in tq:
            images = images.to(device)
            labels = labels.to(device)
            outputs = my_model(images)
            loss = criterion(outputs, labels)

            my_model.zero_grad()
            loss.backward()
            optimizer.step()

            loss_list.append(loss.item())
            loss_ave = sum(loss_list) / len(loss_list)

            _, predicted = torch.max(outputs.data, 1)
            accuracy = (predicted == labels).sum().float() / labels.size(0)
            acc_list.append(accuracy)
            acc_ave = sum(acc_list) / len(acc_list)
            tq.set_postfix(
                loss="%.4f  accuracy:%.4f   loss_ave:%.5f  acc_ave:%.5f  " %
                (loss.item(), accuracy, loss_ave, acc_ave))

        if save_flag:
            log = "\ntrain \tEpoch {}/{} \t Learning rate: {:.5f} \t Train loss_ave: {:.5f} \t  acc_ave: {:.5f} \t  " \
                   .format(epoch, epochs, learning_rate, loss_ave, acc_ave )
            # print(log)
            logFile = open(save_dir + '/log.txt', 'a')
            logFile.write(log + '\n')
            torch.save(my_model.state_dict(), save_dir + '/model_lastest.pt')

        if epoch % 1 == 0:
            loss_list = []
            acc_list = []
            with torch.no_grad():
                tq = tqdm.tqdm(validationloader, desc='teat')
                for images, labels in tq:
                    images = images.to(device)
                    labels = labels.to(device)
                    outputs = my_model(images)
                    validation_loss = criterion(outputs, labels)
                    loss_list.append(validation_loss.item())
                    _, predicted = torch.max(outputs.data, 1)
                    accuracy = (predicted
                                == labels).sum().float() / labels.size(0)
                    acc_list.append(accuracy)
                    acc_ave = sum(acc_list) / len(acc_list)
                    loss_ave = sum(loss_list) / len(loss_list)
                    tq.set_postfix(
                        test_loss=
                        "%.4f  acc:%.4f   loss_ave:%.5f  acc_ave:%.5f  " %
                        (validation_loss, accuracy, loss_ave, acc_ave))
                log = "\ntest \tEpoch {}/{} \t Learning rate: {:.5f} \t Train loss_ave: {:.5f} \t  acc_ave: {:.5f} \t  " \
                    .format(epoch, epochs, learning_rate, loss_ave, acc_ave)
                # print(log)
                logFile = open(save_dir + '/log.txt', 'a')
                logFile.write(log + '\n')
def train_lre(hyperparameters,
              data_loader,
              val_data,
              val_labels,
              test_loader,
              n_val=5):
    net, opt = build_model(hyperparameters)

    plot_step = 10

    accuracy_log = dict()
    data_log = dict()
    subselect_val = n_val * val_labels.unique().size()[0] != len(val_labels)
    meta_net = LeNet(n_out=1)
    for i in range(hyperparameters['num_iterations']):
        t = time.time()
        net.train()
        # Line 2 get batch of data
        image, labels, index = next(iter(data_loader))
        # since validation data is small I just fixed them instead of building an iterator
        # initialize a dummy network for the meta learning of the weights
        meta_net.load_state_dict(net.state_dict())

        if torch.cuda.is_available():
            meta_net.cuda()

        image = to_var(image, requires_grad=False)
        labels = to_var(labels, requires_grad=False)

        # Lines 4 - 5 initial forward pass to compute the initial weighted loss
        y_f_hat = meta_net(image)  # Line 4
        cost = functional.binary_cross_entropy_with_logits(
            y_f_hat, labels, reduce=False)  # Line 5
        eps = to_var(torch.zeros(cost.size()))  # Line 5
        l_f_meta = torch.sum(cost * eps)

        meta_net.zero_grad()

        # Line 6 perform a parameter update
        grads = torch.autograd.grad(l_f_meta, (meta_net.params()),
                                    create_graph=True)
        meta_net.update_params(hyperparameters['lr'], source_params=grads)

        # Line 8 - 10 2nd forward pass and getting the gradients with respect to epsilon
        if subselect_val:
            class_inds = list()
            for c in val_labels.unique():
                matching_inds = (val_labels == c).nonzero()
                class_inds.append(matching_inds[np.random.permutation(
                    len(matching_inds))[:n_val]])
            class_inds = torch.cat(class_inds)
            val_input = val_data[class_inds].squeeze_(1)
            val_output = val_labels[class_inds].squeeze_(1)
        else:
            val_input = val_data
            val_output = val_labels

        y_g_hat = meta_net(val_input)

        l_g_meta = functional.binary_cross_entropy_with_logits(
            y_g_hat, val_output)

        grad_eps = torch.autograd.grad(l_g_meta, eps, only_inputs=True)[0]

        # Line 11 computing and normalizing the weights
        w_tilde = torch.clamp(-grad_eps, min=0)
        norm_c = torch.sum(w_tilde)

        if norm_c != 0:
            w = w_tilde / norm_c
        else:
            w = w_tilde

        # Lines 12 - 14 computing for the loss with the computed weights
        # and then perform a parameter update
        y_f_hat = net(image)
        cost = functional.binary_cross_entropy_with_logits(y_f_hat,
                                                           labels,
                                                           reduce=False)
        data_log[i] = pd.DataFrame(
            data={
                'w': w.numpy(),
                'grad_eps': grad_eps.numpy(),
                'pre_w_cost': cost.detach().numpy(),
                'label': labels.numpy(),
                'index': index.numpy(),
            })
        l_f = torch.sum(cost * w)

        # print(data_log[i].head())
        # print(data_log[i].tail())

        opt.zero_grad()
        l_f.backward()
        opt.step()

        # meta_l = smoothing_alpha * meta_l + (1 - smoothing_alpha) * l_g_meta.item()
        # meta_losses_clean.append(meta_l / (1 - smoothing_alpha ** (i + 1)))
        #
        # net_l = smoothing_alpha * net_l + (1 - smoothing_alpha) * l_f.item()
        # net_losses.append(net_l / (1 - smoothing_alpha ** (i + 1)))
        #
        print(time.time() - t)
        if i % plot_step == 0:
            print(i)
            net.eval()

            acc_df = {'preds': [], 'labels': [], 'index': []}
            for itr, (test_img, test_label,
                      test_idx) in enumerate(test_loader):
                test_img = to_var(test_img, requires_grad=False)
                test_label = to_var(test_label, requires_grad=False)

                output = net(test_img)
                predicted = functional.sigmoid(output)

                acc_df['preds'].extend(predicted.detach().numpy().tolist())
                acc_df['labels'].extend(test_label.numpy().tolist())
                acc_df['index'].extend(test_idx.numpy().tolist())

            accuracy_log[i] = pd.DataFrame(acc_df).sort_values(
                ['labels', 'index']).set_index('index', drop=True)

    data_log = pd.concat(data_log)
    data_log.index.set_names('iteration', level=0, inplace=True)
    accuracy_log = pd.concat(accuracy_log)
    accuracy_log.index.set_names('iteration', level=0, inplace=True)
    return data_log, accuracy_log