Beispiel #1
0
    def run(self):
        ##### Start Source Code Lifelong Learning ########################
        # Args -- Approach
        if self.opt.approach == 'random':
            from approaches import random as approach
        elif self.opt.approach == 'sgd':
            from approaches import sgd as approach
        elif self.opt.approach == 'sgd-restart':
            from approaches import sgd_restart as approach
        elif self.opt.approach == 'sgd-frozen':
            from approaches import sgd_frozen as approach
        elif self.opt.approach == 'lwf':
            from approaches import lwfNLP as approach
        elif self.opt.approach == 'lfl':
            from approaches import lfl as approach
        elif self.opt.approach == 'ewc':
            from approaches import ewcNLP as approach
        elif self.opt.approach == 'imm-mean':
            from approaches import imm_mean as approach
        elif self.opt.approach == 'imm-mode':
            from approaches import imm_mode as approach
        elif self.opt.approach == 'progressive':
            from approaches import progressive as approach
        elif self.opt.approach == 'pathnet':
            from approaches import pathnet as approach
        elif self.opt.approach == 'hat-test':
            from approaches import hat_test as approach

        elif self.opt.approach == 'ar1':
            from approaches import ar1 as approach
        elif self.opt.approach == 'si':
            from approaches import si as approach
            #from approaches import hat as approach
        elif self.opt.approach == 'joint':
            from approaches import joint as approach
        elif self.opt.approach == 'lifelong':
            from approaches import lifelongBing as approach

        # Args -- Network
        if self.opt.experiment == 'mnist2' or self.opt.experiment == 'pmnist':
            if self.opt.approach == 'hat' or self.opt.approach == 'hat-test':
                from networks import mlp_hat as network
            else:
                from networks import mlp as network
        else:
            if self.opt.approach == 'lfl':
                from networks import alexnet_lfl as network
            elif self.opt.approach == 'hat':  #Select the BERT model for training datasets
                from networks import bert as network
            elif self.opt.approach == 'progressive':
                from networks import alexnet_progressive as network
            elif self.opt.approach == 'pathnet':
                from networks import alexnet_pathnet as network
            elif self.opt.approach == 'lifelong' or self.opt.model_name.find(
                    "bert"
            ) == -1:  #Only for BinLiu's method (Lifelong Learning Memory Networks for Aspect
                #Sentiment Classification)
                from networks import NotBert as network
            elif self.opt.approach == 'hat-test' or self.opt.approach == 'ar1' or self.opt.approach == 'ewc' \
                    or self.opt.approach == 'si' or self.opt.approach == 'lwf':
                from networks import bert as network

                # from networks import alexnet_hat_test as network
            else:
                from networks import alexnet as network

    ##### End Source Code Lifelong Learning ########################

    # Loss and Optimizer
        criterion = nn.CrossEntropyLoss()
        _params = filter(lambda p: p.requires_grad, self.model.parameters())

        #It is a way to obtain variables for using in optimizer and not finned tuning Bert model
        # modelVariables = [(name,var) for i, (name, var) in enumerate(self.model.named_parameters())if name.find("bert") == -1]
        #
        # for name, var in modelVariables:
        #  print ("Variable ==> " + name)

        optimizer = self.opt.optimizer(_params,
                                       lr=self.opt.learning_rate,
                                       weight_decay=self.opt.l2reg)

        ##### Start Source Code Lifelong Learning ########################    # Inits

        if self.trainset.multidomain == None or self.trainset.multidomain != True:
            print('Load data...')
            train_data_loader = DataLoader(dataset=self.trainset,
                                           batch_size=self.opt.batch_size,
                                           shuffle=True)
            test_data_loader = DataLoader(dataset=self.testset,
                                          batch_size=self.opt.batch_size,
                                          shuffle=False)
            val_data_loader = DataLoader(dataset=self.valset,
                                         batch_size=self.opt.batch_size,
                                         shuffle=False)

            self._reset_params()
            best_model_path = self._train(criterion, optimizer,
                                          train_data_loader, val_data_loader)
            self.model.load_state_dict(torch.load(best_model_path))
            self.model.eval()
            test_acc, test_f1 = self._evaluate_acc_f1(test_data_loader)
            logger.info('>> test_acc: {:.4f}, test_f1: {:.4f}'.format(
                test_acc, test_f1))
        else:
            print('Inits...')
            sizesentence = 0
            ncla = 0

            for data in self.trainset:  #Compute sentence and class size in mumtidomain context
                sizesentence += data[1]
                ncla += 1
            inputsize = (ncla, sizesentence, 0)

            acc = np.zeros((ncla, ncla), dtype=np.float32)
            lss = np.zeros((ncla, ncla), dtype=np.float32)

            accNew = np.zeros((ncla, ncla), dtype=np.float32)
            lssNew = np.zeros((ncla, ncla), dtype=np.float32)

            recallNew = np.zeros((ncla, ncla), dtype=np.float32)
            f1New = np.zeros((ncla, ncla), dtype=np.float32)

            #If exist save model with same name than model and aproach load first
            #all saved model are in algorithms/ directory
            appr = None
            net = network.Net(inputsize, self.trainset, self.opt).cuda() if torch.cuda.is_available()\
                                                                     else network.Net(inputsize, self.trainset, self.opt)
            net.set_Model(self.model)
            net.set_ModelOptimizer(optimizer)

            if torch.cuda.is_available():
                dev = "cuda:0"
                self.model.to(dev)
                net.to(dev)
                print("Update GPU(Cuda support ):" + dev)
                # utils.print_model_report(net)
            appr = approach.Appr(net,
                                 nepochs=self.opt.nepochs,
                                 lr=self.opt.lr,
                                 args=self.opt)

            if os.path.exists(self.opt.output_algorithm):
                appr.loadModel(self.opt.output_algorithm)
                print("Load Module values from: " + self.opt.output_algorithm)

            #print(appr.criterion)
            #utils.print_optimizer_config(appr.optimizer)
            print('-' * 100)
            ##### End  Source Code Lifelong Learning ########################
            print("!!!!New optmization!!!!!")
            appr._set_optimizer(optimizer)
            print("-------New optmization-------")
            ##### Start Source Code Lifelong Learning ########################    # Inits
            task = 0
            if self.opt.approach == 'lifelong':
                appr.setAllAspect(self.trainset.all_aspects)
                appr.setAllWord(self.tokenizer.word2idx)
            startDateTime = datetime.now()
            test_data_list = []
            for task, (domainame, nclav, data, aspect_vocabulary,
                       word_vocabulary) in enumerate(self.trainset):
                print('*' * 100)
                print('Task {:2d} ({:s})'.format(task, domainame))
                print('*' * 100)
                if self.opt.approach == 'lifelong':
                    appr.setAspectInDomain(task, aspect_vocabulary)
                    appr.setWordInDomain(task, word_vocabulary)

                train_data_loader = DataLoader(dataset=self.trainset[task][2],
                                               batch_size=self.opt.batch_size,
                                               shuffle=True)

                if self.trainset[task][3] != None and self.trainset[task][
                        4] != None:
                    train_data_loader.aspect_vocabulary = self.trainset[task][
                        3]
                    train_data_loader.word_vocabulary = self.trainset[task][4]

                test_data_loader = DataLoader(dataset=self.testset[task][2],
                                              batch_size=self.opt.batch_size,
                                              shuffle=False)
                val_data_loader = DataLoader(dataset=self.valset[task][2],
                                             batch_size=self.opt.batch_size,
                                             shuffle=False)
                print("-- Parameters --")

                test_data_list.append(test_data_loader)

                print("Approach " + self.opt.approach)
                print("Algorithm " + self.opt.model_name)

                print("Size element  in train_data_loader: " +
                      str(train_data_loader.__len__()))
                print("Size element  in trainset(dataset): " +
                      str(self.trainset[task][2].__len__()))

                #print(self.model.parameters())
                appr.train(task, train_data_loader, test_data_loader,
                           val_data_loader)
                print('-' * 100)

                # Test
                # for u in range(task + 1):
                #     test_data_loader = DataLoader(dataset=self.testset[u][2], batch_size=self.opt.batch_size, shuffle=False)
                #
                #     test_loss, test_acc = appr.eval(u, test_data_loader)
                #     print('>>> Test on task {:2d} - {:15s}: loss={:.3f}, acc={:5.1f}% <<<'.format(u, self.testset[u][0], test_loss,
                #                                                                                   100 * test_acc))
                #     acc[task, u] = test_acc
                #     lss[task, u] = test_loss

                # Test Lomonaco evaluation measures
                for u in range(task + 1):
                    #test_data_loader = DataLoader(dataset=self.testset[u][2], batch_size=self.opt.batch_size, shuffle=False)
                    test_data_loader = test_data_list[u]
                    test_loss, test_acc, test_recall, test_f1 = appr.eval(
                        u, test_data_loader)
                    print(
                        '>>> Test on task {:2d} - {:15s}: loss={:.3f}, acc={:5.1f}% <<<'
                        .format(u, self.testset[u][0], test_loss,
                                100 * test_acc))
                    acc[task, u] = test_acc
                    lss[task, u] = test_loss
                    accNew[task, u] = test_acc
                    lssNew[task, u] = test_loss

                    recallNew[task, u] = test_recall
                    f1New[task, u] = test_f1
                # Save

            print('Algorithm final DataTime', datetime.now() - startDateTime)
            print('Save at ' + self.opt.output)
            np.savetxt(self.opt.output, acc, '%.4f')

            print(
                'Save at Lomonaco evaluation measures (Remenber different output file --> ) '
                + self.opt.output)
            np.savetxt(self.opt.output, accNew, '%.4f')

            print(
                'Save at Lomonaco evaluation measures (Remenber different output file --> ) '
                + self.opt.recall_output)
            np.savetxt(self.opt.recall_output, recallNew, '%.4f')

            print(
                'Save at Lomonaco evaluation measures (Remenber different output file --> ) '
                + self.opt.f1_output)
            np.savetxt(self.opt.f1_output, f1New, '%.4f')

            ##### End  Source Code Lifelong Learning ########################
            if self.opt.measure == "accuracy":
                backwardTransfer, negativebackward, positivebackward = Instructor.backwardTransfer(
                    accNew, ncla)
            elif self.opt.measure == "recall":
                backwardTransfer, negativebackward, positivebackward = Instructor.backwardTransfer(
                    recallNew, ncla)
            elif self.opt.measure == "f1":
                backwardTransfer, negativebackward, positivebackward = Instructor.backwardTransfer(
                    f1New, ncla)

            globalAccuracy = Instructor.globallMeasure(accNew, ncla)
            globalF1 = Instructor.globallMeasure(f1New, ncla)
            globalRecall = Instructor.globallMeasure(recallNew, ncla)
            # forwardTransfer = Instructor.forwardTransfer(recallNew, ncla)
            forwardTransfer = Instructor.forwardTransfer(accNew, ncla)
            result = ["BWT=" + str(backwardTransfer)]
            result.append(["-BWT=" + str(negativebackward)])
            result.append(["+BWT=" + str(positivebackward)])
            result.append(["ACC=" + str(globalAccuracy)])
            result.append(["FWD=" + str(forwardTransfer)])
            result.append(["F1=" + str(globalF1)])
            result.append(["RECALL=" + str(globalRecall)])

            np.savetxt(self.opt.multi_output, result, '%s')

            if os.path.exists(self.opt.output_algorithm):
                os.remove(self.opt.output_algorithm)

            appr.saveModel(self.opt.output_algorithm)
            print("Save Module values to: " + self.opt.output_algorithm)