def train_hold_out(model, criterion, optimizer, args, train_set, val_set, test_set, single_view=False): """ Perform a train with validation train split on the given model. Use args.val_split_size to set the percentage of data for the validation set. Keep in mind the two validation sets are genereted. One for early stopping and one to evaluate the model. All the data are sent to wandb or logged on a text file Parameters ---------- model : RotaitonNet model criterion : Pytorch criterion (CrossEntropy for RotationNet) optimizer : Pytorch optimizer (e.g. SGD) args : Input args from the parser Returns ------- Nothing """ # Generate loaders test_loader = DataLoader(test_set, batch_size=args.batch_size, shuffle=single_view, num_workers=args.workers, pin_memory=True, drop_last=True) val_loader = DataLoader(val_set, batch_size=args.batch_size, shuffle=single_view, num_workers=args.workers, pin_memory=True, drop_last=True) train_loader = DataLoader(train_set, batch_size=args.batch_size, shuffle=single_view, num_workers=args.workers, pin_memory=True, drop_last=True) # Track model in wandb #wandb.init(project="MVCNN", config=args, reinit=True) # wandb.watch(model) train(model, criterion, optimizer, train_loader, val_loader, args, single_view) load_model(model, args.fname_best) val_statistics = validate(test_loader, model, criterion, args, single_view) log_summary(val_statistics, "val", test_loader.dataset.dataset.classes)
def train_hold_out(model, criterion, optimizer, args): """ Perform a train with validation train split on the given model. Use args.val_split_size to set the percentage of data for the validation set. Keep in mind the two validation sets are genereted. One for early stopping and one to evaluate the model. All the data are sent to wandb or logged on a text file Parameters ---------- model : RotaitonNet model criterion : Pytorch criterion (CrossEntropy for RotationNet) optimizer : Pytorch optimizer (e.g. SGD) args : Input args from the parser Returns ------- Nothing """ trans = [] if args.flip: # flip is with 0.5 probability trans.append(transforms.RandomHorizontalFlip()) trans.append(transforms.RandomVerticalFlip()) if args.rotation: trans.append(transforms.RandomRotation((0, 90), expand=args.rotation_expand)) # if expand is true then resize the image to the right size if args.rotation_expand: trans.append(transforms.Resize(224)) # Get full train dataset # Create two different sets but one with and one without transformations (random rotation and flip) if args.depth: # create one element tuple to be consistent with ImageFolder dataset of Pytorch full_set_train = (DepthDataset(args.data, 'train', trans),) full_set_val = (DepthDataset(args.data, 'train'),) else: full_set_train = generate_dataset(args.data, 'train', trans) full_set_val = generate_dataset(args.data, 'train',[]) # Get test train split. The test set here is intended as validation set but because we need also a validation set # for the early stopping we call it test test_idx, train_idx = train_test_split(full_set_train[0].samples, range(len(full_set_train[0].samples)), args.nview, args.val_split_size, True) # Get val train split val_idx, train_idx = train_test_split([full_set_train[0].samples[i] for i in train_idx], train_idx, args.nview, args.val_split_size, True) if args.nelements != 0: train_idx = under_sampler_to([full_set_train[0].samples[i] for i in train_idx], train_idx, args.nview, args.nelements) _, classes = zip(*[full_set_train[0].samples[i] for i in train_idx]) if args.sampling == "oversampling": train_idx = random_over_sampler(classes, train_idx, args.nview) elif args.sampling == "undersampling": train_idx = random_under_sampler(classes, train_idx, args.nview) # Get subsets test_set = torch.utils.data.Subset(full_set_val[0], test_idx) val_set = torch.utils.data.Subset(full_set_val[0], val_idx) train_set = torch.utils.data.Subset(full_set_train[0], train_idx) # Generate loaders test_loader = generate_loader(test_set, args.batch_size, args.workers) val_loader = generate_loader(val_set, args.batch_size, args.workers) train_loader = generate_loader(train_set, args.batch_size, args.workers) # load already trained model from single image classification # load_model(model, "for_rotation_net.pth.tar") # Track model in wandb wandb.init(project="RotationNet", config=args) # wandb.watch(model) train(model, criterion, optimizer, train_loader, val_loader, args) # Load best model before validating load_model(model, args.fname_best) # permute indices # indices = test_loader.dataset.indices # inds = random_permute_indices(np.array(indices), args.nview, True) # test_loader.dataset.indices = np.asarray(inds) # del indices # del inds val_statistics = validate(test_loader, model, criterion, args) log_summary(val_statistics, "val", test_loader.dataset.dataset.classes)
def train_k_fold(model, criterion, optimizer, args): """ Perform a k-fold cross validation on the given model. Use args.fold to set the number of total folds and args.ntest_fold to set the number of folds dedicated for the validation. Keep in mind that each training step uses also an extra validation set for early stopping (the size of this subset is set via args.val_split_size). All the data are sent to wandb or logged on a text file Parameters ---------- model : RotaitonNet model criterion : Pytorch criterion (CrossEntropy for RotationNet) optimizer : Pytorch optimizer (e.g. SGD) args : Input args from the parser Returns ------- Nothing """ # Save clean model to reload at each fold save_model(args.arch, model, optimizer, args.fname) # Get full train dataset full_set = generate_dataset(args.data, 'train') # Get folds folds = k_fold(full_set[0].samples, args.nview, True, args.fold) # List of top1 and top5 accuracies to get the average and std of the model performance top1 = [] top5 = [] # K-fold cross validation for i in range(args.fold): test_idx = [] # Use ntest_folds folds for the test set for j in range(args.ntest_folds): test_idx.extend(folds[i]) folds = np.delete(folds, i, 0) # Use rest of the data for the train set train_idx = np.hstack(folds) val_idx, train_idx = train_test_split([full_set[0].samples[i] for i in train_idx], train_idx, args.nview, args.val_split_size, True) # Get subsets test_set = torch.utils.data.Subset(full_set[0], test_idx) val_set = torch.utils.data.Subset(full_set[0], val_idx) train_set = torch.utils.data.Subset(full_set[0], train_idx) # Generate loaders test_loader = generate_loader(test_set, args.batch_size, args.workers) val_loader = generate_loader(val_set, args.batch_size, args.workers) train_loader = generate_loader(train_set, args.batch_size, args.workers) logger.debug("Start train on fold {}/{}".format(i, args.fold)) # Track model in wandb wandb.init(project="RotationNet", name="Fold " + str(i), config=args, reinit=True) # The model can be analyzed only once # if i == 0: # wandb.watch(model) train(model, criterion, optimizer, train_loader, val_loader, args) # Load best model before validating load_model(model, args.fname_best) val_statistics = validate(test_loader, model, criterion, args) log_summary(val_statistics, "val", test_loader.dataset.dataset.classes) # Load fresh model for next train load_model(model, args.fname) logger.info('Val prec@1 {top1:.3f} +- {std1:.3f} \t' 'Val prec@5 {top5:.3f} +- {std5:.3f} \t'.format(top1=np.mean(top1), std1=np.std(top1), top5=np.mean(top5), std5=np.std(top5)))
def train_hold_out_aligned(model, criterion, optimizer, args): """ Perform a train with validation train split on the given model. Use args.val_split_size to set the percentage of data for the validation set. Keep in mind the two validation sets are genereted. One for early stopping and one to evaluate the model. All the data are sent to wandb or logged on a text file Parameters ---------- model : RotaitonNet model criterion : Pytorch criterion (CrossEntropy for RotationNet) optimizer : Pytorch optimizer (e.g. SGD) args : Input args from the parser Returns ------- Nothing """ # create one element tuple to be consistent with ImageFolder dataset of Pytorch full_set_train = (AlignedDataset(args.data_aligned, 'train', []),) # validation data is on normal dataset full_set_val = generate_dataset(args.data, 'train') # full_set_val = (AlignedDataset(args.data_aligned, 'train', []),) # Get test train split. The test set here is intended as validation set but because we need also a validation set # for the early stopping we call it test test_idx, train_idx = train_test_split(full_set_train[0].samples, range(len(full_set_train[0].samples)), args.nview, args.val_split_size, True) # Get val train split val_idx, train_idx = train_test_split([full_set_train[0].samples[i] for i in train_idx], train_idx, args.nview, args.val_split_size, True) _, classes = zip(*[full_set_train[0].samples[i] for i in train_idx]) # Get subsets test_set = torch.utils.data.Subset(full_set_val[0], test_idx) val_set = torch.utils.data.Subset(full_set_val[0], val_idx) train_set = torch.utils.data.Subset(full_set_train[0], train_idx) # Generate loaders test_loader = generate_loader(test_set, args.batch_size, args.workers) val_loader = generate_loader(val_set, args.batch_size, args.workers) train_loader = generate_loader(train_set, args.batch_size, args.workers) # load already trained model from single image classification # load_model(model, "for_rotation_net.pth.tar") # Track model in wandb wandb.init(project="RotationNet", config=args) # wandb.watch(model) train(model, criterion, optimizer, train_loader, val_loader, args) # Load best model before validating load_model(model, args.fname_best) # permute indices # indices = test_loader.dataset.indices # inds = random_permute_indices(np.array(indices), args.nview, True) # test_loader.dataset.indices = np.asarray(inds) # del indices # del inds val_statistics = validate(test_loader, model, criterion, args) log_summary(val_statistics, "val", test_loader.dataset.dataset.classes)
def main(): args = parser.parse_args() torch.manual_seed(0) np.random.seed(0) # Set the cuda device if torch.cuda.is_available(): device = torch.device("cuda:0") torch.cuda.set_device(device) else: device = torch.device("cpu") if args.net_version == 1: from view_net import Model else: from view_net2 import Model # Initialize an OpenGL perspective camera. cameras = OpenGLPerspectiveCameras(device=device) # To blend the 100 faces we set a few parameters which control the opacity and the sharpness of # edges. Refer to blending.py for more details. # blend_params = BlendParams(sigma=1e-4, gamma=1e-4) # We will also create a phong renderer. This is simpler and only needs to render one face per pixel. raster_settings = RasterizationSettings( image_size=224, blur_radius=0.0, # np.log(1. / 1e-4 - 1.) * blend_params.sigma, faces_per_pixel=args.faces_per_pixel, # 100 ) # We can add a point light in front of the object. # lights = PointLights(device=device) # lights = DirectionalLights(device=device, direction=self.camera_position) phong_renderer = MeshRenderer( rasterizer=MeshRasterizer(cameras=cameras, raster_settings=raster_settings), shader=HardFlatShader(device=device, cameras=cameras) # , lights=lights) ) dataset = ClassificationData(args.data, "train", device) test_idx, train_idx = dataset.train_test_split(dataset.paths, range(len(dataset)), 20, True) val_idx, train_idx = dataset.train_test_split( [dataset.paths[i] for i in train_idx], train_idx, 20, True) test_set = torch.utils.data.Subset(dataset, test_idx) val_set = torch.utils.data.Subset(dataset, val_idx) train_set = torch.utils.data.Subset(dataset, train_idx) train_loader = DataLoader(train_set, batch_size=args.batch_size // args.nviews, shuffle=False, num_workers=0, pin_memory=True, drop_last=True, collate_fn=my_collate) val_loader = DataLoader(val_set, batch_size=args.batch_size // args.nviews, shuffle=False, num_workers=1, pin_memory=True, drop_last=True, collate_fn=my_collate) test_loader = DataLoader(test_set, batch_size=args.batch_size // args.nviews, shuffle=False, num_workers=1, pin_memory=True, drop_last=True, collate_fn=my_collate) model = Model(device, phong_renderer, dataset.nclasses, args) args.num_classes = dataset.nclasses # Multi GPUs if torch.cuda.device_count() > 1: model = torch.nn.DataParallel(model) model = model.to(device=device) optimizer = Adam( [ { 'params': model.camera_position, 'lr': args.learning_rate_camera }, # {'params': model.light_position, 'lr': args.learning_rate_camera}, { 'params': model.net_1.parameters() }, { 'params': model.net_2.parameters() } ], lr=args.learning_rate, weight_decay=args.weight_decay) criterion = nn.CrossEntropyLoss().to(device=device) wandb.init(project="views_net", config=args) args.fname_best = 'views_net{}_model_best{}.pth.tar'.format( args.nviews, datetime.now().strftime("%d_%b_%Y_%H_%M_%S")) args.device = device args.obj_path = train_set.dataset.paths[0][0] train(model, criterion, optimizer, train_loader, val_loader, args) load_model(model, args.fname_best) val_statistics = validate(test_loader, model, criterion, device) log_summary(val_statistics, "val", test_loader.dataset.dataset.classes)
def plot_summary(self, phase, classes): #self.statistics.compute(self.num_classes) log_summary(self.statistics, phase, classes)