Esempio n. 1
0
def test_samples():

    samplefiles = [
        '{}normal/Multi_4_W1_1', '{}illum1/Multi_4_W1_1',
        '{}illum2/Multi_4_W1_1', '{}normal/Multi_1_W1_1',
        '{}normal/Multi_4_W1_5'
    ]
    samplefiles = list(
        map(
            lambda x: x.format(
                '/home/louishsu/Work/Workspace/ECUST2019_64x64/DATA1/1/Multi/'
            ), samplefiles))

    ## 23 channels
    modelpath = "/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/recognize_vgg11_bn_split_64x64_1_63subjects_models/recognize_vgg11_bn_split_64x64_1_23chs_550sta_20nm.pkl"
    model = torch.load(
        modelpath, map_location='cuda' if torch.cuda.is_available() else 'cpu')
    images = []
    for samplefile in samplefiles:
        images += [
            RecognizeDataset._load_image(samplefile, 'Multi',
                                         [550 + i * 20
                                          for i in range(23)]).unsqueeze(0)
        ]
    images = torch.cat(images, 0)
    y_pred_23chs = model(images).detach().numpy()

    ## single channel
    MODELPATH = "/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/recognize_vgg11_bn_split_64x64_1_63subjects_models/recognize_vgg11_bn_split_64x64_1_1chs_{}sta_20nm.pkl"
    for samplefile in samplefiles:
        y_pred = []
        for ch in [550 + i * 20 for i in range(23)]:
            image = RecognizeDataset._load_image(samplefile, 'Multi',
                                                 [ch]).unsqueeze(0)
            model = torch.load(
                MODELPATH.format(ch),
                map_location='cuda' if torch.cuda.is_available() else 'cpu')
            y_pred += [model(image).detach().numpy()]
        y_pred += [
            y_pred_23chs[samplefiles.index(samplefile)].reshape((1, -1))
        ]
        y_pred = np.concatenate(y_pred, axis=0)

        filename = '/home/louishsu/Desktop/' + '_'.join(
            samplefile.split('/')[-2:])
        np.save(filename + '.npy', y_pred)
Esempio n. 2
0
 def __init__(self, datapath, filelist, usedChannels):
     filelist = list(
         map(
             lambda x: os.path.join('/'.join(datapath.split('/')[:-1]),
                                    x.strip()), filelist))
     self.samplelist = list(
         map(
             lambda x: [
                 RecognizeDataset._load_image(x, 'Multi', usedChannels),
                 getLabel(x) - 1
             ], filelist))
Esempio n. 3
0
def test(configer):

    ## datasets
    testset = RecognizeDataset(configer.datapath, configer.datatype,
                               configer.splitmode, 'test',
                               configer.usedChannels)
    testloader = DataLoader(testset, configer.batchsize_test, shuffle=False)

    ## model
    modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl'
    assert os.path.exists(modelpath), 'please train first! '
    model = torch.load(modelpath)
    if configer.cuda and is_available(): model.cuda()

    ## loss
    loss = nn.CrossEntropyLoss()

    ## log
    logpath = os.path.join(configer.logspath, configer.modelname)
    ftest = open(os.path.join(logpath, 'test_log.txt'), 'w')

    ## initialize
    acc_test = []
    loss_test = []
    output = None
    ArcMargin = ArcMarginProduct(128, configer.n_class)

    ## start testing
    model.eval()
    for i_batch, (X, y) in enumerate(testloader):

        # get batch
        X = Variable(X.float())
        y = Variable(y)
        if configer.cuda and is_available():
            X = X.cuda()
            y = y.cuda()

        # forward
        if configer.modelbase == 'recognize_mobilefacenet':

            raw_logits = model(X)
            y_pred_prob = ArcMargin(raw_logits, y)

        else:
            y_pred_prob = model(X)
        #y_pred_prob = model(X)

        loss_i = loss(y_pred_prob, y)
        acc_i = accuracy(y_pred_prob, y)

        # log
        print_log = "{} || Batch: [{:3d}]/[{:3d}] || accuracy: {:2.2%}, loss: {:4.4f}".\
                format(getTime(), i_batch, len(testset) // configer.batchsize, acc_i, loss_i)
        print(print_log)
        ftest.write(print_log + '\n')

        loss_test += [loss_i.detach().cpu().numpy()]
        acc_test += [acc_i.cpu().numpy()]

        # save output
        if output is None:
            output = y_pred_prob.detach().cpu().numpy()
        else:
            output = np.concatenate(
                [output, y_pred_prob.detach().cpu().numpy()], axis=0)

    print(
        '------------------------------------------------------------------------------------------------------------------'
    )

    loss_test = np.mean(np.array(loss_test))
    acc_test = np.mean(np.array(acc_test))
    print_log = "{} || test | acc: {:2.2%}, loss: {:4.4f}".\
            format(getTime(), acc_test, loss_test)
    print(print_log)
    ftest.write(print_log + '\n')
    np.save(os.path.join(logpath, 'test_out.npy'), output)

    print(
        '=================================================================================================================='
    )
    ftest.close()
def main_pca():
    from tensorPCA import NDarrayPCA

    for splitidx in range(1, 6):
        
        configer = EasyDict()

        configer.dsize = (64, 64)
        configer.datatype = 'Multi'
        configer.n_epoch   = 500
        configer.lrbase = 0.0001

        configer.n_channel = 23
        configer.n_class = 63
        configer.batchsize = 32
        configer.stepsize = 250
        configer.gamma = 0.2
        configer.cuda = True

        configer.splitmode = 'split_{}x{}_{}'.format(configer.dsize[0], configer.dsize[1], splitidx)
        configer.modelbase = 'recognize_vgg11_bn'

        configer.usedChannels = [550+i*20 for i in range(23)]
        configer.n_usedChannels = len(configer.usedChannels)
        configer.modelname = '{}_{}_{}_PCA'.\
                        format(configer.modelbase, configer.splitmode, 
                                '_'.join(list(map(str, configer.usedChannels))))

        configer.datapath = '/home/louishsu/Work/Workspace/ECUST2019_{}x{}'.\
                                        format(configer.dsize[0], configer.dsize[1])
        configer.logspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/logs/{}_{}_{}subjects_logs'.\
                                        format(configer.modelbase, configer.splitmode, configer.n_class)
        configer.mdlspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/{}_{}_{}subjects_models'.\
                                        format(configer.modelbase, configer.splitmode, configer.n_class)


        trainset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'train', configer.usedChannels)
        validset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'valid', configer.usedChannels)
        trainloader = DataLoader(trainset, configer.batchsize, shuffle=True)
        validloader = DataLoader(validset, configer.batchsize, shuffle=False)

        for chs in range(10, 24):

            print(getTime(), splitidx, 'reduce to ', chs, '...')
            
            ## fit pca
            decomposer = NDarrayPCA(n_components=[chs, 64, 64])
            traindata = np.concatenate([trainset.samplelist[i][0].numpy()[np.newaxis] for i in range(len(trainset.samplelist))], axis=0)
            decomposer.fit(traindata)
            del traindata

            ## model
            modelpath = os.path.join(configer.mdlspath, configer.modelname) + '{}chs.pkl'.format(chs)
            modeldir  = '/'.join(modelpath.split('/')[:-1])
            if not os.path.exists(modeldir): os.makedirs(modeldir)
            model = modeldict[configer.modelbase](chs, configer.n_class, configer.dsize[0])
            if configer.cuda and is_available(): model.cuda()

            ## loss
            loss = nn.CrossEntropyLoss()
            params = model.parameters()
            optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3)
            scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize, configer.gamma)
            logpath = os.path.join(configer.logspath, configer.modelname) + '{}chs'.format(chs)
            if not os.path.exists(logpath): os.makedirs(logpath)
            logger = SummaryWriter(logpath)

            ## initialize
            acc_train = 0.
            acc_valid = 0.
            loss_train = float('inf')
            loss_valid = float('inf')
            loss_valid_last = float('inf')


            ## start training
            for i_epoch in range(configer.n_epoch):

                if configer.cuda and is_available(): empty_cache()
                scheduler.step(i_epoch)
                acc_train = []; acc_valid = []
                loss_train = []; loss_valid = []

                model.train()
                for i_batch, (X, y) in enumerate(trainloader):

                    X = torch.from_numpy(decomposer.transform(X.numpy()))
                    
                    # get batch
                    X = Variable(X.float()); y = Variable(y)
                    if configer.cuda and is_available():
                        X = X.cuda(); y = y.cuda()

                    # forward
                    y_pred_prob = model(X)
                    loss_i = loss(y_pred_prob, y)
                    acc_i  = accuracy(y_pred_prob, y)

                    # backward
                    optimizer.zero_grad()
                    loss_i.backward() 
                    optimizer.step()

                    loss_train += [loss_i.detach().cpu().numpy()]
                    acc_train  += [acc_i.cpu().numpy()]
                
                model.eval()
                for i_batch, (X, y) in enumerate(validloader):

                    X = torch.from_numpy(decomposer.transform(X.numpy()))
                    
                    # get batch
                    X = Variable(X.float()); y = Variable(y)
                    if configer.cuda and is_available():
                        X = X.cuda(); y = y.cuda()

                    # forward
                    y_pred_prob = model(X)
                    loss_i = loss(y_pred_prob, y)
                    acc_i  = accuracy(y_pred_prob, y)

                    loss_valid += [loss_i.detach().cpu().numpy()]
                    acc_valid  += [acc_i.cpu().numpy()]

                loss_train = np.mean(np.array(loss_train))
                acc_train  = np.mean(np.array(acc_train))
                loss_valid = np.mean(np.array(loss_valid))
                acc_valid  = np.mean(np.array(acc_valid))
                
                logger.add_scalars('accuracy', {'train': acc_train,  'valid': acc_valid},  i_epoch)
                logger.add_scalars('logloss',  {'train': loss_train, 'valid': loss_valid}, i_epoch)
                logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch)

                if loss_valid_last > loss_valid:

                    loss_valid_last = loss_valid
                    torch.save(model, modelpath)



            ## start testing
            model.eval()
            testset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'test', configer.usedChannels)
            testloader = DataLoader(testset, configer.batchsize, shuffle=False)
            loss_test = []
            acc_test  = []
            output = None
            for i_batch, (X, y) in enumerate(testloader):

                X = torch.from_numpy(decomposer.transform(X.numpy()))

                # get batch
                X = Variable(X.float()); y = Variable(y)
                if configer.cuda and is_available():
                    X = X.cuda(); y = y.cuda()
                # forward
                y_pred_prob = model(X)
                loss_i = loss(y_pred_prob, y)
                acc_i  = accuracy(y_pred_prob, y)
                # log
                loss_test += [loss_i.detach().cpu().numpy()]
                acc_test  += [acc_i.cpu().numpy()]

                # save output
                if output is None:
                    output = y_pred_prob.detach().cpu().numpy()
                else:
                    output = np.concatenate([output, y_pred_prob.detach().cpu().numpy()], axis=0)

            # print('------------------------------------------------------------------------------------------------------------------')

            loss_test = np.mean(np.array(loss_test))
            acc_test  = np.mean(np.array(acc_test))
            print_log = "{} || test | acc: {:2.2%}, loss: {:4.4f}".\
                    format(getTime(), acc_test, loss_test)
            print(print_log)
            with open(os.path.join(logpath, 'test_log.txt'), 'w') as  f:
                f.write(print_log + '\n')
            np.save(os.path.join(logpath, 'test_out.npy'), output)
def main_finetune_channels():

    # 波段选择依据
    # 最优的波段排序: 
    #       [850, 870, 930, 730, 790, 910, 770, 750, 670, 950, 990, 830, 890, 810, 970, 690, 710, 650, 590, 570, 630, 610, 550]
    # 依次增加一个波段, 前一个模型进行微调

    CHANNEL_SORT = [850, 870, 930, 730, 790, 910, 770, 750, 670, 950, 990, 830, 890, 810, 970, 690, 710, 650, 590, 570, 630, 610, 550]
    
    for splitidx in range(4, 5):
        usedChannelsList = [CHANNEL_SORT[:i+1] for i in range(23)]

        # for i_usedChannels in range(len(usedChannelsList)):
        for i_usedChannels in [4, 6]:

            usedChannels = usedChannelsList[i_usedChannels]

            print(getTime(), splitidx, len(usedChannels), '...')

            configer = EasyDict()

            configer.dsize = (64, 64)
            configer.datatype = 'Multi'
            configer.n_epoch   = 300
            configer.lrbase = 0.001

            configer.n_channel = 23
            configer.n_class = 63
            configer.batchsize = 32
            configer.stepsize = 250
            configer.gamma = 0.2
            configer.cuda = True

            configer.splitmode = 'split_{}x{}_{}'.format(configer.dsize[0], configer.dsize[1], splitidx)
            configer.modelbase = 'recognize_mobilenet'

            configer.usedChannels = usedChannels
            configer.n_usedChannels = len(configer.usedChannels)
            configer.modelname = '{}_{}_{}_finetune'.\
                            format(configer.modelbase, configer.splitmode, 
                                    '_'.join(list(map(str, configer.usedChannels))))


            configer.datapath = '/home/louishsu/Work/Workspace/ECUST2019_{}x{}'.\
                                            format(configer.dsize[0], configer.dsize[1])
            configer.logspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/logs/{}_{}_{}subjects_logs'.\
                                            format(configer.modelbase, configer.splitmode, configer.n_class)
            configer.mdlspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/{}_{}_{}subjects_models'.\
                                            format(configer.modelbase, configer.splitmode, configer.n_class)


            ## datasets
            trainset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'train', configer.usedChannels)
            validset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'valid', configer.usedChannels)
            trainloader = DataLoader(trainset, configer.batchsize, shuffle=True)
            validloader = DataLoader(validset, configer.batchsize, shuffle=False)


            ## ============================================================================================
            ## model
            modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl'
            modeldir  = '/'.join(modelpath.split('/')[:-1])
            if not os.path.exists(modeldir): os.makedirs(modeldir)
            
            if i_usedChannels == 0:
                model = modeldict[configer.modelbase](configer.n_usedChannels, configer.n_class, configer.dsize[0])
                params = model.parameters()
                torch.save(model, modelpath)
            else:
                modelpath_pretrain = os.path.join(
                    modeldir, '{}_{}_{}_finetune.pkl'.format(configer.modelbase, configer.splitmode, 
                                                '_'.join(list(map(str, usedChannelsList[i_usedChannels-1])))))
                model = torch.load(modelpath_pretrain)
                model.features[0] = nn.Conv2d(len(usedChannels), 64, 3, stride=1, padding=1)
                params = [
                    {'params': model.features[1:].parameters(), 'lr': configer.lrbase*0.01, },
                    {'params': model.features[0].parameters(),}
                ]
                torch.save(model, modelpath)
            if configer.cuda and is_available(): model.cuda()
            ## ============================================================================================


            ## optimizer
            optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3)
            
            ## loss
            loss = nn.CrossEntropyLoss()

            ## learning rate scheduler
            scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize, configer.gamma)
            
            ## log
            logpath = os.path.join(configer.logspath, configer.modelname)
            if not os.path.exists(logpath): os.makedirs(logpath)
            logger = SummaryWriter(logpath)

            ## initialize
            acc_train = 0.
            acc_valid = 0.
            loss_train = float('inf')
            loss_valid = float('inf')
            loss_valid_last = float('inf')


            ## start training
            for i_epoch in range(configer.n_epoch):

                if configer.cuda and is_available(): empty_cache()
                scheduler.step(i_epoch)
                acc_train = []; acc_valid = []
                loss_train = []; loss_valid = []


                model.train()
                for i_batch, (X, y) in enumerate(trainloader):
                    
                    # get batch
                    X = Variable(X.float()); y = Variable(y)
                    if configer.cuda and is_available():
                        X = X.cuda(); y = y.cuda()

                    # forward
                    y_pred_prob = model(X)
                    loss_i = loss(y_pred_prob, y)
                    acc_i  = accuracy(y_pred_prob, y)

                    # backward
                    optimizer.zero_grad()
                    loss_i.backward() 
                    optimizer.step()

                    loss_train += [loss_i.detach().cpu().numpy()]
                    acc_train  += [acc_i.cpu().numpy()]
                
                model.eval()
                for i_batch, (X, y) in enumerate(validloader):
                    
                    # get batch
                    X = Variable(X.float()); y = Variable(y)
                    if configer.cuda and is_available():
                        X = X.cuda(); y = y.cuda()

                    # forward
                    y_pred_prob = model(X)
                    loss_i = loss(y_pred_prob, y)
                    acc_i  = accuracy(y_pred_prob, y)

                    loss_valid += [loss_i.detach().cpu().numpy()]
                    acc_valid  += [acc_i.cpu().numpy()]

                loss_train = np.mean(np.array(loss_train))
                acc_train  = np.mean(np.array(acc_train))
                loss_valid = np.mean(np.array(loss_valid))
                acc_valid  = np.mean(np.array(acc_valid))
                
                logger.add_scalars('accuracy', {'train': acc_train,  'valid': acc_valid},  i_epoch)
                logger.add_scalars('logloss',  {'train': loss_train, 'valid': loss_valid}, i_epoch)
                logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch)

                if loss_valid_last > loss_valid:

                    loss_valid_last = loss_valid
                    torch.save(model, modelpath)


            test(configer)
Esempio n. 6
0
def train(configer):
    """
    Update:
        2019.04.24: 固定权值
    """

    ## datasets
    trainset = RecognizeDataset(configer.datapath, configer.datatype,
                                configer.splitmode, 'train',
                                configer.usedChannels)
    validset = RecognizeDataset(configer.datapath, configer.datatype,
                                configer.splitmode, 'valid',
                                configer.usedChannels)
    trainloader = DataLoader(trainset, configer.batchsize, shuffle=True)
    validloader = DataLoader(validset, configer.batchsize, shuffle=False)

    ## model: pre-initialized
    modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl'
    modeldir = '/'.join(modelpath.split('/')[:-1])
    if not os.path.exists(modeldir): os.makedirs(modeldir)
    preInitdir = os.path.join('/'.join(configer.mdlspath.split('/')[:-1]),
                              "preinit")
    if not os.path.exists(preInitdir): os.makedirs(preInitdir)
    preInitmodelpath = os.path.join(preInitdir, configer.modelbase + '.pkl')

    model = modeldict[configer.modelbase](configer.n_usedChannels,
                                          configer.n_class, configer.dsize[0])
    if not os.path.exists(preInitmodelpath):
        model_state = model.state_dict()
        torch.save(model_state, preInitmodelpath)
    else:
        preinit_state = torch.load(preInitmodelpath)
        model_state = model.state_dict()
        toload_state = {k: v for k, v in preinit_state.items() \
                    if preinit_state[k].shape==model_state[k].shape}
        model_state.update(toload_state)
        model.load_state_dict(model_state)

    if configer.cuda and is_available(): model.cuda()

    ## loss
    loss = nn.CrossEntropyLoss()

    ## optimizer
    params = model.parameters()
    optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3)

    ## learning rate scheduler
    scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize,
                                    configer.gamma)

    ## log
    logpath = os.path.join(configer.logspath, configer.modelname)
    if not os.path.exists(logpath): os.makedirs(logpath)
    logger = SummaryWriter(logpath)

    ## initialize
    elapsed_time = 0
    total_time = 0
    start_time = 0
    acc_train = 0.
    acc_valid = 0.
    loss_train = float('inf')
    loss_valid = float('inf')
    loss_valid_last = float('inf')

    ## start training
    for i_epoch in range(configer.n_epoch):

        if configer.cuda and is_available(): empty_cache()
        scheduler.step(i_epoch)
        acc_train = []
        acc_valid = []
        loss_train = []
        loss_valid = []

        model.train()
        start_time = time.time()
        for i_batch, (X, y) in enumerate(trainloader):

            # get batch
            X = Variable(X.float())
            y = Variable(y)
            if configer.cuda and is_available():
                X = X.cuda()
                y = y.cuda()

            # forward
            y_pred_prob = model(X)
            loss_i = loss(y_pred_prob, y)
            acc_i = accuracy(y_pred_prob, y)

            # backward
            optimizer.zero_grad()
            loss_i.backward()
            optimizer.step()

            # time
            duration_time = time.time() - start_time
            start_time = time.time()
            elapsed_time += duration_time
            total_time = duration_time * configer.n_epoch * len(
                trainset) // configer.batchsize

            # log
            # print_log = "{} || Elapsed: {:.4f}h | Left: {:.4f}h | FPS: {:4.2f} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || lr: {:.6f} | accuracy: {:2.2%}, loss: {:4.4f}".\
            #         format(getTime(), elapsed_time/3600, (total_time - elapsed_time)/3600, configer.batchsize / duration_time,
            #                 i_epoch, configer.n_epoch, i_batch, len(trainset) // configer.batchsize,
            #                 scheduler.get_lr()[-1], acc_i, loss_i)
            # print(print_log)

            loss_train += [loss_i.detach().cpu().numpy()]
            acc_train += [acc_i.cpu().numpy()]

        # print('------------------------------------------------------------------------------------------------------------------')

        model.eval()
        for i_batch, (X, y) in enumerate(validloader):

            # get batch
            X = Variable(X.float())
            y = Variable(y)
            if configer.cuda and is_available():
                X = X.cuda()
                y = y.cuda()

            # forward
            y_pred_prob = model(X)
            loss_i = loss(y_pred_prob, y)
            acc_i = accuracy(y_pred_prob, y)

            # log
            # print_log = "{} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || accuracy: {:2.2%}, loss: {:4.4f}".\
            #         format(getTime(), i_epoch, configer.n_epoch, i_batch, len(validset) // configer.batchsize, acc_i, loss_i)
            # print(print_log)

            loss_valid += [loss_i.detach().cpu().numpy()]
            acc_valid += [acc_i.cpu().numpy()]

        # print('------------------------------------------------------------------------------------------------------------------')

        loss_train = np.mean(np.array(loss_train))
        acc_train = np.mean(np.array(acc_train))
        loss_valid = np.mean(np.array(loss_valid))
        acc_valid = np.mean(np.array(acc_valid))
        # print_log = "{} || Epoch: [{:3d}]/[{:3d}] || lr: {:.6f} || train | acc: {:2.2%}, loss: {:4.4f} || valid | acc: {:2.2%}, loss: {:4.4f}".\
        #         format(getTime(), i_epoch, configer.n_epoch, scheduler.get_lr()[-1], acc_train, loss_train, acc_valid, loss_valid)
        # print(print_log)

        logger.add_scalars('accuracy', {
            'train': acc_train,
            'valid': acc_valid
        }, i_epoch)
        logger.add_scalars('logloss', {
            'train': loss_train,
            'valid': loss_valid
        }, i_epoch)
        logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch)

        # print('------------------------------------------------------------------------------------------------------------------')

        if loss_valid_last > loss_valid:

            loss_valid_last = loss_valid
            torch.save(model, modelpath)
Esempio n. 7
0
def main_3_5(make_table_figure=False):

    datatypes   = ["Multi", "RGB"]
    splitcounts = [i for i in range(1, 11)]
    H = len(splitcounts)

    loss = nn.CrossEntropyLoss()

    if make_table_figure:

        illum_types = ["illum1", "illum2", "illum3", "normal"]
        positions   = [i + 1 for i in range(7)]         # 共7个拍摄角度,编号 1 ~ 7
        glass_types = [1, 5, 6]                         # `1`表示无眼镜,`5`表示戴眼镜,`6`表示太阳镜

        for datatype in datatypes:

            print("Generating tables and figures [{}]...".format(datatype))
        
            usedChannels = [i for i in range(1, 26)] \
                        if datatype == "Multi" else "RGB"

            data_acc_illum_types  = np.zeros(shape=(H, len(illum_types)))
            data_loss_illum_types = np.zeros(shape=(H, len(illum_types)))
            data_acc_positions    = np.zeros(shape=(H, len(positions  )))
            data_loss_positions   = np.zeros(shape=(H, len(positions  )))
            data_acc_glass_types  = np.zeros(shape=(H, len(glass_types)))
            data_loss_glass_types = np.zeros(shape=(H, len(glass_types)))
            
            for i in range(len(splitcounts)):
                splitcount = splitcounts[i]

                ## 获取configer
                configer = get_configer(datatype=datatype, 
                            splitcount=splitcount, usedChannels=usedChannels)

                ## 读取保存的测试结果
                logpath = os.path.join(configer.logspath, configer.modelname)
                print(logpath)
                y_pred_prob = np.load(os.path.join(logpath, 'test_out.npy'))

                ## 读取文件列表
                testset = RecognizeDataset(configer.datapath, configer.datatype, 
                        configer.splitmode, 'test', configer.usedChannels)
                y_true = np.array(list(map(lambda x: x[1], testset.samplelist)))
                test_list  = testset.filelist
                test_attr_list = list(map(lambda  x: ImageAttributes(x), test_list))
                del testset

                ## 分析光照
                for j in range(len(illum_types)):
                    illum_type = illum_types[j]

                    # FIXME:
                    # index = list(map(lambda x: x.illum_type==illum_type, test_attr_list))
                    index = list(map(lambda x: x.illum_type==illum_type and \
                                            #    x.glass_type==1 and \
                                               x.position==4, 
                                               test_attr_list))
                    index = np.array(index, dtype=np.bool)

                    y_pred_prob_sub = torch.tensor(y_pred_prob[index])
                    y_true_sub      = torch.tensor(y_true[index])
                    data_acc_illum_types [i, j] = accuracy(y_pred_prob_sub, y_true_sub).cpu().numpy()
                    data_loss_illum_types[i, j] = loss(y_pred_prob_sub, y_true_sub).cpu().numpy()

                ## 分析位置
                for j in range(len(positions)):
                    position = positions[j]

                    # FIXME:
                    # index = list(map(lambda x: x.position==position, test_attr_list))
                    index = list(map(lambda x: x.position==position and \
                                               x.glass_type==1, test_attr_list))
                    index = np.array(index, dtype=np.bool)

                    y_pred_prob_sub = torch.tensor(y_pred_prob[index])
                    y_true_sub      = torch.tensor(y_true[index])
                    data_acc_positions [i, j] = accuracy(y_pred_prob_sub, y_true_sub).cpu().numpy()
                    data_loss_positions[i, j] = loss(y_pred_prob_sub, y_true_sub).cpu().numpy()

                ## 分析眼镜
                for j in range(len(glass_types)):
                    glass_type = glass_types[j]

                    index = list(map(lambda x: x.glass_type==glass_type, test_attr_list))
                    index = np.array(index, dtype=np.bool)

                    y_pred_prob_sub = torch.tensor(y_pred_prob[index])
                    y_true_sub      = torch.tensor(y_true[index])
                    data_acc_glass_types [i, j] = accuracy(y_pred_prob_sub, y_true_sub).cpu().numpy()
                    data_loss_glass_types[i, j] = loss(y_pred_prob_sub, y_true_sub).cpu().numpy()

            ## 绘制表格
            rows_name = [str(i) for i in splitcounts] + ['average']
            
            # =====================================================================================================
            head_name = "count/光照"
            cols_name = illum_types
            # -----------------------------------------------------------------------------------------------------
            data_acc_illum_types  = np.r_[data_acc_illum_types,  np.mean(data_acc_illum_types, axis=0).reshape(1, -1)]
            data_loss_illum_types = np.r_[data_loss_illum_types, np.mean(data_loss_illum_types, axis=0).reshape(1, -1)]
            # -----------------------------------------------------------------------------------------------------
            table_acc_illum_types  = gen_markdown_table_2d(head_name, rows_name, cols_name, data_acc_illum_types )
            table_loss_illum_types = gen_markdown_table_2d(head_name, rows_name, cols_name, data_loss_illum_types)
            with open("images/3_5_<table>_[{}]_[illum_types].txt".format(datatype), 'w') as f:
                f.write("\n\nacc\n")
                f.write(table_acc_illum_types)
                f.write("\n\nloss\n")
                f.write(table_loss_illum_types)
            # -----------------------------------------------------------------------------------------------------
            plt.figure()
            plt.subplot(121); plt.title("acc")
            avg_acc  = data_acc_illum_types[-1]
            plt.bar(np.arange(avg_acc.shape[0]),  avg_acc )
            plt.subplot(122); plt.title("loss")
            avg_loss = data_loss_illum_types[-1]
            plt.bar(np.arange(avg_loss.shape[0]), avg_loss)
            plt.savefig("images/3_5_<figure>_[{}]_[illum_types].png".format(datatype))

            # =====================================================================================================
            head_name = "count/位置"
            cols_name = list(map(str, positions))
            # -----------------------------------------------------------------------------------------------------
            data_acc_positions  = np.r_[data_acc_positions,  np.mean(data_acc_positions, axis=0).reshape(1, -1)]
            data_loss_positions = np.r_[data_loss_positions, np.mean(data_loss_positions, axis=0).reshape(1, -1)]
            # -----------------------------------------------------------------------------------------------------
            table_acc_positions  = gen_markdown_table_2d(head_name, rows_name, cols_name, data_acc_positions )
            table_loss_positions = gen_markdown_table_2d(head_name, rows_name, cols_name, data_loss_positions)
            with open("images/3_5_<table>_[{}]_[positions].md".format(datatype), 'w') as f:
                f.write("\n\nacc\n")
                f.write(table_acc_positions)
                f.write("\n\nloss\n")
                f.write(table_loss_positions)
            # -----------------------------------------------------------------------------------------------------
            plt.figure()
            plt.subplot(121); plt.title("acc")
            avg_acc  = data_acc_positions[-1]
            plt.bar(np.arange(avg_acc.shape[0]),  avg_acc )
            plt.subplot(122); plt.title("loss")
            avg_loss = data_loss_positions[-1]
            plt.bar(np.arange(avg_loss.shape[0]), avg_loss)
            plt.savefig("images/3_5_<figure>_[{}]_[positions].png".format(datatype))

            # =====================================================================================================
            head_name = "count/眼镜"
            cols_name = list(map(str, glass_types))
            # -----------------------------------------------------------------------------------------------------
            data_acc_glass_types  = np.r_[data_acc_glass_types,  np.mean(data_acc_glass_types, axis=0).reshape(1, -1)]
            data_loss_glass_types = np.r_[data_loss_glass_types, np.mean(data_loss_glass_types, axis=0).reshape(1, -1)]
            # -----------------------------------------------------------------------------------------------------
            table_acc_glass_types  = gen_markdown_table_2d(head_name, rows_name, cols_name, data_acc_glass_types )
            table_loss_glass_types = gen_markdown_table_2d(head_name, rows_name, cols_name, data_loss_glass_types)
            with open("images/3_5_<table>_[{}]_[glass_types].txt".format(datatype), 'w') as f:
                f.write("\n\nacc\n")
                f.write(table_acc_glass_types)
                f.write("\n\nloss\n")
                f.write(table_loss_glass_types)
            # -----------------------------------------------------------------------------------------------------
            plt.figure()
            plt.subplot(121); plt.title("acc")
            avg_acc  = data_acc_glass_types[-1]
            plt.bar(np.arange(avg_acc.shape[0]),  avg_acc )
            plt.subplot(122); plt.title("loss")
            avg_loss = data_loss_glass_types[-1]
            plt.bar(np.arange(avg_loss.shape[0]), avg_loss)
            plt.savefig("images/3_5_<figure>_[{}]_[glass_types].png".format(datatype))

        return

    start_time = time.time(); elapsed_time = 0

    for datatype in datatypes:
        
        usedChannels = [i for i in range(1, 26)] \
                    if datatype == "Multi" else "RGB"

        data_acc  = np.zeros(H)
        data_loss = np.zeros(H)
        
        for i in range(len(splitcounts)):
            splitcount = splitcounts[i]

            configer = get_configer(datatype=datatype, 
                        splitcount=splitcount, usedChannels=usedChannels)

            elapsed_time += time.time() - start_time
            start_time    = time.time()
            print("Main 3.2 [{}] [{}] {}... Elaped >>> {} min".\
                        format(configer.datatype, configer.splitmode, usedChannels, elapsed_time/60))

            logpath = os.path.join(configer.logspath, configer.modelname)
            print(logpath)
            if os.path.exists(logpath):
                with open(os.path.join(logpath, 'test_log.txt'), 'r') as f:
                    test_log = f.readlines()[0]
                    data_acc[i], data_loss[i] = parse_log(test_log)
                    print(test_log)
            else:
                train(configer)
                data_acc[i], data_loss[i] = test(configer)
            print("-------------------------------------------------")
        
        ## 保存数据
        avg_acc  = np.mean(data_acc,  axis=0)
        avg_loss = np.mean(data_loss, axis=0)

        table_data_acc  = np.r_[data_acc,  avg_acc ]
        table_data_loss = np.r_[data_loss, avg_loss]
        table_data      = np.r_[table_data_acc.reshape(1, -1), 
                                table_data_loss.reshape(1, -1)]

        np.savetxt("images/3_5_<data>_[{}].txt".format(datatype), table_data)
Esempio n. 8
0
def train(configer):

    ## datasets
    trainset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'train', configer.usedChannels)
    validset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'valid', configer.usedChannels)
    trainloader = DataLoader(trainset, configer.batchsize, shuffle=True)
    validloader = DataLoader(validset, configer.batchsize, shuffle=False)

    ## model
    modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl'
    modeldir  = '/'.join(modelpath.split('/')[:-1])
    model = modeldict[configer.modelbase](configer.n_usedChannels, configer.n_class, configer.dsize[0])
    if not os.path.exists(modeldir): 
        os.makedirs(modeldir)
        torch.save(model.state_dict(), modelpath)
    else:
        model.load_state_dict(torch.load())
    
    model=torch.load("init.pkl")
    #if configer.cuda and is_available(): model.cuda()
    
    #ArcMargin = ArcMarginProduct(128,configer.n_class)

    ## loss
    loss = nn.CrossEntropyLoss() 

    ## optimizer
    params = model.parameters()
    #optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3)
    optimizer = optim.Adam(params, configer.lrbase)

    ## learning rate scheduler
    scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize, configer.gamma)
    
    ## log
    logpath = os.path.join(configer.logspath, configer.modelname)
    if not os.path.exists(logpath): os.makedirs(logpath)
    logger = SummaryWriter(logpath)

    ## initialize
    elapsed_time = 0; total_time = 0; start_time = 0
    acc_train = 0.
    acc_valid = 0.
    loss_train = float('inf')
    loss_valid = float('inf')
    loss_valid_last = float('inf')


    ## start training
    for i_epoch in range(configer.n_epoch):

        if configer.cuda and is_available(): empty_cache()
        scheduler.step(i_epoch)
        acc_train = []; acc_valid = []
        loss_train = []; loss_valid = []


        model.train()
        start_time = time.time()
        for i_batch, (X, y) in enumerate(trainloader):
            
            # get batch
            X = Variable(X.float()); y = Variable(y)
            if configer.cuda and is_available():
                X = X.cuda(); y = y.cuda()

            # forward
            if configer.modelbase == 'recognize_mobilefacenet':
                raw_logits = model(X)
                y_pred_prob = ArcMargin(raw_logits, y)
            else:
                y_pred_prob = model(X)
            #y_pred_prob = model(X)

            loss_i = loss(y_pred_prob, y)
            acc_i  = accuracy(y_pred_prob, y)

            # backward
            optimizer.zero_grad()
            loss_i.backward() 
            optimizer.step()

            # time
            duration_time = time.time() - start_time
            start_time    = time.time()
            elapsed_time += duration_time
            total_time    = duration_time * configer.n_epoch * len(trainset) // configer.batchsize

            # log
            print_log = "{} || Elapsed: {:.4f}h | Left: {:.4f}h | FPS: {:4.2f} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || lr: {:.6f} | accuracy: {:2.2%}, loss: {:4.4f}".\
                    format(getTime(), elapsed_time/3600, (total_time - elapsed_time)/3600, configer.batchsize / duration_time,
                            i_epoch, configer.n_epoch, i_batch, len(trainset) // configer.batchsize, 
                            scheduler.get_lr()[-1], acc_i, loss_i)
            ##print(print_log)

            loss_train += [loss_i.detach().cpu().numpy()]
            acc_train  += [acc_i.cpu().numpy()]
        
        print('------------------------------------------------------------------------------------------------------------------')


        model.eval()
        for i_batch, (X, y) in enumerate(validloader):
            
            # get batch
            X = Variable(X.float()); y = Variable(y)
            if configer.cuda and is_available():
                X = X.cuda(); y = y.cuda()

            # # forward
            if configer.modelbase == 'recognize_mobilefacenet':
                raw_logits = model(X)
                y_pred_prob = ArcMargin(raw_logits, y)
            else:
                y_pred_prob = model(X)
            #y_pred_prob = model(X)
            
            loss_i = loss(y_pred_prob, y)
            acc_i  = accuracy(y_pred_prob, y)

            # log
            print_log = "{} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || accuracy: {:2.2%}, loss: {:4.4f}".\
                    format(getTime(), i_epoch, configer.n_epoch, i_batch, len(validset) // configer.batchsize, acc_i, loss_i)
            ##print(print_log)

            loss_valid += [loss_i.detach().cpu().numpy()]
            acc_valid  += [acc_i.cpu().numpy()]

        print('------------------------------------------------------------------------------------------------------------------')


        loss_train = np.mean(np.array(loss_train))
        acc_train  = np.mean(np.array(acc_train))
        loss_valid = np.mean(np.array(loss_valid))
        acc_valid  = np.mean(np.array(acc_valid))
        print_log = "{} || Epoch: [{:3d}]/[{:3d}] || lr: {:.6f} || train | acc: {:2.2%}, loss: {:4.4f} || valid | acc: {:2.2%}, loss: {:4.4f}".\
                format(getTime(), i_epoch, configer.n_epoch, scheduler.get_lr()[-1], acc_train, loss_train, acc_valid, loss_valid)
        print(print_log)
        
        logger.add_scalars('accuracy', {'train': acc_train,  'valid': acc_valid},  i_epoch)
        logger.add_scalars('logloss',  {'train': loss_train, 'valid': loss_valid}, i_epoch)
        logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch)

        print('------------------------------------------------------------------------------------------------------------------')

        if loss_valid_last > loss_valid:

            loss_valid_last = loss_valid
            torch.save(model, modelpath)
            print_log = "{} || Epoch: [{:3d}]/[{:3d}] || Saved as {}".\
                    format(getTime(), i_epoch, configer.n_epoch, modelpath)
            print(print_log)

        print('==================================================================================================================')