def main():
    global args

    args = parser.parse_args()

    use_cuda = cuda_model.ifUseCuda(args.gpu_id, args.multiGpu)

    model = PointerNet(args.input_size, args.hidden_size, args.nlayers,
                       args.dropout, args.bidir)
    if args.resume is not None:
        assert os.path.isfile(
            args.resume), 'Error: no checkpoint directory found!'
        checkpoint = torch.load(args.resume,
                                map_location=lambda storage, loc: storage)
        args.start_epoch = checkpoint['epoch']
        model.load_state_dict(checkpoint['state_dict'], strict=False)
        print("=> loading checkpoint '{:s}', epoch: {:d}".format(
            args.resume, args.start_epoch))

    model = cuda_model.convertModel2Cuda(model,
                                         gpu_id=args.gpu_id,
                                         multiGpu=args.multiGpu)

    train_dataset = LocalDataLoader.Dataset(dataset_name='SumMe',
                                            split='train',
                                            clip_size=args.clip_size,
                                            sample_rates=[1, 5, 10])
    val_dataset = LocalDataLoader.Dataset(dataset_name='SumMe',
                                          split='val',
                                          clip_size=args.clip_size)

    train_dataloader = DataLoader(train_dataset,
                                  batch_size=args.batch_size,
                                  shuffle=True,
                                  num_workers=4)

    val_dataloader = DataLoader(val_dataset,
                                batch_size=args.batch_size,
                                shuffle=True,
                                num_workers=4)

    NLL = torch.nn.NLLLoss()
    model_optim = optim.Adam(filter(lambda p: p.requires_grad,
                                    model.parameters()),
                             lr=args.lr)

    best_status = {
        'train_accuracy': 0,
        'val_accuracy': 0,
        'train_loss': float('inf'),
        'val_loss': float('inf')
    }
    isBest_status = {
        'train_accuracy': 0,
        'val_accuracy': 0,
        'train_loss': 0,
        'val_loss': 0
    }
    for epoch in range(args.start_epoch, args.nof_epoch):
        total_losses = AverageMeter()
        loc_losses = AverageMeter()
        cls_losses = AverageMeter()
        Accuracy_Top1 = AverageMeter()
        Accuracy_Top3 = AverageMeter()
        F1_Top1 = AverageMeter()
        F1_Top3 = AverageMeter()

        model.train()
        pbar = progressbar.ProgressBar(max_value=len(train_dataloader))
        for i_batch, sample_batched in enumerate(train_dataloader):
            pbar.update(i_batch)

            feature_batch = Variable(sample_batched[0])
            gt_index_batch = Variable(sample_batched[1])

            if use_cuda:
                feature_batch = feature_batch.cuda()
                gt_index_batch = gt_index_batch.cuda()
            index_vector, segment_score = model(feature_batch)

            index_vector = index_vector.contiguous().view(-1, args.clip_size)
            gt_index_batch = gt_index_batch.view(-1)

            accuracy = Metrics.accuracy_topN(index_vector.data,
                                             gt_index_batch.data,
                                             topk=[1, 3])
            F1 = Metrics.accuracy_F1(index_vector.data,
                                     gt_index_batch.data,
                                     topk=[1, 3])

            loc_loss = NLL(torch.log(index_vector), gt_index_batch)

            total_loss = loc_loss

            model_optim.zero_grad()
            total_loss.backward()
            model_optim.step()

            total_losses.update(total_loss.data[0], feature_batch.size(0))
            loc_losses.update(loc_loss.data[0], feature_batch.size(0))
            Accuracy_Top1.update(accuracy[0][0], feature_batch.size(0))
            Accuracy_Top3.update(accuracy[1][0], feature_batch.size(0))
            F1_Top1.update(F1[0], feature_batch.size(0))
            F1_Top3.update(F1[1], feature_batch.size(0))

        print(
            "Train -- Epoch :{:06d}, LR: {:.6f},\tloc-loss={:.4f}\ttop1={:.4f}\ttop3={:.4f}\tF1_1={:.4f}\tF1_3={:.4f}"
            .format(epoch, model_optim.param_groups[0]['lr'], loc_losses.avg,
                    Accuracy_Top1.avg, Accuracy_Top3.avg, F1_Top1.avg,
                    F1_Top3.avg))
        if best_status['train_loss'] > total_losses.avg:
            best_status['train_loss'] = total_losses.avg
            isBest_status['train_loss'] = 1
        if best_status['train_accuracy'] < Accuracy_Top1.avg:
            best_status['train_accuracy'] = Accuracy_Top1.avg
            isBest_status['train_accuracy'] = 1

        model.eval()

        total_losses.reset()
        loc_losses.reset()
        cls_losses.reset()
        Accuracy_Top1.reset()
        Accuracy_Top3.reset()
        F1_Top1.reset()
        F1_Top3.reset()

        pbar = progressbar.ProgressBar(max_value=len(val_dataloader))
        for i_batch, sample_batched in enumerate(val_dataloader):
            pbar.update(i_batch)

            feature_batch = Variable(sample_batched[0])
            gt_index_batch = Variable(sample_batched[1])

            if use_cuda:
                feature_batch = feature_batch.cuda()
                gt_index_batch = gt_index_batch.cuda()

            index_vector, segment_score = model(feature_batch)

            index_vector = index_vector.contiguous().view(-1, args.clip_size)
            gt_index_batch = gt_index_batch.view(-1)
            accuracy = Metrics.accuracy_topN(index_vector.data,
                                             gt_index_batch.data,
                                             topk=[1, 3])
            F1 = Metrics.accuracy_F1(index_vector.data,
                                     gt_index_batch.data,
                                     topk=[1, 3])
            loc_loss = NLL(torch.log(index_vector), gt_index_batch)

            total_loss = loc_loss

            loc_losses.update(loc_loss.data[0], feature_batch.size(0))

            total_losses.update(total_loss.data[0], feature_batch.size(0))
            Accuracy_Top1.update(accuracy[0][0], feature_batch.size(0))
            Accuracy_Top3.update(accuracy[1][0], feature_batch.size(0))
            F1_Top1.update(F1[0], feature_batch.size(0))
            F1_Top3.update(F1[1], feature_batch.size(0))

        print(
            "Test -- Epoch :{:06d}, LR: {:.6f},\tloc-loss={:.4f}\ttop1={:.4f}\ttop3={:.4f}\tF1_1={:.4f}\tF1_3={:.4f}"
            .format(epoch, model_optim.param_groups[0]['lr'], loc_losses.avg,
                    Accuracy_Top1.avg, Accuracy_Top3.avg, F1_Top1.avg,
                    F1_Top3.avg))

        # val_F1_score = val_evaluator.EvaluateTop1(model, use_cuda)
        # print "Val F1 Score: {:f}".format(val_F1_score)
        if best_status['val_loss'] > total_losses.avg:
            best_status['val_loss'] = total_losses.avg
            isBest_status['val_loss'] = 1
        if best_status['val_accuracy'] < Accuracy_Top1.avg:
            best_status['val_accuracy'] = Accuracy_Top1.avg
            isBest_status['val_accuracy'] = 1

        save_checkpoint(
            {
                'epoch': epoch + 1,
                'state_dict': model.state_dict(),
                'val_loss': best_status['val_loss'],
                'val_accuracy': best_status['val_accuracy'],
                'train_loss': best_status['train_loss'],
                'train_accuracy': best_status['train_accuracy']
            },
            isBest_status,
            file_direcotry='vsPtrDep_Localization')

        for item in isBest_status.keys():
            isBest_status[item] = 0
def main():
    global args

    args = parser.parse_args()

    use_cuda = cuda_model.ifUseCuda(args.gpu_id, args.multiGpu)

    model = PointerNet(args.input_size, args.hidden_size, args.nlayers,
                       args.dropout, args.bidir)
    if args.resume is not None:
        assert os.path.isfile(
            args.resume), 'Error: no checkpoint directory found!'
        checkpoint = torch.load(args.resume,
                                map_location=lambda storage, loc: storage)
        args.start_epoch = checkpoint['epoch']
        args.start_epoch = 0
        model.load_state_dict(checkpoint['state_dict'], strict=False)
        print("=> loading checkpoint '{:s}', epoch: {:d}".format(
            args.resume, args.start_epoch))

    model = cuda_model.convertModel2Cuda(model,
                                         gpu_id=args.gpu_id,
                                         multiGpu=args.multiGpu)

    train_dataset = LocalDataLoader.Dataset(dataset_name="SumMe",
                                            split='train',
                                            clip_size=args.clip_size,
                                            output_score=True,
                                            output_rdIdx=True,
                                            sample_rates=[1, 5, 10])
    val_dataset = LocalDataLoader.Dataset(dataset_name="SumMe",
                                          split='val',
                                          clip_size=args.clip_size,
                                          output_score=True,
                                          output_rdIdx=True)

    train_dataloader = DataLoader(train_dataset,
                                  batch_size=args.batch_size,
                                  shuffle=True,
                                  num_workers=4)

    val_dataloader = DataLoader(val_dataset,
                                batch_size=args.batch_size,
                                shuffle=True,
                                num_workers=4)

    model_optim = optim.Adam(filter(lambda p: p.requires_grad,
                                    model.parameters()),
                             lr=args.lr)

    best_status = {
        'train_accuracy': 0,
        'val_accuracy': 0,
        'train_loss': float('inf'),
        'val_loss': float('inf')
    }
    isBest_status = {
        'train_accuracy': 0,
        'val_accuracy': 0,
        'train_loss': 0,
        'val_loss': 0
    }
    for epoch in range(args.start_epoch, args.nof_epoch):

        total_losses = AverageMeter()
        loc_losses = AverageMeter()
        cls_losses = AverageMeter()
        Accuracy_Top1 = AverageMeter()
        Accuracy_Top3 = AverageMeter()
        F1_Top1 = AverageMeter()
        F1_Top3 = AverageMeter()

        model.train()
        pbar = progressbar.ProgressBar(max_value=len(train_dataloader))
        for i_batch, sample_batched in enumerate(train_dataloader):
            pbar.update(i_batch)

            feature_batch = Variable(sample_batched[0])
            gt_index_batch = Variable(sample_batched[1])
            score_batch = Variable(sample_batched[2])
            rd_index_batch = Variable(sample_batched[3])

            if use_cuda:
                feature_batch = feature_batch.cuda()
                rd_index_batch = rd_index_batch.cuda()
                gt_index_batch = gt_index_batch.cuda()
                score_batch = score_batch.cuda()

            rd_starting_index_batch = rd_index_batch[:, 0]
            rd_ending_index_batch = rd_index_batch[:, 1]
            _, segment_score = model(feature_batch,
                                     starting_idx=rd_starting_index_batch,
                                     ending_idx=rd_ending_index_batch)

            overlap = loss_transforms.IoU_Overlaps(rd_index_batch.data,
                                                   gt_index_batch.data)

            overlap = Variable(overlap, requires_grad=False)
            if use_cuda:
                overlap = overlap.cuda()
            cls_loss = losses.ClsLocLoss_Regression(segment_score,
                                                    score_batch,
                                                    overlap,
                                                    thres=0.5)

            total_loss = cls_loss

            model_optim.zero_grad()
            total_loss.backward()
            model_optim.step()

            total_losses.update(total_loss.data[0], feature_batch.size(0))

        print("Train -- Epoch :{:06d}, LR: {:.6f},\tcls-loss={:.4f}".format(
            epoch, model_optim.param_groups[0]['lr'], total_losses.avg))
        if best_status['train_loss'] > total_losses.avg:
            best_status['train_loss'] = total_losses.avg
            isBest_status['train_loss'] = 1
        if best_status['train_accuracy'] < Accuracy_Top1.avg:
            best_status['train_accuracy'] = Accuracy_Top1.avg
            isBest_status['train_accuracy'] = 1

        model.eval()

        total_losses.reset()
        loc_losses.reset()
        cls_losses.reset()
        Accuracy_Top1.reset()
        Accuracy_Top3.reset()
        F1_Top1.reset()
        F1_Top3.reset()
        pbar = progressbar.ProgressBar(max_value=len(val_dataloader))
        for i_batch, sample_batched in enumerate(val_dataloader):
            pbar.update(i_batch)

            feature_batch = Variable(sample_batched[0])
            gt_index_batch = Variable(sample_batched[1])
            score_batch = Variable(sample_batched[2])
            rd_index_batch = Variable(sample_batched[3])

            if use_cuda:
                feature_batch = feature_batch.cuda()
                rd_index_batch = rd_index_batch.cuda()
                gt_index_batch = gt_index_batch.cuda()
                score_batch = score_batch.cuda()

            rd_starting_index_batch = rd_index_batch[:, 0]
            rd_ending_index_batch = rd_index_batch[:, 1]
            _, segment_score = model(feature_batch,
                                     starting_idx=rd_starting_index_batch,
                                     ending_idx=rd_ending_index_batch)

            overlap = loss_transforms.IoU_Overlaps(rd_index_batch.data,
                                                   gt_index_batch.data)

            overlap = Variable(overlap, requires_grad=False)
            if use_cuda:
                overlap = overlap.cuda()
            cls_loss = losses.ClsLocLoss_Regression(segment_score,
                                                    score_batch,
                                                    overlap,
                                                    thres=0.5)

            total_loss = cls_loss

            # Here adjust the ratio based on loss values...

            total_losses.update(total_loss.data[0], feature_batch.size(0))

        print("Test -- Epoch :{:06d}, LR: {:.6f},\tcls-loss={:.4f}".format(
            epoch,
            model_optim.param_groups[0]['lr'],
            total_losses.avg,
        ))

        # val_F1_score = val_evaluator.EvaluateTop1(model, use_cuda)
        # print "Val F1 Score: {:f}".format(val_F1_score)
        if best_status['val_loss'] > total_losses.avg:
            best_status['val_loss'] = total_losses.avg
            isBest_status['val_loss'] = 1
        if best_status['val_accuracy'] < Accuracy_Top1.avg:
            best_status['val_accuracy'] = Accuracy_Top1.avg
            isBest_status['val_accuracy'] = 1

        save_checkpoint(
            {
                'epoch': epoch + 1,
                'state_dict': model.state_dict(),
                'val_loss': best_status['val_loss'],
                'val_accuracy': best_status['val_accuracy'],
                'train_loss': best_status['train_loss'],
                'train_accuracy': best_status['train_accuracy']
            },
            isBest_status,
            file_direcotry='vsPtrDep_Classification')

        for item in isBest_status.keys():
            isBest_status[item] = 0