Exemple #1
0
def main():
    nclass = 7
    batch_size = 4
    drop_last = True
    train_loader, val_loader = make_dataloader(batch_size=batch_size,
                                               drop_last=drop_last)
    model = DeepLab(num_classes=nclass, output_stride=16, freeze_bn=False)
    model = load_pretrained_model(model)
    evaluator = Evaluator(nclass)
    model = model.cuda()

    model.eval()
    evaluator.reset()

    for i, sample in enumerate(val_loader):
        image, target = sample['image'], sample['label']
        image, target = image.cuda(), target.cuda()
        with torch.no_grad():
            output = model(image)

        pred = output.data.cpu().numpy()
        target = target.cpu().numpy()
        pred = np.argmax(pred, axis=1)
        evaluator.add_batch(target, pred)

    Acc = evaluator.Pixel_Accuracy()
    Acc_class = evaluator.Pixel_Accuracy_Class()
    mIoU = evaluator.Mean_Intersection_over_Union()
    FWIoU = evaluator.Frequency_Weighted_Intersection_over_Union()
    print("Acc:{}, Acc_class:{}, mIoU:{}, fwIoU: {}".format(
        Acc, Acc_class, mIoU, FWIoU))
    def __init__(self, args):
        self.args = args

        # define Dataloader
        self.train_loader, self.val_loader, self.test_loader, self.nclass = make_data_loader(args)

        # define network
        model = DeepLab(num_classes=self.nclass, output_stride=args.out_stride)

        optimizer = torch.optim.Adam(model.parameters(), lr=args.base_lr, weight_decay=args.weight_decay)

        self.criterion = SegmentationLoss(weight=None, cuda=args.cuda).build_loss(mode=args.loss_type)
        self.model, self.optimizer = model, optimizer

        self.evaluator = Evaluator(self.nclass)
        self.best_pred = 0.0

        self.trainloss_history = []
        self.valloss_history = []

        self.train_plot = []
        self.val_plot = []
        # every 10 epochs the lr will multiply 0.1
        self.scheduler = LR_Scheduler(args.lr_scheduler, args.base_lr, args.epochs, len(self.train_loader), lr_step=20)

        if args.cuda:
            self.model = self.model.cuda()
Exemple #3
0
    def __init__(self, env_cls, args, manager, cfg, process_num, pre=False, pre_irl=False, infer=False, realtrain=False):
        """
        :param env_cls: env class or function, not instance, as we need to create several instance in class.
        :param args:
        :param manager:
        :param cfg:
        :param process_num: process number
        :param pre: set to pretrain mode
        :param infer: set to test mode
        """
        self.train_direc = args.train_direc
        self.realtrain = realtrain
        self.process_num = process_num
        self.human_reward = human_reward(args, cfg)
        # initialize envs for each process
        self.env_list = []
        for _ in range(process_num):
            self.env_list.append(env_cls())

        # construct policy and value network
        self.feature_layer = nn.Sequential(
                                 nn.Linear(cfg.s_dim, cfg.h_dim),
                                 nn.ReLU()
        )
        self.policy = MultiDiscretePolicy(cfg, self.feature_layer).to(device=DEVICE)
        self.value = Value(cfg).to(device=DEVICE)
        self.multi_entropy_loss = nn.MultiLabelSoftMarginLoss()

        
        if pre:
            self.print_per_batch = args.print_per_batch
            from dbquery import DBQuery
            db = DBQuery(args.data_dir)
            self.data_train = manager.create_dataset_rl('train', args.batchsz, cfg, db)
            self.data_valid = manager.create_dataset_rl('valid', args.batchsz, cfg, db)
            self.data_test = manager.create_dataset_rl('test', args.batchsz, cfg, db)
            # self.multi_entropy_loss = nn.MultiLabelSoftMarginLoss()
        else:
            self.rewarder = RewardEstimator(args, manager, cfg, pretrain=pre_irl, inference=infer, feature_extractor=self.policy)
            # self.rewarder = DiscEstimator(args, manager, cfg, pretrain=pre_irl, inference=infer)
            self.evaluator = Evaluator(args.data_dir, cfg)

        self.save_dir = args.save_dir
        self.save_per_epoch = args.save_per_epoch
        self.optim_batchsz = args.batchsz
        self.update_round = args.update_round
        self.policy.eval()
        self.value.eval()
        
        self.gamma = args.gamma
        self.epsilon = args.epsilon
        self.tau = args.tau
        self.policy_optim = optim.RMSprop(self.policy.parameters(), lr=args.lr_rl)
        self.value_optim = optim.Adam(self.value.parameters(), lr=args.lr_rl)
        self.mt_factor = args.mt_factor
Exemple #4
0
def evaluate_batch(gt_list,pred_list,num_of_class):
    evaluator = Evaluator(num_of_class)
    evaluator.reset()
    for i in range(len(gt_list)):
        evaluator.add_batch(gt_list[i],pred_list[i])
    Acc = evaluator.Pixel_Accuracy()
    Acc_class = evaluator.Pixel_Accuracy_Class()
    mIoU = evaluator.Mean_Intersection_over_Union()
    FWIoU = evaluator.Frequency_Weighted_Intersection_over_Union()

    return format(Acc, '.4f'), format(Acc_class, '.4f'), format(mIoU, '.4f'), format(FWIoU, '.4f')
Exemple #5
0
def evaluate_single(gt,pred,num_of_class):
    evaluator = Evaluator(num_of_class)
    evaluator.reset()
    evaluator.add_batch(gt,pred)

    Acc = evaluator.Pixel_Accuracy()
    Acc_class = evaluator.Pixel_Accuracy_Class()
    mIoU = evaluator.Mean_Intersection_over_Union()
    FWIoU = evaluator.Frequency_Weighted_Intersection_over_Union()

    return format(Acc, '.4f'), format(Acc_class, '.4f'), format(mIoU, '.4f'), format(FWIoU, '.4f')
 def create_evaluator():
     return Evaluator(
         graph.n_node,
         given_as_target=given_as_target,
         siblings_nodes=siblings_nodes,
         config=config,
     )
Exemple #7
0
    def __init__(self,
                 anchors,
                 size: Tuple[int, int],
                 metric_names: list,
                 detect_thresh: float = 0.3,
                 nms_thresh: float = 0.3,
                 images_per_batch: int = -1):
        self.ap = 'AP'
        self.anchors = anchors
        self.size = size
        self.detect_thresh = detect_thresh
        self.nms_thresh = nms_thresh

        self.images_per_batch = images_per_batch
        self.metric_names_original = metric_names
        self.metric_names = ["{}-{}".format(self.ap, i) for i in metric_names]

        self.evaluator = Evaluator()
        self.boundingBoxes = BoundingBoxes()
Exemple #8
0
    def __init__(self, args):
        self.epochs = args.epochs
        self.save_interval = args.save_interval
        self.train_data = AerialDataset(args, mode='train')
        self.train_loader = DataLoader(self.train_data,
                                       batch_size=args.train_batch_size,
                                       shuffle=True,
                                       num_workers=1)
        self.model = models.deeplabv3_resnet50(num_classes=args.num_of_class)
        #self.model = models.fcn_resnet50(num_classes=args.num_of_class)

        self.loss = args.loss
        if self.loss == 'CE':
            self.criterion = nn.CrossEntropyLoss()
        else:  #self.loss == 'LS'
            self.criterion = LovaszSoftmax()

        self.optimizer = torch.optim.AdamW(self.model.parameters())

        self.eval_interval = args.eval_interval
        self.eval_data = AerialDataset(args, mode='eval')
        self.eval_loader = DataLoader(self.eval_data,
                                      batch_size=args.eval_batch_size,
                                      shuffle=False,
                                      num_workers=1)
        self.evaluator = Evaluator(args.num_of_class)

        self.cuda = args.cuda
        if self.cuda is True:
            self.model = self.model.cuda()

        self.resume = args.resume
        if self.resume != None:
            if self.cuda:
                checkpoint = torch.load(args.resume)
            else:
                checkpoint = torch.load(args.resume, map_location='cpu')
            self.model.load_state_dict(checkpoint['model'])
            self.optimizer.load_state_dict(checkpoint['opt'])
            self.start_epoch = checkpoint['epoch'] + 1
            #start from next epoch
        else:
            self.start_epoch = 1
Exemple #9
0
class human_reward(object):
    def __init__(self, args, config):
        self.evaluator = Evaluator(args.data_dir, config)

    def check_success(self, s):
        match_session = self.evaluator.match_rate(s, True)
        inform_session = self.evaluator.inform_F1(s, True)
        if (match_session == 1 and inform_session[1] == 1) \
        or (match_session == 1 and inform_session[1] is None) \
        or (match_session is None and inform_session[1] == 1):
            return True
        else:
            return False

    def reward_human(self, s, done):
        success = self.check_success(s)
        if success:
            reward = 0.2 * 40
        if not success and not done:
            reward = -0.1
        if not success and done:
            reward = -0.1 * 40  # 10
        return reward
Exemple #10
0
def evaluate(image_file_paths,
             gt_file_paths,
             model,
             nn_input_size,
             num_classes,
             window_sizes=None,
             step_sizes=None,
             device=None):
    """
    Evaluate model performance
    :param image_file_paths: paths to images that will be predicted
    :param gt_file_paths: paths to ground truth masks
    :param model: model used for prediction
    :param nn_input_size: size that the images will be scaled to before feeding them into the nn
    :param num_classes: number of classes
    :param window_sizes: list of sizes that determine how the image will be cut (for sliding window). Image will be cut
    into squares
    :param step_sizes: list of step sizes for sliding window
    :param device: PyTorch device (cpu or gpu)
    :return: list of prediction masks if res_fcn is None, else Nothing
    """
    model.eval()
    evaluator = Evaluator(num_classes)

    def ev(prediction, index):
        pred_class_id_mask = np.argmax(prediction, axis=-1)
        gt_colour_mask = cv2.imread(gt_file_paths[index])[:, :, 0]
        gt_class_id_mask = colour_mask_to_class_id_mask(gt_colour_mask)

        # Add sample into evaluator
        evaluator.add_batch(gt_class_id_mask, pred_class_id_mask)

    with torch.no_grad():
        predict.predict(image_file_paths=image_file_paths,
                        model=model,
                        nn_input_size=nn_input_size,
                        res_fcn=ev,
                        window_sizes=window_sizes,
                        step_sizes=step_sizes,
                        device=device)

    with np.errstate(divide='ignore', invalid='ignore'):
        acc = evaluator.Pixel_Accuracy()
        acc_class = evaluator.Pixel_Accuracy_Class()
        mIoU = evaluator.Mean_Intersection_over_Union()
        fWIoU = evaluator.Frequency_Weighted_Intersection_over_Union()

    return acc, acc_class, mIoU, fWIoU
 def func_wrapper(model, arguments):
     evaluator = Evaluator(args.num_classes)
     evaluator.reset()
     model.eval()
     model.cuda()
     threshold, use_cuda = arguments[0], arguments[1]
     total_samples = 0
     for sample in tqdm(data_loader):
         images, label = sample['image'], sample['label']
         images, label = images.cuda(), label.cpu().numpy()
         output = model(images)
         pred = torch.argmax(output, 1).data.cpu().numpy()
         evaluator.add_batch(label, pred)
         total_samples += images.size()[0]
         if total_samples > threshold:
             break
     mIoU = evaluator.Mean_Intersection_over_Union() * 100.
     print("mIoU : {:0.2f}".format(mIoU))
     return mIoU
    def main():
        os.environ["CUDA_VISIBLE_DEVICES"] = "3"

        testdataset = Cityscapesloader('Cityscapes/', split='val', )
        testdataloader = DataLoader(testdataset, batch_size=4, shuffle=True, num_workers=8, pin_memory=True)


        ICnet_ = ICnet_model(19, (512, 1024)).cuda()

        model_path = 'checkpoints/last.pth'
        if os.path.exists(model_path):
            ICnet_.load(model_path)

        summary(ICnet_, ( 3, 512, 1024))

        ICnet_.eval()

        eval = Evaluator(19)
        eval.reset()
        with torch.no_grad():
            for batch_index, (image_batch, labels_batch) in enumerate(testdataloader):
                print(batch_index)
                image = image_batch.cuda()
                labels_batch = np.array(labels_batch)


                output = ICnet_.forward(image).cpu().numpy()

                pred = np.argmax(output, axis=1)



                eval.add_batch(labels_batch, pred)

        Pixel_Accuracy = eval.Pixel_Accuracy()

        print('Pixel_Accuracy = ', Pixel_Accuracy)
Exemple #13
0
def main():
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    load_weights_folder = os.path.expanduser(settings.load_weights_dir)
    model_path = os.path.join(load_weights_folder, "model.pth")
    model_dict = torch.load(model_path)

    # data
    datasets_dict = {
        "3d60": datasets.ThreeD60,
        "panosuncg": datasets.PanoSunCG,
        "stanford2d3d": datasets.Stanford2D3D,
        "matterport3d": datasets.Matterport3D
    }
    dataset = datasets_dict[settings.dataset]

    fpath = os.path.join(os.path.dirname(__file__), "datasets", "{}_{}.txt")

    test_file_list = fpath.format(settings.dataset, "test")

    test_dataset = dataset(settings.data_path,
                           test_file_list,
                           model_dict['height'],
                           model_dict['width'],
                           is_training=False)
    test_loader = DataLoader(test_dataset,
                             settings.batch_size,
                             False,
                             num_workers=settings.num_workers,
                             pin_memory=True,
                             drop_last=False)
    num_test_samples = len(test_dataset)
    num_steps = num_test_samples // settings.batch_size
    print("Num. of test samples:", num_test_samples, "Num. of steps:",
          num_steps, "\n")

    # network
    Net_dict = {"UniFuse": UniFuse, "Equi": Equi}
    Net = Net_dict[model_dict['net']]

    model = Net(model_dict['layers'],
                model_dict['height'],
                model_dict['width'],
                max_depth=test_dataset.max_depth_meters,
                fusion_type=model_dict['fusion'],
                se_in_fusion=model_dict['se_in_fusion'])

    model.to(device)
    model_state_dict = model.state_dict()
    model.load_state_dict(
        {k: v
         for k, v in model_dict.items() if k in model_state_dict})
    model.eval()

    evaluator = Evaluator(settings.median_align)
    evaluator.reset_eval_metrics()
    saver = Saver(load_weights_folder)
    pbar = tqdm.tqdm(test_loader)
    pbar.set_description("Testing")

    with torch.no_grad():
        for batch_idx, inputs in enumerate(pbar):

            equi_inputs = inputs["normalized_rgb"].to(device)

            cube_inputs = inputs["normalized_cube_rgb"].to(device)

            outputs = model(equi_inputs, cube_inputs)

            pred_depth = outputs["pred_depth"].detach().cpu()

            gt_depth = inputs["gt_depth"]
            mask = inputs["val_mask"]
            for i in range(gt_depth.shape[0]):
                evaluator.compute_eval_metrics(gt_depth[i:i + 1],
                                               pred_depth[i:i + 1],
                                               mask[i:i + 1])

            if settings.save_samples:
                saver.save_samples(inputs["rgb"], gt_depth, pred_depth, mask)

    evaluator.print(load_weights_folder)
class Trainer(object):
    def __init__(self, args):
        self.args = args

        # define Dataloader
        self.train_loader, self.val_loader, self.test_loader, self.nclass = make_data_loader(args)

        # define network
        model = DeepLab(num_classes=self.nclass, output_stride=args.out_stride)

        optimizer = torch.optim.Adam(model.parameters(), lr=args.base_lr, weight_decay=args.weight_decay)

        self.criterion = SegmentationLoss(weight=None, cuda=args.cuda).build_loss(mode=args.loss_type)
        self.model, self.optimizer = model, optimizer

        self.evaluator = Evaluator(self.nclass)
        self.best_pred = 0.0

        self.trainloss_history = []
        self.valloss_history = []

        self.train_plot = []
        self.val_plot = []
        # every 10 epochs the lr will multiply 0.1
        self.scheduler = LR_Scheduler(args.lr_scheduler, args.base_lr, args.epochs, len(self.train_loader), lr_step=20)

        if args.cuda:
            self.model = self.model.cuda()

    
    def training(self, epoch):
        train_loss = 0.0
        self.model.train()
        #tbar = tqdm(self.train_loader)    # Instantly make your loops show a smart progress meter

        for i, sample in enumerate(self.train_loader):
            
            if i >= 10000:
                break
            else:
                image, target = sample['image'], sample['label']
                if self.args.cuda:
                    image, target = image.cuda(), target.cuda()
                
                self.scheduler(self.optimizer, i, epoch, self.best_pred)
                self.optimizer.zero_grad()
                output = self.model(image)
                
                loss = self.criterion(output, target)
                loss.backward()
                self.optimizer.step()
                self.trainloss_history.append(loss.data.cpu().numpy())
                

                if epoch == 3 and i == 1:
                    print("after 3 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)

                if epoch == 9 and i == 1:
                    print("after 10 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)
                  
                if epoch == 29 and i == 1:
                    print("after 20 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 3:
             
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 5:
                  
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 7:
                  
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 9:
                   
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 1:
                    print("after 30 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 3:
             
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 5:
                  
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 7:
                  
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 9:
                   
                    visualize_image("coco", image, target, output)
                
                pred = output.data.cpu().numpy()
                
                pred = np.argmax(pred, axis=1)
                self.evaluator.add_batch(target.cpu().numpy(), pred)

        acc = self.evaluator.Pixel_Accuracy()
        #acc_class = self.evaluator.Pixel_Accuracy_Class()
        mIoU = self.evaluator.Mean_Intersection_over_Union()
        
        last_loss = self.trainloss_history[-i:]
        train_loss = np.mean(last_loss) 
        self.train_plot.append(train_loss)
        
        print('[Epoch: %d, numImages: %5d]' % (epoch, i * self.args.batch_size ))
        print('Loss: %.3f' % train_loss)
        print("Train_Acc:{}".format(acc), "Train_mIoU:{}".format(mIoU))

        if epoch == 20:
            torch.save(self.model.state_dict(), '/home/wan/Segmentation/model_20')
        if epoch == 30:
            torch.save(self.model.state_dict(), '/home/wan/Segmentation/model_30')
        if epoch == 40:
            torch.save(self.model.state_dict(), '/home/wan/Segmentation/model_40')
        if epoch == 50:
            torch.save(self.model.state_dict(), '/home/wan/Segmentation/model_50')

    def validation(self, epoch):
        self.model.eval()
        self.evaluator.reset()
        #tbar = tqdm(self.val_loader, desc='\r')
        val_loss = 0.0
        for i, sample in enumerate(self.val_loader):
            
            if i >= 750:
                break
            else:
                image, target = sample['image'], sample['label']
                if self.args.cuda:
                    image, target = image.cuda(), target.cuda()
                with torch.no_grad():
                    output = self.model(image)

                loss = self.criterion(output, target)
                self.valloss_history.append(loss.data.cpu().numpy())

                pred = output.data.cpu().numpy()
                
                pred = np.argmax(pred, axis=1)
                # visualize the prediction and target
                if epoch == 3 and i == 0:
                    print("after 3 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)
                if epoch ==9 and i == 0:
                    print("after 10 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 0:
                    print("after 20 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 1:
                    
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 2:
                   
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 3:
                   
                    visualize_image("coco", image, target, output)
                if epoch == 29 and i == 4:
                   
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 0:
                    print("after 30 epochs, the result of training data:")
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 1:
                    
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 2:
                   
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 3:
                   
                    visualize_image("coco", image, target, output)
                if epoch == 49 and i == 4:
                   
                    visualize_image("coco", image, target, output)

                self.evaluator.add_batch(target.cpu().numpy(), pred)
            
        acc = self.evaluator.Pixel_Accuracy()
        #acc_class = self.evaluator.Pixel_Accuracy_Class()
        mIoU = self.evaluator.Mean_Intersection_over_Union()

        last_loss = self.valloss_history[-i:]
        val_loss = np.mean(last_loss)
        self.val_plot.append(val_loss)


        print('Validation: ')
        print('[Epoch: %d, numImages: %5d]' % (epoch, i * self.args.batch_size ))
        print("Acc:{}".format(acc), "mIoU:{}".format(mIoU))
        print('Loss: %.3f' % val_loss)
Exemple #15
0
    # Save per epoch loss on loss.log
    train_callbacks.append(
        TrainLogger(args.log_interval,
                    train.nbatches(),
                    loss_log_path=join(log_path, f"loss.log")))
else:
    print(f"[Logging: None]")

# Model saving configuration
print(f"[Model Saving: {args.save}]")
if args.save:
    test_callbacks.append(BestModelSaver(log_path, args.loss))

# Evaluation configuration
metric = KNNF1ScoreMetric(config.test_distance, neighbors=10)
dev_evaluator = Evaluator(dev, metric, 'dev', test_callbacks)
test_evaluator = Evaluator(
    test,
    metric,
    'test',
    callbacks=[MetricFileLogger(log_path=join(log_path, 'test-metric.log'))])
train_callbacks.extend([dev_evaluator, test_evaluator])

# Training configuration
optim = config.optimizer(model, lr=args.lr)
model_loader = ModelLoader(
    args.recover, args.recover_optim) if args.recover is not None else None
trainer = Trainer(args.loss,
                  model,
                  config.loss,
                  train,
Exemple #16
0
    def __init__(self, data_train, data_valid, image_base_dir, instructions):
        """

        :param data_train:
        :param data_valid:
        :param image_base_dir:
        :param instructions:
        """

        self.image_base_dir = image_base_dir
        self.data_valid = data_valid
        self.instructions = instructions

        # specify model save dir
        self.model_name = instructions[STR.MODEL_NAME]
        # now = time.localtime()
        # start_time = "{}-{}-{}T{}:{}:{}".format(now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min,
        #                                         now.tm_sec)
        experiment_folder_path = os.path.join(paths.MODELS_FOLDER_PATH,
                                              self.model_name)

        if os.path.exists(experiment_folder_path):
            Warning(
                "Experiment folder exists already. Files might be overwritten")
        os.makedirs(experiment_folder_path, exist_ok=True)

        # define saver and save instructions
        self.saver = Saver(folder_path=experiment_folder_path,
                           instructions=instructions)
        self.saver.save_instructions()

        # define Tensorboard Summary
        self.writer = SummaryWriter(log_dir=experiment_folder_path)

        nn_input_size = instructions[STR.NN_INPUT_SIZE]
        state_dict_file_path = instructions.get(STR.STATE_DICT_FILE_PATH, None)

        self.colour_mapping = mapping.get_colour_mapping()

        # define transformers for training
        crops_per_image = instructions.get(STR.CROPS_PER_IMAGE, 10)

        apply_random_cropping = (STR.CROPS_PER_IMAGE in instructions.keys()) and \
                                (STR.IMAGES_PER_BATCH in instructions.keys())

        print("{}applying random cropping".format(
            "" if apply_random_cropping else "_NOT_ "))

        t = [Normalize()]
        if apply_random_cropping:
            t.append(
                RandomCrop(min_size=instructions.get(STR.CROP_SIZE_MIN, 400),
                           max_size=instructions.get(STR.CROP_SIZE_MAX, 1000),
                           crop_count=crops_per_image))
        t += [
            Resize(nn_input_size),
            Flip(p_vertical=0.2, p_horizontal=0.5),
            ToTensor()
        ]

        transformations_train = transforms.Compose(t)

        # define transformers for validation
        transformations_valid = transforms.Compose(
            [Normalize(), Resize(nn_input_size),
             ToTensor()])

        # set up data loaders
        dataset_train = DictArrayDataSet(image_base_dir=image_base_dir,
                                         data=data_train,
                                         num_classes=len(
                                             self.colour_mapping.keys()),
                                         transformation=transformations_train)

        # define batch sizes
        self.batch_size = instructions[STR.BATCH_SIZE]

        if apply_random_cropping:
            self.data_loader_train = DataLoader(
                dataset=dataset_train,
                batch_size=instructions[STR.IMAGES_PER_BATCH],
                shuffle=True,
                collate_fn=custom_collate)
        else:
            self.data_loader_train = DataLoader(dataset=dataset_train,
                                                batch_size=self.batch_size,
                                                shuffle=True,
                                                collate_fn=custom_collate)

        dataset_valid = DictArrayDataSet(image_base_dir=image_base_dir,
                                         data=data_valid,
                                         num_classes=len(
                                             self.colour_mapping.keys()),
                                         transformation=transformations_valid)

        self.data_loader_valid = DataLoader(dataset=dataset_valid,
                                            batch_size=self.batch_size,
                                            shuffle=False,
                                            collate_fn=custom_collate)

        self.num_classes = dataset_train.num_classes()

        # define model
        print("Building model")
        self.model = DeepLab(num_classes=self.num_classes,
                             backbone=instructions.get(STR.BACKBONE, "resnet"),
                             output_stride=instructions.get(
                                 STR.DEEPLAB_OUTPUT_STRIDE, 16))

        # load weights
        if state_dict_file_path is not None:
            print("loading state_dict from:")
            print(state_dict_file_path)
            load_state_dict(self.model, state_dict_file_path)

        learning_rate = instructions.get(STR.LEARNING_RATE, 1e-5)
        train_params = [{
            'params': self.model.get_1x_lr_params(),
            'lr': learning_rate
        }, {
            'params': self.model.get_10x_lr_params(),
            'lr': learning_rate
        }]

        # choose gpu or cpu
        self.device = torch.device(
            "cuda:0" if torch.cuda.is_available() else "cpu")
        if instructions.get(STR.MULTI_GPU, False):
            if torch.cuda.device_count() > 1:
                print("Using ", torch.cuda.device_count(), " GPUs!")
                self.model = nn.DataParallel(self.model)

        self.model.to(self.device)

        # Define Optimizer
        self.optimizer = torch.optim.SGD(train_params,
                                         momentum=0.9,
                                         weight_decay=5e-4,
                                         nesterov=False)

        # calculate class weights
        if instructions.get(STR.CLASS_STATS_FILE_PATH, None):

            class_weights = calculate_class_weights(
                instructions[STR.CLASS_STATS_FILE_PATH],
                self.colour_mapping,
                modifier=instructions.get(STR.LOSS_WEIGHT_MODIFIER, 1.01))

            class_weights = torch.from_numpy(class_weights.astype(np.float32))
        else:
            class_weights = None
        self.criterion = SegmentationLosses(
            weight=class_weights, cuda=self.device.type != "cpu").build_loss()

        # Define Evaluator
        self.evaluator = Evaluator(self.num_classes)

        # Define lr scheduler
        self.scheduler = None
        if instructions.get(STR.USE_LR_SCHEDULER, True):
            self.scheduler = LR_Scheduler(mode="cos",
                                          base_lr=learning_rate,
                                          num_epochs=instructions[STR.EPOCHS],
                                          iters_per_epoch=len(
                                              self.data_loader_train))

        # print information before training start
        print("-" * 60)
        print("instructions")
        pprint(instructions)
        model_parameters = sum([p.nelement() for p in self.model.parameters()])
        print("Model parameters: {:.2E}".format(model_parameters))

        self.best_prediction = 0.0
Exemple #17
0
class Trainer:
    def __init__(self, data_train, data_valid, image_base_dir, instructions):
        """

        :param data_train:
        :param data_valid:
        :param image_base_dir:
        :param instructions:
        """

        self.image_base_dir = image_base_dir
        self.data_valid = data_valid
        self.instructions = instructions

        # specify model save dir
        self.model_name = instructions[STR.MODEL_NAME]
        # now = time.localtime()
        # start_time = "{}-{}-{}T{}:{}:{}".format(now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min,
        #                                         now.tm_sec)
        experiment_folder_path = os.path.join(paths.MODELS_FOLDER_PATH,
                                              self.model_name)

        if os.path.exists(experiment_folder_path):
            Warning(
                "Experiment folder exists already. Files might be overwritten")
        os.makedirs(experiment_folder_path, exist_ok=True)

        # define saver and save instructions
        self.saver = Saver(folder_path=experiment_folder_path,
                           instructions=instructions)
        self.saver.save_instructions()

        # define Tensorboard Summary
        self.writer = SummaryWriter(log_dir=experiment_folder_path)

        nn_input_size = instructions[STR.NN_INPUT_SIZE]
        state_dict_file_path = instructions.get(STR.STATE_DICT_FILE_PATH, None)

        self.colour_mapping = mapping.get_colour_mapping()

        # define transformers for training
        crops_per_image = instructions.get(STR.CROPS_PER_IMAGE, 10)

        apply_random_cropping = (STR.CROPS_PER_IMAGE in instructions.keys()) and \
                                (STR.IMAGES_PER_BATCH in instructions.keys())

        print("{}applying random cropping".format(
            "" if apply_random_cropping else "_NOT_ "))

        t = [Normalize()]
        if apply_random_cropping:
            t.append(
                RandomCrop(min_size=instructions.get(STR.CROP_SIZE_MIN, 400),
                           max_size=instructions.get(STR.CROP_SIZE_MAX, 1000),
                           crop_count=crops_per_image))
        t += [
            Resize(nn_input_size),
            Flip(p_vertical=0.2, p_horizontal=0.5),
            ToTensor()
        ]

        transformations_train = transforms.Compose(t)

        # define transformers for validation
        transformations_valid = transforms.Compose(
            [Normalize(), Resize(nn_input_size),
             ToTensor()])

        # set up data loaders
        dataset_train = DictArrayDataSet(image_base_dir=image_base_dir,
                                         data=data_train,
                                         num_classes=len(
                                             self.colour_mapping.keys()),
                                         transformation=transformations_train)

        # define batch sizes
        self.batch_size = instructions[STR.BATCH_SIZE]

        if apply_random_cropping:
            self.data_loader_train = DataLoader(
                dataset=dataset_train,
                batch_size=instructions[STR.IMAGES_PER_BATCH],
                shuffle=True,
                collate_fn=custom_collate)
        else:
            self.data_loader_train = DataLoader(dataset=dataset_train,
                                                batch_size=self.batch_size,
                                                shuffle=True,
                                                collate_fn=custom_collate)

        dataset_valid = DictArrayDataSet(image_base_dir=image_base_dir,
                                         data=data_valid,
                                         num_classes=len(
                                             self.colour_mapping.keys()),
                                         transformation=transformations_valid)

        self.data_loader_valid = DataLoader(dataset=dataset_valid,
                                            batch_size=self.batch_size,
                                            shuffle=False,
                                            collate_fn=custom_collate)

        self.num_classes = dataset_train.num_classes()

        # define model
        print("Building model")
        self.model = DeepLab(num_classes=self.num_classes,
                             backbone=instructions.get(STR.BACKBONE, "resnet"),
                             output_stride=instructions.get(
                                 STR.DEEPLAB_OUTPUT_STRIDE, 16))

        # load weights
        if state_dict_file_path is not None:
            print("loading state_dict from:")
            print(state_dict_file_path)
            load_state_dict(self.model, state_dict_file_path)

        learning_rate = instructions.get(STR.LEARNING_RATE, 1e-5)
        train_params = [{
            'params': self.model.get_1x_lr_params(),
            'lr': learning_rate
        }, {
            'params': self.model.get_10x_lr_params(),
            'lr': learning_rate
        }]

        # choose gpu or cpu
        self.device = torch.device(
            "cuda:0" if torch.cuda.is_available() else "cpu")
        if instructions.get(STR.MULTI_GPU, False):
            if torch.cuda.device_count() > 1:
                print("Using ", torch.cuda.device_count(), " GPUs!")
                self.model = nn.DataParallel(self.model)

        self.model.to(self.device)

        # Define Optimizer
        self.optimizer = torch.optim.SGD(train_params,
                                         momentum=0.9,
                                         weight_decay=5e-4,
                                         nesterov=False)

        # calculate class weights
        if instructions.get(STR.CLASS_STATS_FILE_PATH, None):

            class_weights = calculate_class_weights(
                instructions[STR.CLASS_STATS_FILE_PATH],
                self.colour_mapping,
                modifier=instructions.get(STR.LOSS_WEIGHT_MODIFIER, 1.01))

            class_weights = torch.from_numpy(class_weights.astype(np.float32))
        else:
            class_weights = None
        self.criterion = SegmentationLosses(
            weight=class_weights, cuda=self.device.type != "cpu").build_loss()

        # Define Evaluator
        self.evaluator = Evaluator(self.num_classes)

        # Define lr scheduler
        self.scheduler = None
        if instructions.get(STR.USE_LR_SCHEDULER, True):
            self.scheduler = LR_Scheduler(mode="cos",
                                          base_lr=learning_rate,
                                          num_epochs=instructions[STR.EPOCHS],
                                          iters_per_epoch=len(
                                              self.data_loader_train))

        # print information before training start
        print("-" * 60)
        print("instructions")
        pprint(instructions)
        model_parameters = sum([p.nelement() for p in self.model.parameters()])
        print("Model parameters: {:.2E}".format(model_parameters))

        self.best_prediction = 0.0

    def train(self, epoch):
        self.model.train()
        train_loss = 0.0

        # create a progress bar
        pbar = tqdm(self.data_loader_train)
        num_batches_train = len(self.data_loader_train)

        # go through each item in the training data
        for i, sample in enumerate(pbar):
            # set input and target
            nn_input = sample[STR.NN_INPUT].to(self.device)
            nn_target = sample[STR.NN_TARGET].to(self.device,
                                                 dtype=torch.float)

            if self.scheduler:
                self.scheduler(self.optimizer, i, epoch, self.best_prediction)

            # run model
            output = self.model(nn_input)

            # calc losses
            loss = self.criterion(output, nn_target)
            # # save step losses
            # combined_loss_steps.append(float(loss))
            # regression_loss_steps.append(float(regression_loss))
            # classification_loss_steps.append(float(classification_loss))

            train_loss += loss.item()
            pbar.set_description('Train loss: %.3f' % (train_loss / (i + 1)))
            self.writer.add_scalar('train/total_loss_iter', loss.item(),
                                   i + num_batches_train * epoch)

            # calculate gradient and update model weights
            loss.backward()
            # torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1)
            self.optimizer.step()
            self.optimizer.zero_grad()

        self.writer.add_scalar('train/total_loss_epoch', train_loss, epoch)
        print("[Epoch: {}, num images/crops: {}]".format(
            epoch, num_batches_train * self.batch_size))

        print("Loss: {:.2f}".format(train_loss))

    def validation(self, epoch):

        self.model.eval()
        self.evaluator.reset()
        test_loss = 0.0

        pbar = tqdm(self.data_loader_valid, desc='\r')
        num_batches_val = len(self.data_loader_valid)

        for i, sample in enumerate(pbar):
            # set input and target
            nn_input = sample[STR.NN_INPUT].to(self.device)
            nn_target = sample[STR.NN_TARGET].to(self.device,
                                                 dtype=torch.float)

            with torch.no_grad():
                output = self.model(nn_input)

            loss = self.criterion(output, nn_target)
            test_loss += loss.item()
            pbar.set_description('Test loss: %.3f' % (test_loss / (i + 1)))
            pred = output.data.cpu().numpy()
            pred = np.argmax(pred, axis=1)
            nn_target = nn_target.cpu().numpy()
            # Add batch sample into evaluator
            self.evaluator.add_batch(nn_target, pred)

        # Fast test during the training
        Acc = self.evaluator.Pixel_Accuracy()
        Acc_class = self.evaluator.Pixel_Accuracy_Class()
        mIoU = self.evaluator.Mean_Intersection_over_Union()
        FWIoU = self.evaluator.Frequency_Weighted_Intersection_over_Union()
        self.writer.add_scalar('val/total_loss_epoch', test_loss, epoch)
        self.writer.add_scalar('val/mIoU', mIoU, epoch)
        self.writer.add_scalar('val/Acc', Acc, epoch)
        self.writer.add_scalar('val/Acc_class', Acc_class, epoch)
        self.writer.add_scalar('val/fwIoU', FWIoU, epoch)
        print('Validation:')
        print("[Epoch: {}, num crops: {}]".format(
            epoch, num_batches_val * self.batch_size))
        print(
            "Acc:{:.2f}, Acc_class:{:.2f}, mIoU:{:.2f}, fwIoU: {:.2f}".format(
                Acc, Acc_class, mIoU, FWIoU))
        print("Loss: {:.2f}".format(test_loss))

        new_pred = mIoU
        is_best = new_pred > self.best_prediction
        if is_best:
            self.best_prediction = new_pred
        self.saver.save_checkpoint(self.model, is_best, epoch)
Exemple #18
0
class PPO(object):
    def __init__(self,
                 env_cls,
                 args,
                 manager,
                 cfg,
                 process_num,
                 pre=False,
                 pre_irl=False,
                 infer=False):
        """
        :param env_cls: env class or function, not instance, as we need to create several instance in class.
        :param args:
        :param manager:
        :param cfg:
        :param process_num: process number
        :param pre: set to pretrain mode
        :param infer: set to test mode
        """

        self.process_num = process_num

        # initialize envs for each process
        self.env_list = []
        for _ in range(process_num):
            self.env_list.append(env_cls())

        # construct policy and value network
        self.policy = MultiDiscretePolicy(cfg).to(device=DEVICE)
        self.value = Value(cfg).to(device=DEVICE)

        if pre:
            self.print_per_batch = args.print_per_batch
            from dbquery import DBQuery
            db = DBQuery(args.data_dir)
            self.data_train = manager.create_dataset_rl(
                'train', args.batchsz, cfg, db)
            self.data_valid = manager.create_dataset_rl(
                'valid', args.batchsz, cfg, db)
            self.data_test = manager.create_dataset_rl('test', args.batchsz,
                                                       cfg, db)
            self.multi_entropy_loss = nn.MultiLabelSoftMarginLoss()
        else:
            self.rewarder = RewardEstimator(args,
                                            manager,
                                            cfg,
                                            pretrain=pre_irl,
                                            inference=infer)
            self.evaluator = Evaluator(args.data_dir, cfg)

        self.save_dir = args.save_dir
        self.save_per_epoch = args.save_per_epoch
        self.optim_batchsz = args.batchsz
        self.update_round = args.update_round
        self.policy.eval()
        self.value.eval()

        self.gamma = args.gamma
        self.epsilon = args.epsilon
        self.tau = args.tau
        self.policy_optim = optim.RMSprop(self.policy.parameters(),
                                          lr=args.lr_rl)
        self.value_optim = optim.Adam(self.value.parameters(), lr=args.lr_rl)

    def policy_loop(self, data):
        s, target_a = to_device(data)
        a_weights = self.policy(s)

        loss_a = self.multi_entropy_loss(a_weights, target_a)
        return loss_a

    def imitating(self, epoch):
        """
        pretrain the policy by simple imitation learning (behavioral cloning)
        """
        self.policy.train()
        a_loss = 0.
        for i, data in enumerate(self.data_train):
            self.policy_optim.zero_grad()
            loss_a = self.policy_loop(data)
            a_loss += loss_a.item()
            loss_a.backward()
            self.policy_optim.step()

            if (i + 1) % self.print_per_batch == 0:
                a_loss /= self.print_per_batch
                logging.debug(
                    '<<dialog policy>> epoch {}, iter {}, loss_a:{}'.format(
                        epoch, i, a_loss))
                a_loss = 0.

        if (epoch + 1) % self.save_per_epoch == 0:
            self.save(self.save_dir, epoch, True)
        self.policy.eval()

    def imit_test(self, epoch, best):
        """
        provide an unbiased evaluation of the policy fit on the training dataset
        """
        a_loss = 0.
        for i, data in enumerate(self.data_valid):
            loss_a = self.policy_loop(data)
            a_loss += loss_a.item()

        a_loss /= len(self.data_valid)
        logging.debug(
            '<<dialog policy>> validation, epoch {}, loss_a:{}'.format(
                epoch, a_loss))
        if a_loss < best:
            logging.info('<<dialog policy>> best model saved')
            best = a_loss
            self.save(self.save_dir, 'best', True)

        a_loss = 0.
        for i, data in enumerate(self.data_test):
            loss_a = self.policy_loop(data)
            a_loss += loss_a.item()

        a_loss /= len(self.data_test)
        logging.debug('<<dialog policy>> test, epoch {}, loss_a:{}'.format(
            epoch, a_loss))
        return best

    def imit_value(self, epoch, batchsz, best):
        self.value.train()
        batch = self.sample(batchsz)
        s = torch.from_numpy(np.stack(batch.state)).to(device=DEVICE)
        a = torch.from_numpy(np.stack(batch.action)).to(device=DEVICE)
        next_s = torch.from_numpy(np.stack(batch.next_state)).to(device=DEVICE)
        mask = torch.Tensor(np.stack(batch.mask)).to(device=DEVICE)
        batchsz = s.size(0)

        v = self.value(s).squeeze(-1).detach()
        log_pi_old_sa = self.policy.get_log_prob(s, a).detach()
        r = self.rewarder.estimate(s, a, next_s, log_pi_old_sa).detach()
        A_sa, v_target = self.est_adv(r, v, mask)

        for i in range(self.update_round):
            perm = torch.randperm(batchsz)
            v_target_shuf, s_shuf = v_target[perm], s[perm]
            optim_chunk_num = int(np.ceil(batchsz / self.optim_batchsz))
            v_target_shuf, s_shuf = torch.chunk(v_target_shuf,
                                                optim_chunk_num), torch.chunk(
                                                    s_shuf, optim_chunk_num)

            value_loss = 0.
            for v_target_b, s_b in zip(v_target_shuf, s_shuf):
                self.value_optim.zero_grad()
                v_b = self.value(s_b).squeeze(-1)
                loss = (v_b - v_target_b).pow(2).mean()
                value_loss += loss.item()
                loss.backward()
                self.value_optim.step()

            value_loss /= optim_chunk_num
            logging.debug(
                '<<dialog policy>> epoch {}, iteration {}, loss {}'.format(
                    epoch, i, value_loss))

        if value_loss < best:
            logging.info('<<dialog policy>> best model saved')
            best = value_loss
            self.save(self.save_dir, 'best', True)
        if (epoch + 1) % self.save_per_epoch == 0:
            self.save(self.save_dir, epoch, True)
        self.value.eval()
        return best

    def train_irl(self, epoch, batchsz):
        batch = self.sample(batchsz)
        self.rewarder.train_irl(batch, epoch)

    def test_irl(self, epoch, batchsz, best):
        batch = self.sample(batchsz)
        best = self.rewarder.test_irl(batch, epoch, best)
        return best

    def est_adv(self, r, v, mask):
        """
        we save a trajectory in continuous space and it reaches the ending of current trajectory when mask=0.
        :param r: reward, Tensor, [b]
        :param v: estimated value, Tensor, [b]
        :param mask: indicates ending for 0 otherwise 1, Tensor, [b]
        :return: A(s, a), V-target(s), both Tensor
        """
        batchsz = v.size(0)

        # v_target is worked out by Bellman equation.
        v_target = torch.Tensor(batchsz).to(device=DEVICE)
        delta = torch.Tensor(batchsz).to(device=DEVICE)
        A_sa = torch.Tensor(batchsz).to(device=DEVICE)

        prev_v_target = 0
        prev_v = 0
        prev_A_sa = 0
        for t in reversed(range(batchsz)):
            # mask here indicates a end of trajectory
            # this value will be treated as the target value of value network.
            # mask = 0 means the immediate reward is the real V(s) since it's end of trajectory.
            # formula: V(s_t) = r_t + gamma * V(s_t+1)
            v_target[t] = r[t] + self.gamma * prev_v_target * mask[t]

            # please refer to : https://arxiv.org/abs/1506.02438
            # for generalized adavantage estimation
            # formula: delta(s_t) = r_t + gamma * V(s_t+1) - V(s_t)
            delta[t] = r[t] + self.gamma * prev_v * mask[t] - v[t]

            # formula: A(s, a) = delta(s_t) + gamma * lamda * A(s_t+1, a_t+1)
            # here use symbol tau as lambda, but original paper uses symbol lambda.
            A_sa[t] = delta[t] + self.gamma * self.tau * prev_A_sa * mask[t]

            # update previous
            prev_v_target = v_target[t]
            prev_v = v[t]
            prev_A_sa = A_sa[t]

        # normalize A_sa
        A_sa = (A_sa - A_sa.mean()) / A_sa.std()

        return A_sa, v_target

    def update(self, batchsz, epoch, best=None):
        """
        firstly sample batchsz items and then perform optimize algorithms.
        :param batchsz:
        :param epoch:
        :param best:
        :return:
        """
        backward = True if best is None else False
        if backward:
            self.policy.train()
            self.value.train()

        # 1. sample data asynchronously
        batch = self.sample(batchsz)

        # data in batch is : batch.state: ([1, s_dim], [1, s_dim]...)
        # batch.action: ([1, a_dim], [1, a_dim]...)
        # batch.reward/ batch.mask: ([1], [1]...)
        s = torch.from_numpy(np.stack(batch.state)).to(device=DEVICE)
        a = torch.from_numpy(np.stack(batch.action)).to(device=DEVICE)
        next_s = torch.from_numpy(np.stack(batch.next_state)).to(device=DEVICE)
        mask = torch.Tensor(np.stack(batch.mask)).to(device=DEVICE)
        batchsz = s.size(0)

        # 2. update reward estimator
        inputs = (s, a, next_s)
        if backward:
            self.rewarder.update_irl(inputs, batchsz, epoch)
        else:
            best[1] = self.rewarder.update_irl(inputs, batchsz, epoch, best[1])

        # 3. get estimated V(s) and PI_old(s, a)
        # actually, PI_old(s, a) can be saved when interacting with env, so as to save the time of one forward elapsed
        # v: [b, 1] => [b]
        v = self.value(s).squeeze(-1).detach()
        log_pi_old_sa = self.policy.get_log_prob(s, a).detach()

        # 4. estimate advantage and v_target according to GAE and Bellman Equation
        r = self.rewarder.estimate(s, a, next_s, log_pi_old_sa).detach()
        A_sa, v_target = self.est_adv(r, v, mask)
        if backward:
            logging.debug('<<dialog policy>> epoch {}, reward {}'.format(
                epoch,
                r.mean().item()))
        else:
            reward = r.mean().item()
            logging.debug(
                '<<dialog policy>> validation, epoch {}, reward {}'.format(
                    epoch, reward))
            if reward > best[2]:
                logging.info('<<dialog policy>> best model saved')
                best[2] = reward
                self.save(self.save_dir, 'best', True)
            with open(self.save_dir + '/best.pkl', 'wb') as f:
                pickle.dump(best, f)
            return best

        # 5. update dialog policy
        for i in range(self.update_round):

            # 1. shuffle current batch
            perm = torch.randperm(batchsz)
            # shuffle the variable for mutliple optimize
            v_target_shuf, A_sa_shuf, s_shuf, a_shuf, log_pi_old_sa_shuf = v_target[perm], A_sa[perm], s[perm], a[perm], \
                                                                           log_pi_old_sa[perm]

            # 2. get mini-batch for optimizing
            optim_chunk_num = int(np.ceil(batchsz / self.optim_batchsz))
            # chunk the optim_batch for total batch
            v_target_shuf, A_sa_shuf, s_shuf, a_shuf, log_pi_old_sa_shuf = torch.chunk(v_target_shuf, optim_chunk_num), \
                                                                           torch.chunk(A_sa_shuf, optim_chunk_num), \
                                                                           torch.chunk(s_shuf, optim_chunk_num), \
                                                                           torch.chunk(a_shuf, optim_chunk_num), \
                                                                           torch.chunk(log_pi_old_sa_shuf,
                                                                                       optim_chunk_num)
            # 3. iterate all mini-batch to optimize
            policy_loss, value_loss = 0., 0.
            for v_target_b, A_sa_b, s_b, a_b, log_pi_old_sa_b in zip(
                    v_target_shuf, A_sa_shuf, s_shuf, a_shuf,
                    log_pi_old_sa_shuf):
                # print('optim:', batchsz, v_target_b.size(), A_sa_b.size(), s_b.size(), a_b.size(), log_pi_old_sa_b.size())
                # 1. update value network
                self.value_optim.zero_grad()
                v_b = self.value(s_b).squeeze(-1)
                loss = (v_b - v_target_b).pow(2).mean()
                value_loss += loss.item()

                # backprop
                loss.backward()
                # nn.utils.clip_grad_norm(self.value.parameters(), 4)
                self.value_optim.step()

                # 2. update policy network by clipping
                self.policy_optim.zero_grad()
                # [b, 1]
                log_pi_sa = self.policy.get_log_prob(s_b, a_b)
                # ratio = exp(log_Pi(a|s) - log_Pi_old(a|s)) = Pi(a|s) / Pi_old(a|s)
                # we use log_pi for stability of numerical operation
                # [b, 1] => [b]
                ratio = (log_pi_sa - log_pi_old_sa_b).exp().squeeze(-1)
                surrogate1 = ratio * A_sa_b
                surrogate2 = torch.clamp(ratio, 1 - self.epsilon,
                                         1 + self.epsilon) * A_sa_b
                # this is element-wise comparing.
                # we add negative symbol to convert gradient ascent to gradient descent
                surrogate = -torch.min(surrogate1, surrogate2).mean()
                policy_loss += surrogate.item()

                # backprop
                surrogate.backward()
                # gradient clipping, for stability
                torch.nn.utils.clip_grad_norm(self.policy.parameters(), 10)
                # self.lock.acquire() # retain lock to update weights
                self.policy_optim.step()
                # self.lock.release() # release lock

            value_loss /= optim_chunk_num
            policy_loss /= optim_chunk_num
            logging.debug(
                '<<dialog policy>> epoch {}, iteration {}, value, loss {}'.
                format(epoch, i, value_loss))
            logging.debug(
                '<<dialog policy>> epoch {}, iteration {}, policy, loss {}'.
                format(epoch, i, policy_loss))

        if (epoch + 1) % self.save_per_epoch == 0:
            self.save(self.save_dir, epoch)
            with open(self.save_dir + '/' + str(epoch) + '.pkl', 'wb') as f:
                pickle.dump(best, f)
        self.policy.eval()
        self.value.eval()

    def sample(self, batchsz):
        """
        Given batchsz number of task, the batchsz will be splited equally to each processes
        and when processes return, it merge all data and return
        :param batchsz:
        :return: batch
        """

        # batchsz will be splitted into each process,
        # final batchsz maybe larger than batchsz parameters
        process_batchsz = np.ceil(batchsz / self.process_num).astype(np.int32)
        # buffer to save all data
        queue = mp.Queue()

        # start processes for pid in range(1, processnum)
        # if processnum = 1, this part will be ignored.
        # when save tensor in Queue, the process should keep alive till Queue.get(),
        # please refer to : https://discuss.pytorch.org/t/using-torch-tensor-over-multiprocessing-queue-process-fails/2847
        # however still some problem on CUDA tensors on multiprocessing queue,
        # please refer to : https://discuss.pytorch.org/t/cuda-tensors-on-multiprocessing-queue/28626
        # so just transform tensors into numpy, then put them into queue.
        evt = mp.Event()
        processes = []
        for i in range(self.process_num):
            process_args = (i, queue, evt, self.env_list[i], self.policy,
                            process_batchsz)
            processes.append(mp.Process(target=sampler, args=process_args))
        for p in processes:
            # set the process as daemon, and it will be killed once the main process is stoped.
            p.daemon = True
            p.start()

        # we need to get the first Memory object and then merge others Memory use its append function.
        pid0, buff0 = queue.get()
        for _ in range(1, self.process_num):
            pid, buff_ = queue.get()
            buff0.append(buff_)  # merge current Memory into buff0
        evt.set()

        # now buff saves all the sampled data
        buff = buff0

        return buff.get_batch()

    def evaluate(self):
        env = self.env_list[0]
        traj_len = 40
        reward_tot, turn_tot, inform_tot, match_tot, success_tot = [], [], [], [], []
        for seed in range(1000):
            s = env.reset(seed)
            print('seed', seed)
            print('goal', env.goal.domain_goals)
            print('usr', s['user_action'])
            turn = traj_len
            reward = []
            value = []
            mask = []
            for t in range(traj_len):
                s_vec = torch.Tensor(state_vectorize(s, env.cfg,
                                                     env.db)).to(device=DEVICE)
                # mode with policy during evaluation
                a = self.policy.select_action(s_vec, False)
                next_s, done = env.step(s, a.cpu())
                next_s_vec = torch.Tensor(
                    state_vectorize(next_s, env.cfg, env.db)).to(device=DEVICE)
                log_pi = self.policy.get_log_prob(s_vec, a)
                r = self.rewarder.estimate(s_vec, a, next_s_vec, log_pi)
                v = self.value(s_vec).squeeze(-1)
                reward.append(r.item())
                value.append(v.item())
                s = next_s
                print('sys', s['last_sys_action'])
                print('usr', s['user_action'])
                if done:
                    mask.append(0)
                    turn = t + 2  # one due to counting from 0, the one for the last turn
                    break
                mask.append(1)

            reward_tot.append(np.mean(reward))
            turn_tot.append(turn)
            match_tot += self.evaluator.match_rate(s)
            inform_tot.append(self.evaluator.inform_F1(s))
            reward = torch.Tensor(reward)
            value = torch.Tensor(value)
            mask = torch.LongTensor(mask)
            A_sa, v_target = self.est_adv(reward, value, mask)
            print('turn', turn)
            #print('reward', A_sa.tolist())
            print('reward', v_target[0].item())
            match_session = self.evaluator.match_rate(s, True)
            print('match', match_session)
            inform_session = self.evaluator.inform_F1(s, True)
            print('inform', inform_session)
            if (match_session == 1 and inform_session[1] == 1) \
            or (match_session == 1 and inform_session[1] is None) \
            or (match_session is None and inform_session[1] == 1):
                print('success', 1)
                success_tot.append(1)
            else:
                print('success', 0)
                success_tot.append(0)

        logging.info('reward {}'.format(np.mean(reward_tot)))
        logging.info('turn {}'.format(np.mean(turn_tot)))
        logging.info('match {}'.format(np.mean(match_tot)))
        TP, FP, FN = np.sum(inform_tot, 0)
        prec = TP / (TP + FP)
        rec = TP / (TP + FN)
        F1 = 2 * prec * rec / (prec + rec)
        logging.info('inform rec {}, F1 {}'.format(rec, F1))
        logging.info('success {}'.format(np.mean(success_tot)))

    def save(self, directory, epoch, rl_only=False):
        if not os.path.exists(directory):
            os.makedirs(directory)

        if not rl_only:
            self.rewarder.save_irl(directory, epoch)

        torch.save(self.value.state_dict(),
                   directory + '/' + str(epoch) + '_ppo.val.mdl')
        torch.save(self.policy.state_dict(),
                   directory + '/' + str(epoch) + '_ppo.pol.mdl')

        logging.info(
            '<<dialog policy>> epoch {}: saved network to mdl'.format(epoch))

    def load(self, filename):
        self.rewarder.load_irl(filename)

        value_mdl = filename + '_ppo.val.mdl'
        policy_mdl = filename + '_ppo.pol.mdl'
        if os.path.exists(value_mdl):
            self.value.load_state_dict(torch.load(value_mdl))
            logging.info(
                '<<dialog policy>> loaded checkpoint from file: {}'.format(
                    value_mdl))
        if os.path.exists(policy_mdl):
            self.policy.load_state_dict(torch.load(policy_mdl))
            logging.info(
                '<<dialog policy>> loaded checkpoint from file: {}'.format(
                    policy_mdl))

        best_pkl = filename + '.pkl'
        if os.path.exists(best_pkl):
            with open(best_pkl, 'rb') as f:
                best = pickle.load(f)
        else:
            best = [float('inf'), float('inf'), float('-inf')]
        return best
Exemple #19
0
def model_fn(features, labels, mode, params):
    """
    This is a function for creating a computational tensorflow graph.
    The function is in format required by tf.estimator.
    """
    is_training = mode == tf.estimator.ModeKeys.TRAIN

    # the base network
    def backbone(images, is_training):
        if params['backbone'] == 'mobilenet':
            return mobilenet_v1(images,
                                is_training,
                                depth_multiplier=params['depth_multiplier'])
        elif params['backbone'] == 'shufflenet':
            return shufflenet_v2(images,
                                 is_training,
                                 depth_multiplier=str(
                                     params['depth_multiplier']))

    # add additional layers to the base network
    feature_extractor = RetinaNetFeatureExtractor(is_training, backbone)

    # ssd anchor maker
    anchor_generator = AnchorGenerator(strides=[8, 16, 32, 64, 128],
                                       scales=[32, 64, 128, 256, 512],
                                       scale_multipliers=[1.0, 1.4142],
                                       aspect_ratios=[1.0, 2.0, 0.5])
    num_anchors_per_location = anchor_generator.num_anchors_per_location

    # add layers that predict boxes and labels
    box_predictor = RetinaNetBoxPredictor(is_training, params['num_classes'],
                                          num_anchors_per_location)

    # collect everything on one place
    ssd = SSD(features['images'], feature_extractor, anchor_generator,
              box_predictor, params['num_classes'])

    # add nms to the graph
    if not is_training:
        predictions = ssd.get_predictions(
            score_threshold=params['score_threshold'],
            iou_threshold=params['iou_threshold'],
            max_boxes_per_class=params['max_boxes_per_class'])

    if mode == tf.estimator.ModeKeys.PREDICT:

        # because images are resized before
        # feeding them to the network
        box_scaler = features['box_scaler']
        predictions['boxes'] /= box_scaler

        export_outputs = tf.estimator.export.PredictOutput({
            name: tf.identity(tensor, name)
            for name, tensor in predictions.items()
        })
        return tf.estimator.EstimatorSpec(
            mode,
            predictions=predictions,
            export_outputs={'outputs': export_outputs})

    # add l2 regularization
    with tf.name_scope('weight_decay'):
        add_weight_decay(params['weight_decay'])
        regularization_loss = tf.losses.get_regularization_loss()

    # create localization and classification losses
    losses = ssd.loss(labels, params)
    tf.losses.add_loss(params['localization_loss_weight'] *
                       losses['localization_loss'])
    tf.losses.add_loss(params['classification_loss_weight'] *
                       losses['classification_loss'])
    tf.summary.scalar('regularization_loss', regularization_loss)
    tf.summary.scalar('localization_loss', losses['localization_loss'])
    tf.summary.scalar('classification_loss', losses['classification_loss'])
    total_loss = tf.losses.get_total_loss(add_regularization_losses=True)

    if mode == tf.estimator.ModeKeys.EVAL:

        batch_size = features['images'].shape[0].value
        assert batch_size == 1

        evaluator = Evaluator(num_classes=params['num_classes'])
        eval_metric_ops = evaluator.get_metric_ops(labels, predictions)

        return tf.estimator.EstimatorSpec(mode,
                                          loss=total_loss,
                                          eval_metric_ops=eval_metric_ops)

    assert mode == tf.estimator.ModeKeys.TRAIN
    with tf.variable_scope('learning_rate'):
        global_step = tf.train.get_global_step()
        learning_rate = tf.train.cosine_decay(params['initial_learning_rate'],
                                              global_step,
                                              decay_steps=params['num_steps'])
        tf.summary.scalar('learning_rate', learning_rate)

    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(update_ops), tf.variable_scope('optimizer'):
        optimizer = tf.train.AdamOptimizer(learning_rate)
        grads_and_vars = optimizer.compute_gradients(total_loss)
        train_op = optimizer.apply_gradients(grads_and_vars, global_step)

    for g, v in grads_and_vars:
        tf.summary.histogram(v.name[:-2] + '_hist', v)
        tf.summary.histogram(v.name[:-2] + '_grad_hist', g)

    with tf.control_dependencies([train_op]), tf.name_scope('ema'):
        ema = tf.train.ExponentialMovingAverage(decay=MOVING_AVERAGE_DECAY,
                                                num_updates=global_step)
        train_op = ema.apply(tf.trainable_variables())

    return tf.estimator.EstimatorSpec(mode, loss=total_loss, train_op=train_op)
Exemple #20
0
    weight = np.load(classes_weights_path)
else:
    weight = calculate_weigths_labels(dataset, dataloader, 18)
weight = torch.from_numpy(weight.astype(np.float32))
"""
5.2、定义损失函数

"""

criterion = SegmentationLosses(weight=weight, cuda=False).build_loss(mode="ce")
"""
6、定义评价指标

"""

evaluator = Evaluator(18)
"""
7、定义学习率调度器

"""

scheduler = LR_Scheduler(lr_scheduler, lr, epochs, len(dataloader))
"""
8、使用预定义模型,并判断是否使用cuda

if os.path.isdir(model_save):
    try:
        checkpoint = torch.load(model_save+'model.t7', map_location='cpu')
        model.load_state_dict(checkpoint['state'])
        start_epoch = checkpoint['epoch']
        print('===> Load last checkpoint data')
def main():
    nclass = 7
    lr = 0.01
    num_epochs = 400
    batch_size = 4
    best_pred = 0.0
    drop_last = True

    train_loader, val_loader = make_dataloader(batch_size=batch_size,
                                               drop_last=drop_last)

    model = DeepLab(num_classes=nclass, output_stride=16, freeze_bn=False)

    train_params = [{
        'params': model.get_1x_lr_params(),
        'lr': lr
    }, {
        'params': model.get_10x_lr_params(),
        'lr': lr * 10
    }]

    optimizer = torch.optim.SGD(train_params,
                                momentum=0.9,
                                weight_decay=5e-4,
                                nesterov=False)
    criterion = SegmentationLosses(weight=None,
                                   cuda=True).build_loss(mode='ce')
    evaluator = Evaluator(nclass)
    scheduler = LR_Scheduler(mode='poly',
                             base_lr=lr,
                             num_epochs=num_epochs,
                             iters_per_epoch=len(train_loader))
    model = model.cuda()

    for epoch in range(num_epochs):

        train_loss = 0.0
        count = 0
        model.train()
        for i, sample in enumerate(train_loader):
            image, target = sample['image'], sample['label']
            image, target = image.cuda(), target.cuda()
            scheduler(optimizer, i, epoch, best_pred)
            optimizer.zero_grad()
            output = model(image)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            train_loss += loss.item()
            count += 1
        train_loss = train_loss / count
        print(
            'Training  [Epoch: %d, best_pred: %.4f, numImages: %5d, Loss: %.3f]'
            % (epoch, best_pred, i * batch_size + image.data.shape[0],
               train_loss))
        writer.add_scalar('scalar/loss_seg_train', train_loss, epoch)

        model.eval()
        evaluator.reset()
        test_loss = 0.0
        count = 0
        for i, sample in enumerate(val_loader):
            image, target = sample['image'], sample['label']
            image, target = image.cuda(), target.cuda()
            with torch.no_grad():
                output = model(image)
            loss = criterion(output, target)
            test_loss += loss.item()
            count += 1
            pred = output.data.cpu().numpy()
            target = target.cpu().numpy()
            pred = np.argmax(pred, axis=1)
            # Add batch sample into evaluator
            evaluator.add_batch(target, pred)

        # Fast test during the training
        test_loss = test_loss / count
        Acc = evaluator.Pixel_Accuracy()
        Acc_class = evaluator.Pixel_Accuracy_Class()
        mIoU = evaluator.Mean_Intersection_over_Union()
        FWIoU = evaluator.Frequency_Weighted_Intersection_over_Union()

        print('Validation  [Epoch: %d, numImages: %5d, Loss: %.3f]' %
              (epoch, i * batch_size + image.data.shape[0], test_loss))
        print("Acc:{}, Acc_class:{}, mIoU:{}, fwIoU: {}".format(
            Acc, Acc_class, mIoU, FWIoU))
        writer.add_scalar('scalar/loss_seg_val', test_loss, epoch)
        writer.add_scalar('scalar/Acc_val', Acc, epoch)
        writer.add_scalar('scalar/Acc_class_val', Acc_class, epoch)
        writer.add_scalar('scalar/mIou_val', mIoU, epoch)
        writer.add_scalar('scalar/FWIou_val', FWIoU, epoch)
        path = '/home/user/'
        if mIoU > best_pred:
            best_pred = mIoU
            torch.save(model.state_dict(), path + 'model_params.pkl')
            print('save the segmentation ' + str(epoch) +
                  'model, replace the previous parameters')
Exemple #22
0
class Trainer:
    def __init__(self, settings):
        self.settings = settings

        self.device = torch.device(
            "cuda" if len(self.settings.gpu_devices) else "cpu")
        self.gpu_devices = ','.join([str(id) for id in settings.gpu_devices])
        os.environ["CUDA_VISIBLE_DEVICES"] = self.gpu_devices

        self.log_path = os.path.join(self.settings.log_dir,
                                     self.settings.model_name)

        # checking the input height and width are multiples of 32
        assert self.settings.height % 32 == 0, "input height must be a multiple of 32"
        assert self.settings.width % 32 == 0, "input width must be a multiple of 32"

        # data
        datasets_dict = {
            "3d60": datasets.ThreeD60,
            "panosuncg": datasets.PanoSunCG,
            "stanford2d3d": datasets.Stanford2D3D,
            "matterport3d": datasets.Matterport3D
        }
        self.dataset = datasets_dict[self.settings.dataset]
        self.settings.cube_w = self.settings.height // 2

        fpath = os.path.join(os.path.dirname(__file__), "datasets",
                             "{}_{}.txt")

        train_file_list = fpath.format(self.settings.dataset, "train")
        val_file_list = fpath.format(self.settings.dataset, "val")

        train_dataset = self.dataset(
            self.settings.data_path,
            train_file_list,
            self.settings.height,
            self.settings.width,
            self.settings.disable_color_augmentation,
            self.settings.disable_LR_filp_augmentation,
            self.settings.disable_yaw_rotation_augmentation,
            is_training=True)
        self.train_loader = DataLoader(train_dataset,
                                       self.settings.batch_size,
                                       True,
                                       num_workers=self.settings.num_workers,
                                       pin_memory=True,
                                       drop_last=True)
        num_train_samples = len(train_dataset)
        self.num_total_steps = num_train_samples // self.settings.batch_size * self.settings.num_epochs

        val_dataset = self.dataset(
            self.settings.data_path,
            val_file_list,
            self.settings.height,
            self.settings.width,
            self.settings.disable_color_augmentation,
            self.settings.disable_LR_filp_augmentation,
            self.settings.disable_yaw_rotation_augmentation,
            is_training=False)
        self.val_loader = DataLoader(val_dataset,
                                     self.settings.batch_size,
                                     False,
                                     num_workers=self.settings.num_workers,
                                     pin_memory=True,
                                     drop_last=True)
        # network
        Net_dict = {"UniFuse": UniFuse, "Equi": Equi}
        Net = Net_dict[self.settings.net]

        self.model = Net(self.settings.num_layers,
                         self.settings.height,
                         self.settings.width,
                         self.settings.imagenet_pretrained,
                         train_dataset.max_depth_meters,
                         fusion_type=self.settings.fusion,
                         se_in_fusion=self.settings.se_in_fusion)

        self.model.to(self.device)
        self.parameters_to_train = list(self.model.parameters())

        self.optimizer = optim.Adam(self.parameters_to_train,
                                    self.settings.learning_rate)

        if self.settings.load_weights_dir is not None:
            self.load_model()

        print("Training model named:\n ", self.settings.model_name)
        print("Models and tensorboard events files are saved to:\n",
              self.settings.log_dir)
        print("Training is using:\n ", self.device)

        self.compute_loss = BerhuLoss()
        self.evaluator = Evaluator()

        self.writers = {}
        for mode in ["train", "val"]:
            self.writers[mode] = SummaryWriter(
                os.path.join(self.log_path, mode))

        self.save_settings()

    def train(self):
        """Run the entire training pipeline
        """
        self.epoch = 0
        self.step = 0
        self.start_time = time.time()
        self.validate()
        for self.epoch in range(self.settings.num_epochs):
            self.train_one_epoch()
            self.validate()
            if (self.epoch + 1) % self.settings.save_frequency == 0:
                self.save_model()

    def train_one_epoch(self):
        """Run a single epoch of training
        """
        self.model.train()

        pbar = tqdm.tqdm(self.train_loader)
        pbar.set_description("Training Epoch_{}".format(self.epoch))

        for batch_idx, inputs in enumerate(pbar):

            outputs, losses = self.process_batch(inputs)

            self.optimizer.zero_grad()
            losses["loss"].backward()
            self.optimizer.step()

            # log less frequently after the first 1000 steps to save time & disk space
            early_phase = batch_idx % self.settings.log_frequency == 0 and self.step < 1000
            late_phase = self.step % 1000 == 0

            if early_phase or late_phase:

                pred_depth = outputs["pred_depth"].detach()
                gt_depth = inputs["gt_depth"]
                mask = inputs["val_mask"]

                depth_errors = compute_depth_metrics(gt_depth, pred_depth,
                                                     mask)
                for i, key in enumerate(self.evaluator.metrics.keys()):
                    losses[key] = np.array(depth_errors[i].cpu())

                self.log("train", inputs, outputs, losses)

            self.step += 1

    def process_batch(self, inputs):
        for key, ipt in inputs.items():
            if key not in ["rgb", "cube_rgb"]:
                inputs[key] = ipt.to(self.device)

        losses = {}

        equi_inputs = inputs["normalized_rgb"]

        cube_inputs = inputs["normalized_cube_rgb"]

        outputs = self.model(equi_inputs, cube_inputs)

        losses["loss"] = self.compute_loss(inputs["gt_depth"],
                                           outputs["pred_depth"],
                                           inputs["val_mask"])

        return outputs, losses

    def validate(self):
        """Validate the model on the validation set
        """
        self.model.eval()

        self.evaluator.reset_eval_metrics()

        pbar = tqdm.tqdm(self.val_loader)
        pbar.set_description("Validating Epoch_{}".format(self.epoch))

        with torch.no_grad():
            for batch_idx, inputs in enumerate(pbar):
                outputs, losses = self.process_batch(inputs)
                pred_depth = outputs["pred_depth"].detach()
                gt_depth = inputs["gt_depth"]
                mask = inputs["val_mask"]
                self.evaluator.compute_eval_metrics(gt_depth, pred_depth, mask)

        for i, key in enumerate(self.evaluator.metrics.keys()):
            losses[key] = np.array(self.evaluator.metrics[key].avg.cpu())
        self.log("val", inputs, outputs, losses)
        del inputs, outputs, losses

    def log(self, mode, inputs, outputs, losses):
        """Write an event to the tensorboard events file
        """
        writer = self.writers[mode]
        for l, v in losses.items():
            writer.add_scalar("{}".format(l), v, self.step)

        for j in range(min(
                4,
                self.settings.batch_size)):  # write a maxmimum of four images
            writer.add_image("rgb/{}".format(j), inputs["rgb"][j].data,
                             self.step)
            writer.add_image("cube_rgb/{}".format(j),
                             inputs["cube_rgb"][j].data, self.step)
            writer.add_image(
                "gt_depth/{}".format(j),
                inputs["gt_depth"][j].data / inputs["gt_depth"][j].data.max(),
                self.step)
            writer.add_image(
                "pred_depth/{}".format(j), outputs["pred_depth"][j].data /
                outputs["pred_depth"][j].data.max(), self.step)

    def save_settings(self):
        """Save settings to disk so we know what we ran this experiment with
        """
        models_dir = os.path.join(self.log_path, "models")
        if not os.path.exists(models_dir):
            os.makedirs(models_dir)
        to_save = self.settings.__dict__.copy()

        with open(os.path.join(models_dir, 'settings.json'), 'w') as f:
            json.dump(to_save, f, indent=2)

    def save_model(self):
        """Save model weights to disk
        """
        save_folder = os.path.join(self.log_path, "models",
                                   "weights_{}".format(self.epoch))
        if not os.path.exists(save_folder):
            os.makedirs(save_folder)

        save_path = os.path.join(save_folder, "{}.pth".format("model"))
        to_save = self.model.state_dict()
        # save resnet layers - these are needed at prediction time
        to_save['layers'] = self.settings.num_layers
        # save the input sizes
        to_save['height'] = self.settings.height
        to_save['width'] = self.settings.width
        # save the dataset to train on
        to_save['dataset'] = self.settings.dataset
        to_save['net'] = self.settings.net
        to_save['fusion'] = self.settings.fusion
        to_save['se_in_fusion'] = self.settings.se_in_fusion

        torch.save(to_save, save_path)

        save_path = os.path.join(save_folder, "{}.pth".format("adam"))
        torch.save(self.optimizer.state_dict(), save_path)

    def load_model(self):
        """Load model from disk
        """
        self.settings.load_weights_dir = os.path.expanduser(
            self.settings.load_weights_dir)

        assert os.path.isdir(self.settings.load_weights_dir), \
            "Cannot find folder {}".format(self.settings.load_weights_dir)
        print("loading model from folder {}".format(
            self.settings.load_weights_dir))

        path = os.path.join(self.settings.load_weights_dir,
                            "{}.pth".format("model"))
        model_dict = self.model.state_dict()
        pretrained_dict = torch.load(path)
        pretrained_dict = {
            k: v
            for k, v in pretrained_dict.items() if k in model_dict
        }
        model_dict.update(pretrained_dict)
        self.model.load_state_dict(model_dict)

        # loading adam state
        optimizer_load_path = os.path.join(self.settings.load_weights_dir,
                                           "adam.pth")
        if os.path.isfile(optimizer_load_path):
            print("Loading Adam weights")
            optimizer_dict = torch.load(optimizer_load_path)
            self.optimizer.load_state_dict(optimizer_dict)
        else:
            print("Cannot find Adam weights so Adam is randomly initialized")
Exemple #23
0
    def __init__(self,
                 env_cls,
                 args,
                 manager,
                 cfg,
                 process_num,
                 pre=False,
                 pre_irl=False,
                 infer=False,
                 realtrain=False):
        """
        :param env_cls: env class or function, not instance, as we need to create several instance in class.
        :param args:
        :param manager:
        :param cfg:
        :param process_num: process number
        :param pre: set to pretrain mode
        :param infer: set to test mode
        """
        self.cfg = cfg
        self.policy_clip = args.policy_clip
        self.train_direc = args.train_direc
        self.realtrain = realtrain
        self.process_num = process_num
        self.human_reward = human_reward(args, cfg)
        self.gan_type = args.gan_type
        # initialize envs for each process
        self.env_list = []
        for _ in range(process_num):
            self.env_list.append(env_cls())

        self.policy = MultiDiscretePolicy(cfg).to(device=DEVICE)
        self.value = Value(cfg).to(device=DEVICE)
        logging.info(summary(self.policy, show_weights=False))
        # logging.info(summary(self.value , show_weights=False))

        self.multi_entropy_loss = nn.MultiLabelSoftMarginLoss()
        self.loss = nn.BCELoss()

        # if pre:
        self.print_per_batch = args.print_per_batch
        from dbquery import DBQuery
        db = DBQuery(args.data_dir)
        self.data_train = manager.create_dataset_seq('train', args.batchsz,
                                                     cfg, db)
        self.data_valid = manager.create_dataset_seq('valid', args.batchsz,
                                                     cfg, db)
        self.data_test = manager.create_dataset_seq('test', args.batchsz, cfg,
                                                    db)
        self.multi_entropy_loss = nn.MultiLabelSoftMarginLoss()
        self.evaluator = Evaluator(args.data_dir, cfg)

        # else:
        #     # self.rewarder = RewardEstimator(args, manager, cfg, pretrain=pre_irl, inference=infer, feature_extractor=self.policy)
        #     self.rewarder = DiscEstimator(args, manager, cfg, pretrain=pre_irl, inference=infer)
        #     self.evaluator = Evaluator(args.data_dir, cfg)
        #     from dbquery import DBQuery
        #     db = DBQuery(args.data_dir)
        #     self.data_train = manager.create_dataset_seq('train', args.batchsz, cfg, db)
        self.expert_iter = iter(self.data_train)

        self.save_dir = args.save_dir
        self.save_per_epoch = args.save_per_epoch
        self.optim_batchsz = args.batchsz
        self.update_round = args.update_round
        self.policy.eval()

        self.gamma = args.gamma
        self.epsilon = args.epsilon
        self.tau = args.tau
        self.policy_optim = optim.Adam(self.policy.parameters(), lr=args.lr_rl)
        self.value_optim = optim.Adam(self.value.parameters(), lr=args.lr_rl)
        self.mt_factor = args.mt_factor
        self.epoch = 0
        self.best_valid_loss = np.inf
        self.valid_loss_threshold = np.inf
        self.patience = 10
Exemple #24
0
class DiaSeq(object):
    def __init__(self,
                 env_cls,
                 args,
                 manager,
                 cfg,
                 process_num,
                 pre=False,
                 pre_irl=False,
                 infer=False,
                 realtrain=False):
        """
        :param env_cls: env class or function, not instance, as we need to create several instance in class.
        :param args:
        :param manager:
        :param cfg:
        :param process_num: process number
        :param pre: set to pretrain mode
        :param infer: set to test mode
        """
        self.cfg = cfg
        self.policy_clip = args.policy_clip
        self.train_direc = args.train_direc
        self.realtrain = realtrain
        self.process_num = process_num
        self.human_reward = human_reward(args, cfg)
        self.gan_type = args.gan_type
        # initialize envs for each process
        self.env_list = []
        for _ in range(process_num):
            self.env_list.append(env_cls())

        self.policy = MultiDiscretePolicy(cfg).to(device=DEVICE)
        self.value = Value(cfg).to(device=DEVICE)
        logging.info(summary(self.policy, show_weights=False))
        # logging.info(summary(self.value , show_weights=False))

        self.multi_entropy_loss = nn.MultiLabelSoftMarginLoss()
        self.loss = nn.BCELoss()

        # if pre:
        self.print_per_batch = args.print_per_batch
        from dbquery import DBQuery
        db = DBQuery(args.data_dir)
        self.data_train = manager.create_dataset_seq('train', args.batchsz,
                                                     cfg, db)
        self.data_valid = manager.create_dataset_seq('valid', args.batchsz,
                                                     cfg, db)
        self.data_test = manager.create_dataset_seq('test', args.batchsz, cfg,
                                                    db)
        self.multi_entropy_loss = nn.MultiLabelSoftMarginLoss()
        self.evaluator = Evaluator(args.data_dir, cfg)

        # else:
        #     # self.rewarder = RewardEstimator(args, manager, cfg, pretrain=pre_irl, inference=infer, feature_extractor=self.policy)
        #     self.rewarder = DiscEstimator(args, manager, cfg, pretrain=pre_irl, inference=infer)
        #     self.evaluator = Evaluator(args.data_dir, cfg)
        #     from dbquery import DBQuery
        #     db = DBQuery(args.data_dir)
        #     self.data_train = manager.create_dataset_seq('train', args.batchsz, cfg, db)
        self.expert_iter = iter(self.data_train)

        self.save_dir = args.save_dir
        self.save_per_epoch = args.save_per_epoch
        self.optim_batchsz = args.batchsz
        self.update_round = args.update_round
        self.policy.eval()

        self.gamma = args.gamma
        self.epsilon = args.epsilon
        self.tau = args.tau
        self.policy_optim = optim.Adam(self.policy.parameters(), lr=args.lr_rl)
        self.value_optim = optim.Adam(self.value.parameters(), lr=args.lr_rl)
        self.mt_factor = args.mt_factor
        self.epoch = 0
        self.best_valid_loss = np.inf
        self.valid_loss_threshold = np.inf
        self.patience = 10

    def retrieve_expert(self, to_device_=True):
        try:
            data = self.expert_iter.next()
        except StopIteration:
            self.expert_iter = iter(self.data_train)
            data = self.expert_iter.next()
            self.epoch += 1
        if to_device_:
            return to_device(data)
        else:
            return data

    def policy_loop(self, data):
        s, target_a, target_d = to_device(data)
        target_a = id2onehot(target_a)
        a_weights = self.policy(s)
        loss_a = self.multi_entropy_loss(a_weights, target_a)
        return loss_a

    def imitate_loop(self, data):
        s, target_a, target_d = to_device(data)
        target_a = id2onehot(target_a)
        a_weights = self.policy.imitate(s)
        loss_a = self.multi_entropy_loss(a_weights, target_a)
        return loss_a

    def prepare_data(self, data_batch):
        s_real, a_real_, next_s_real, d_real = to_device(data_batch)

    def update_loop(self, data):
        # gen_type: beam, greedy
        # mode: GEN, TEACH_FORCE
        # s, a, d, a_seq = self.retrieve_expert(True)
        s, _, _, a_seq = data
        s = s.to(device=DEVICE)
        a_seq = a_seq.to(device=DEVICE)
        loss = self.policy(s=s,
                           a_seq=a_seq[:, :self.cfg.max_len],
                           mode=TEACH_FORCE)
        return loss

    def train(self, epoch):
        """
        pretrain the policy by simple imitation learning (behavioral cloning)
        """
        self.policy.train()
        a_loss = 0.
        for i, data in enumerate(self.data_train):
            self.policy_optim.zero_grad()
            loss_a = self.update_loop(data)
            a_loss += loss_a.item()
            loss_a.backward()
            torch.nn.utils.clip_grad_norm_(self.policy.parameters(),
                                           self.policy_clip)
            self.policy_optim.step()

            if (i + 1) % self.print_per_batch == 0:
                a_loss /= self.print_per_batch
                logging.debug(
                    '<<dialog policy>> epoch {}, iter {}, loss_a:{}'.format(
                        epoch, i, a_loss))
                a_loss = 0.

        self.policy.eval()
        if (epoch + 1) % self.save_per_epoch == 0:
            self.save(self.save_dir, epoch, True)

        for i, data in enumerate(self.data_valid):
            loss_a = self.update_loop(data)
            a_loss += loss_a.item()
        valid_loss = a_loss / len(self.data_valid)
        logging.debug(
            '<<dialog policy>> validation, epoch {}, loss_a:{}'.format(
                epoch, valid_loss))
        if valid_loss < self.best_valid_loss:
            if valid_loss <= self.valid_loss_threshold * self.cfg.improve_threshold:
                self.patience = max(self.patience,
                                    epoch * self.cfg.patient_increase)
                self.valid_loss_threshold = valid_loss
                logging.info("Update patience to {}".format(self.patience))
            self.best_valid_loss = valid_loss

            logging.info('<<dialog policy>> best model saved')
            self.save(self.save_dir, 'best', True)

        if self.cfg.early_stop and self.patience <= epoch:
            if epoch < self.cfg.max_epoch:
                logging.info("!!Early stop due to run out of patience!!")

            logging.info("Best validation loss %f" % self.best_valid_loss)
            return True
        return False

    def sample(self, batchsz):
        """
        Given batchsz number of task, the batchsz will be splited equally to each processes
        and when processes return, it merge all data and return
        :param batchsz:
        :return: batch
        """

        # batchsz will be splitted into each process,
        # final batchsz maybe larger than batchsz parameters
        process_batchsz = np.ceil(batchsz / self.process_num).astype(np.int32)
        # buffer to save all data
        queue = mp.Queue()

        # start processes for pid in range(1, processnum)
        # if processnum = 1, this part will be ignored.
        # when save tensor in Queue, the process should keep alive till Queue.get(),
        # please refer to : https://discuss.pytorch.org/t/using-torch-tensor-over-multiprocessing-queue-process-fails/2847
        # however still some problem on CUDA tensors on multiprocessing queue,
        # please refer to : https://discuss.pytorch.org/t/cuda-tensors-on-multiprocessing-queue/28626
        # so just transform tensors into numpy, then put them into queue.
        evt = mp.Event()
        processes = []
        for i in range(self.process_num):
            process_args = (i, queue, evt, self.env_list[i], self.policy,
                            process_batchsz, self.human_reward)
            processes.append(mp.Process(target=sampler, args=process_args))
        for p in processes:
            # set the process as daemon, and it will be killed once the main process is stoped.
            p.daemon = True
            p.start()

        # we need to get the first Memory object and then merge others Memory use its append function.
        pid0, buff0 = queue.get()
        for _ in range(1, self.process_num):
            pid, buff_ = queue.get()
            buff0.append(buff_)  # merge current Memory into buff0
        evt.set()

        # now buff saves all the sampled data
        buff = buff0

        return buff.get_batch()

    def evaluate(self, save_dialog=False):
        self.policy.eval()
        if save_dialog:
            with open('./data/goal.json', 'r') as f:
                saved_goal_list = json.load(f)
        collected_dialog = []

        env = self.env_list[0]
        traj_len = 40
        reward_tot, turn_tot, inform_tot, match_tot, success_tot = [], [], [], [], []
        for seed in range(1000):
            dialog_list = []
            if save_dialog:
                s = env.reset(seed, saved_goal=saved_goal_list[seed])
            else:
                s = env.reset(seed, saved_goal=None)
            # print('seed', seed)
            # print('goal', env.goal.domain_goals)
            # print('usr', s['user_action'])
            dialog_list.append(s['user_action'])
            turn = traj_len
            reward = []
            value = []
            mask = []
            for t in range(traj_len):
                s_vec = torch.Tensor(state_vectorize(s, env.cfg,
                                                     env.db)).to(device=DEVICE)
                # mode with policy during evaluation
                a = self.policy.select_action(s_vec, False)
                next_s, done = env.step(s, a.cpu())
                next_s_vec = torch.Tensor(
                    state_vectorize(next_s, env.cfg, env.db)).to(device=DEVICE)
                r = self.human_reward.reward_human(next_s, done)
                reward.append(r)
                s = next_s
                dialog_list.append(s['last_sys_action'])
                dialog_list.append(s['user_action'])
                # print('sys', s['last_sys_action'])
                # print('usr', s['user_action'])
                if done:
                    mask.append(0)
                    turn = t + 2  # one due to counting from 0, the one for the last turn
                    break
                mask.append(1)

            reward_tot.append(np.mean(reward))
            turn_tot.append(turn)
            match_tot += self.evaluator.match_rate(s)
            inform_tot.append(self.evaluator.inform_F1(s))
            reward = torch.Tensor(reward)
            mask = torch.LongTensor(mask)
            # print('turn', turn)
            match_session = self.evaluator.match_rate(s, True)
            # print('match', match_session)
            inform_session = self.evaluator.inform_F1(s, True)
            # print('inform', inform_session)
            if (match_session == 1 and inform_session[1] == 1) \
            or (match_session == 1 and inform_session[1] is None) \
            or (match_session is None and inform_session[1] == 1):
                # print('success', 1)
                success_tot.append(1)
            else:
                # print('success', 0)
                success_tot.append(0)
            dialog_dict = {
                'goal id': seed,
                'goal': env.goal.domain_goals,
                'dialog': dialog_list,
                'turn': turn,
                'status': success_tot[-1]
            }
            collected_dialog.append(dialog_dict)

        logging.info('reward {}'.format(np.mean(reward_tot)))
        logging.info('turn {}'.format(np.mean(turn_tot)))
        logging.info('match {}'.format(np.mean(match_tot)))
        TP, FP, FN = np.sum(inform_tot, 0)
        prec = TP / (TP + FP)
        rec = TP / (TP + FN)
        F1 = 2 * prec * rec / (prec + rec)
        logging.info('inform rec {}, F1 {}'.format(rec, F1))
        logging.info('success {}'.format(np.mean(success_tot)))

        if save_dialog:
            self.save_dialog(self.save_dir, collected_dialog)

    def save_dialog(self, directory, collected_dialog):
        if not os.path.exists(directory):
            os.makedirs(directory)
        des_path = directory + '/' + 'collected_dialog.json'
        with open(des_path, 'w') as f:
            json.dump(collected_dialog, f, indent=4)

    def save(self, directory, epoch, rl_only=False):
        if not os.path.exists(directory):
            os.makedirs(directory)

        # if not rl_only:
        # self.rewarder.save_irl(directory, epoch)

        torch.save(self.value.state_dict(),
                   directory + '/' + str(epoch) + '_ppo.val.mdl')
        torch.save(self.policy.state_dict(),
                   directory + '/' + str(epoch) + '_ppo.pol.mdl')

        logging.info(
            '<<dialog policy>> epoch {}: saved network to mdl'.format(epoch))

    def load(self, filename):
        # self.rewarder.load_irl(filename)
        # if self.realtrain:
        # filename='model_saved_ori/model_agenda_pre_ori/best'
        # filename='model_saved/model_agenda_pre_mt_op_1.0/best'
        value_mdl = filename + '_ppo.val.mdl'
        policy_mdl = filename + '_ppo.pol.mdl'
        if os.path.exists(value_mdl):
            self.value.load_state_dict(torch.load(value_mdl))
            logging.info(
                '<<dialog policy>> loaded checkpoint from file: {}'.format(
                    value_mdl))
        if os.path.exists(policy_mdl):
            self.policy.load_state_dict(torch.load(policy_mdl))
            logging.info(
                '<<dialog policy>> loaded checkpoint from file: {}'.format(
                    policy_mdl))

        best_pkl = filename + '.pkl'
        if os.path.exists(best_pkl):
            with open(best_pkl, 'rb') as f:
                best = pickle.load(f)
        else:
            best = [float('inf'), float('inf'), float('-inf')]
        return best
Exemple #25
0
    def __init__(self, settings):
        self.settings = settings

        self.device = torch.device(
            "cuda" if len(self.settings.gpu_devices) else "cpu")
        self.gpu_devices = ','.join([str(id) for id in settings.gpu_devices])
        os.environ["CUDA_VISIBLE_DEVICES"] = self.gpu_devices

        self.log_path = os.path.join(self.settings.log_dir,
                                     self.settings.model_name)

        # checking the input height and width are multiples of 32
        assert self.settings.height % 32 == 0, "input height must be a multiple of 32"
        assert self.settings.width % 32 == 0, "input width must be a multiple of 32"

        # data
        datasets_dict = {
            "3d60": datasets.ThreeD60,
            "panosuncg": datasets.PanoSunCG,
            "stanford2d3d": datasets.Stanford2D3D,
            "matterport3d": datasets.Matterport3D
        }
        self.dataset = datasets_dict[self.settings.dataset]
        self.settings.cube_w = self.settings.height // 2

        fpath = os.path.join(os.path.dirname(__file__), "datasets",
                             "{}_{}.txt")

        train_file_list = fpath.format(self.settings.dataset, "train")
        val_file_list = fpath.format(self.settings.dataset, "val")

        train_dataset = self.dataset(
            self.settings.data_path,
            train_file_list,
            self.settings.height,
            self.settings.width,
            self.settings.disable_color_augmentation,
            self.settings.disable_LR_filp_augmentation,
            self.settings.disable_yaw_rotation_augmentation,
            is_training=True)
        self.train_loader = DataLoader(train_dataset,
                                       self.settings.batch_size,
                                       True,
                                       num_workers=self.settings.num_workers,
                                       pin_memory=True,
                                       drop_last=True)
        num_train_samples = len(train_dataset)
        self.num_total_steps = num_train_samples // self.settings.batch_size * self.settings.num_epochs

        val_dataset = self.dataset(
            self.settings.data_path,
            val_file_list,
            self.settings.height,
            self.settings.width,
            self.settings.disable_color_augmentation,
            self.settings.disable_LR_filp_augmentation,
            self.settings.disable_yaw_rotation_augmentation,
            is_training=False)
        self.val_loader = DataLoader(val_dataset,
                                     self.settings.batch_size,
                                     False,
                                     num_workers=self.settings.num_workers,
                                     pin_memory=True,
                                     drop_last=True)
        # network
        Net_dict = {"UniFuse": UniFuse, "Equi": Equi}
        Net = Net_dict[self.settings.net]

        self.model = Net(self.settings.num_layers,
                         self.settings.height,
                         self.settings.width,
                         self.settings.imagenet_pretrained,
                         train_dataset.max_depth_meters,
                         fusion_type=self.settings.fusion,
                         se_in_fusion=self.settings.se_in_fusion)

        self.model.to(self.device)
        self.parameters_to_train = list(self.model.parameters())

        self.optimizer = optim.Adam(self.parameters_to_train,
                                    self.settings.learning_rate)

        if self.settings.load_weights_dir is not None:
            self.load_model()

        print("Training model named:\n ", self.settings.model_name)
        print("Models and tensorboard events files are saved to:\n",
              self.settings.log_dir)
        print("Training is using:\n ", self.device)

        self.compute_loss = BerhuLoss()
        self.evaluator = Evaluator()

        self.writers = {}
        for mode in ["train", "val"]:
            self.writers[mode] = SummaryWriter(
                os.path.join(self.log_path, mode))

        self.save_settings()
Exemple #26
0
 def __init__(self, args, config):
     self.evaluator = Evaluator(args.data_dir, config)
Exemple #27
0
def model_fn(features, labels, mode, params, config):
    """This is a function for creating a computational tensorflow graph.
    The function is in format required by tf.estimator.
    """

    # choose a backbone network
    if params['backbone'] == 'resnet':
        feature_extractor = resnet
        checkpoint_scope = 'resnet_v1_50/'
    elif params['backbone'] == 'mobilenet':
        feature_extractor = lambda x: mobilenet(x, params['depth_multiplier'])
        checkpoint_scope = 'MobilenetV2/'
    elif params['backbone'] == 'shufflenet':
        feature_extractor = lambda x: shufflenet(
            x, str(params['depth_multiplier']))
        checkpoint_scope = 'ShuffleNetV2/'

    # build the main graph
    is_training = mode == tf.estimator.ModeKeys.TRAIN
    detector = Detector(features['images'], feature_extractor, is_training,
                        params)

    # use a pretrained backbone network
    if is_training:
        with tf.name_scope('init_from_checkpoint'):
            tf.train.init_from_checkpoint(params['pretrained_checkpoint'],
                                          {checkpoint_scope: checkpoint_scope})

    # add NMS to the graph
    if not is_training:
        predictions = detector.get_predictions(
            score_threshold=params['score_threshold'],
            iou_threshold=params['iou_threshold'],
            max_boxes_per_class=params['max_boxes_per_class'])

    if mode == tf.estimator.ModeKeys.PREDICT:

        w, h = tf.unstack(tf.to_float(
            features['images_size']))  # original image size
        s = tf.to_float(tf.shape(features['images']))  # size after resizing
        scaler = tf.stack([h / s[1], w / s[2], h / s[1], w / s[2]])
        predictions['boxes'] = scaler * predictions['boxes']

        export_outputs = tf.estimator.export.PredictOutput({
            name: tf.identity(tensor, name)
            for name, tensor in predictions.items()
        })
        return tf.estimator.EstimatorSpec(
            mode,
            predictions=predictions,
            export_outputs={'outputs': export_outputs})

    # add L2 regularization
    with tf.name_scope('weight_decay'):
        add_weight_decay(params['weight_decay'])
        regularization_loss = tf.losses.get_regularization_loss()

    # create localization and classification losses
    losses = detector.get_losses(labels, params)
    tf.losses.add_loss(params['alpha'] * losses['rpn_localization_loss'])
    tf.losses.add_loss(params['beta'] * losses['rpn_classification_loss'])
    tf.losses.add_loss(params['gamma'] * losses['roi_localization_loss'])
    tf.losses.add_loss(params['theta'] * losses['roi_classification_loss'])
    total_loss = tf.losses.get_total_loss(add_regularization_losses=True)

    tf.summary.scalar('regularization_loss', regularization_loss)
    tf.summary.scalar('rpn_localization_loss', losses['rpn_localization_loss'])
    tf.summary.scalar('rpn_classification_loss',
                      losses['rpn_classification_loss'])
    tf.summary.scalar('roi_localization_loss', losses['roi_localization_loss'])
    tf.summary.scalar('roi_classification_loss',
                      losses['roi_classification_loss'])

    if mode == tf.estimator.ModeKeys.EVAL:

        with tf.name_scope('evaluator'):
            evaluator = Evaluator(num_classes=params['num_classes'])
            eval_metric_ops = evaluator.get_metric_ops(labels, predictions)

        return tf.estimator.EstimatorSpec(mode,
                                          loss=total_loss,
                                          eval_metric_ops=eval_metric_ops)

    assert mode == tf.estimator.ModeKeys.TRAIN
    with tf.variable_scope('learning_rate'):
        global_step = tf.train.get_global_step()
        learning_rate = tf.train.piecewise_constant(global_step,
                                                    params['lr_boundaries'],
                                                    params['lr_values'])
        tf.summary.scalar('learning_rate', learning_rate)

    with tf.variable_scope('optimizer'):
        optimizer = tf.train.MomentumOptimizer(learning_rate,
                                               momentum=MOMENTUM,
                                               use_nesterov=USE_NESTEROV)
        grads_and_vars = optimizer.compute_gradients(total_loss)
        grads_and_vars = [(tf.clip_by_norm(g, GRADIENT_CLIP), v)
                          for g, v in grads_and_vars]
        train_op = optimizer.apply_gradients(grads_and_vars, global_step)

    for g, v in grads_and_vars:
        tf.summary.histogram(v.name[:-2] + '_hist', v)
        tf.summary.histogram(v.name[:-2] + '_grad_hist', g)

    with tf.control_dependencies([train_op]), tf.name_scope('ema'):
        ema = tf.train.ExponentialMovingAverage(decay=MOVING_AVERAGE_DECAY,
                                                num_updates=global_step)
        train_op = ema.apply(tf.trainable_variables())

    return tf.estimator.EstimatorSpec(mode, loss=total_loss, train_op=train_op)
def display_baseline(
    config: Config,
    graph: Graph,
    train_trajectories: Trajectories,
    test_trajectories: Trajectories,
    evaluator: Evaluator,
):
    """Compute baseline uniform random walk with/without

    Args:
        config (Config): [description]
        graph (Graph): graph
        train_trajectories (Trajectories): train trajectories
        test_trajectories (Trajectories): test trajectories
        evaluator (Evaluator): evaluator to compute metrics
    """

    graph = graph.add_self_loops(degree_zero_only=True)
    graph = graph.update(edges=torch.ones(graph.n_edge, device=graph.device))
    graph = graph.softmax_weights()
    print("Computing non backtracking edges...")
    graph.compute_non_backtracking_edges()
    print("Done")

    print("=== BASELINE ===")
    baseline_model = create_baseline(config, non_backtracking=False)

    print("TEST DATASET")
    evaluator.compute(baseline_model, graph, test_trajectories, None)
    print(colored(evaluator.to_string(), "green"))

    print("TRAIN DATASET")
    evaluator.compute(baseline_model, graph, train_trajectories, None)
    print(colored(evaluator.to_string(), "green"))

    print("=== NON BACKTRACKING BASELINE ===")
    nb_baseline_model = create_baseline(config, non_backtracking=True)

    print("TEST DATASET")
    evaluator.compute(nb_baseline_model, graph, test_trajectories, None)
    print(colored(evaluator.to_string(), "green"))

    print("TRAIN DATASET")
    evaluator.compute(nb_baseline_model, graph, train_trajectories, None)
    print(colored(evaluator.to_string(), "green"))
def main():
    # 配置设备
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    # 数据路径
    train_dir = './data_road/training'
    # 超参数
    num_epochs = 60
    learning_rate = 0.001
    img_size = (640, 192)
    num_class = 2
    SAVE_INTERVAL = 5
    evaluator = Evaluator(num_class=num_class)

    # 构建Dataset实例
    train_data = LaneDataset(data_dir=train_dir, img_size=img_size)
    train_loader = DataLoader(train_data, batch_size=2, shuffle=True)

    # 构建Model实例
    model = FCN8s(n_class=2)
    vgg16_path = "models/vgg16_from_caffe.pth"
    vgg16 = load_vgg16(model_file=vgg16_path)
    model.copy_params_from_vgg16(vgg16)
    model = model.to(device)
    print("模型加载成功!!!")

    # 定义损失函数和优化器
    criterion = nn.BCELoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, momentum=0.9, weight_decay=5e-4)

    Acc_list = []
    Acc_class_list = []
    mIoU_list = []
    FWIoU_list = []
    loss_list = []

    # 训练
    for epoch in range(num_epochs):
        train_loss = 0.0
        evaluator.reset()
        for i, (image, label) in enumerate(train_loader):
            image = image.to(device)
            label = label.to(device)

            optimizer.zero_grad()
            # 前向传播
            output = model(image)
            output = torch.sigmoid(output)
            loss = criterion(output, label)
            output = torch.argmax(output, dim=1).cpu().numpy()
            label = torch.argmax(label, dim=1).cpu().numpy()

            # 后向传播及优化
            loss.backward()
            train_loss += loss.item()
            optimizer.step()

            evaluator.add_batch(label, output)   # 添加output和label,用于后续评估

        # 计算像素准确率、平均像素准确率、平均交并比、频权交并比
        Acc = evaluator.Pixel_Accuracy()
        Acc_class = evaluator.Pixel_Accuracy_Class()
        mIoU = evaluator.Mean_Intersection_over_Union()
        FWIoU = evaluator.Frequency_Weighted_Intersection_over_Union()

        Acc_list.append(Acc)
        Acc_class_list.append(Acc_class)
        mIoU_list.append(mIoU)
        FWIoU_list.append(FWIoU)
        loss_list.append(train_loss/len(train_loader))

        # 保存模型
        if epoch % SAVE_INTERVAL == 0 or (epoch+1) == num_epochs:
            torch.save(model.state_dict(), './models/fcn8s_{}.pth'.format(epoch))
        print("Epoch_{}: train_loss: {:.6f} Acc: {:.4f} Acc_class: {:.4f} mIoU: {:.4f} FWIoU: {:.4f}"
              .format(epoch+1, train_loss/len(train_loader), Acc, Acc_class, mIoU, FWIoU))

    # 绘制曲线
    draw_figures(loss_list, title='train_loss')
    draw_figures(Acc_list, title='Acc')
    draw_figures(Acc_class_list, title='Acc_class')
    draw_figures(mIoU_list, title='mIoU')
    draw_figures(FWIoU_list, title='FWIoU')
    print("完成曲线绘制!!!")
def main():
    # print("BEGIN...")
    parser = argparse.ArgumentParser()
    parser.add_argument("config_file")
    parser.add_argument("--name")
    parser.add_argument("--bs")
    parser.add_argument("--lr")
    parser.add_argument("--loss")

    args = parser.parse_args()

    # load configuration
    writer = SummaryWriter()
    config = Config()
    config.load_from_file(args.config_file)
    # Hyperparameter logging
    if 'bs' in args:
        config.batch_size = int(args.bs)
    if 'lr' in args:
        config.lr = float(args.lr)
    if 'loss' in args:
        config.loss = args.loss
    writer.add_scalar('batch_size', config.batch_size)
    writer.add_scalar('lr', config.lr)
    writer.add_text('loss_func', config.loss)

    graph, trajectories, pairwise_node_features, _ = load_data(config)
    print("loaded data...")
    train_trajectories, valid_trajectories, test_trajectories = trajectories
    use_validation_set = len(valid_trajectories) > 0
    graph = graph.to(config.device)
    print("loaded device...")

    given_as_target, siblings_nodes = None, None
    if config.dataset == "wikispeedia":
        given_as_target, siblings_nodes = load_wiki_data(config)

    if pairwise_node_features is not None:
        pairwise_node_features = pairwise_node_features.to(config.device)

    if config.rw_edge_weight_see_number_step:  # TODO
        raise NotImplementedError

    if args.name is not None:
        print(f"Experiment name from CLI: {args.name}")
        config.name = args.name

    if not config.name:
        experiment_name = input("Give a name to this experiment? ").strip()
        config.name = experiment_name or config.date

    print(f'==== START "{config.name}" ====')

    torch.manual_seed(config.seed)

    if config.enable_checkpointing:
        chkpt_dir = os.path.join(config.workspace, config.checkpoint_directory,
                                 config.name)
        os.makedirs(chkpt_dir, exist_ok=True)
        print(f"Checkpoints will be saved in [{chkpt_dir}]")

    d_node = graph.nodes.shape[1] if graph.nodes is not None else 0
    d_edge = graph.edges.shape[1] if graph.edges is not None else 0
    print(
        f"Number of node features {d_node}. Number of edge features {d_edge}")

    model = create_model(graph, pairwise_node_features, config)
    model = model.to(config.device)

    optimizer = create_optimizer(model.parameters(), config)

    if config.restore_from_checkpoint:
        filename = input("Checkpoint file: ")
        checkpoint_data = torch.load(filename)
        model.load_state_dict(checkpoint_data["model_state_dict"])
        optimizer.load_state_dict(checkpoint_data["optimizer_state_dict"])
        print("Loaded parameters from checkpoint")

    def create_evaluator():
        return Evaluator(
            graph.n_node,
            given_as_target=given_as_target,
            siblings_nodes=siblings_nodes,
            config=config,
        )

    if use_validation_set:
        valid_evaluator = Evaluator(
            graph.n_node,
            given_as_target=given_as_target,
            siblings_nodes=siblings_nodes,
            config=config,
        )

    if config.compute_baseline:
        display_baseline(config, graph, train_trajectories, test_trajectories,
                         create_evaluator())

    graph = graph.add_self_loops(
        degree_zero_only=config.self_loop_deadend_only,
        edge_value=config.self_loop_weight)

    if config.rw_non_backtracking:
        print("Computing non backtracking graph...", end=" ")
        sys.stdout.flush()
        graph.compute_non_backtracking_edges()
        print("Done")

    evaluate(model,
             graph,
             test_trajectories,
             pairwise_node_features,
             create_evaluator,
             dataset="TEST")
    if use_validation_set:
        evaluate(
            model,
            graph,
            valid_trajectories,
            pairwise_node_features,
            create_evaluator,
            dataset="EVAL",
        )

    for epoch in range(config.number_epoch):

        print(f"\n=== EPOCH {epoch} ===")

        model.train()
        train_epoch(model, graph, optimizer, config, train_trajectories,
                    pairwise_node_features)

        # VALID and TEST metrics computation
        test_evaluator = evaluate(
            model,
            graph,
            test_trajectories,
            pairwise_node_features,
            create_evaluator,
            dataset="TEST",
        )
        writer.add_scalar('precision_top1',
                          test_evaluator.metrics['precision_top1'].mean(),
                          epoch)
        writer.add_scalar('precision_top5',
                          test_evaluator.metrics['precision_top5'].mean(),
                          epoch)
        writer.add_scalar('target_p',
                          test_evaluator.metrics['target_probability'].mean(),
                          epoch)
        writer.add_scalar('choice_acc',
                          test_evaluator.metrics['choice_accuracy'].mean(),
                          epoch)

        valid_evaluator = None
        if use_validation_set:
            valid_evaluator = evaluate(
                model,
                graph,
                valid_trajectories,
                pairwise_node_features,
                create_evaluator,
                dataset="EVAL",
            )

        if config.enable_checkpointing and epoch % config.chechpoint_every_num_epoch == 0:
            print("Checkpointing...")
            directory = os.path.join(config.workspace,
                                     config.checkpoint_directory, config.name)
            chkpt_file = os.path.join(directory, f"{epoch:04d}.pt")
            torch.save(
                {
                    "epoch": epoch,
                    "model_state_dict": model.state_dict(),
                    "optimizer_state_dict": optimizer.state_dict(),
                },
                chkpt_file,
            )
            config_file = os.path.join(directory, "config")
            config.save_to_file(config_file)

            metrics_file = os.path.join(directory, f"{epoch:04d}.txt")
            with open(metrics_file, "w") as f:
                f.write(test_evaluator.to_string())
                if valid_evaluator:
                    f.write("\n\n=== VALIDATION ==\n\n")
                    f.write(valid_evaluator.to_string())

            print(colored(f"Checkpoint saved in {chkpt_file}", "blue"))