def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) ########### PLOT TSNE ################ argreader.parser.add_argument('--tsne',action='store_true',help='To plot t-sne representation of feature extracted. Also plots the representation of a video side by side to make an image. \ The --exp_id, --model_id, --seed and --dataset_test arguments should be set.') ########### PLOT SCORE EVOLUTION ALONG VIDEO ################## argreader.parser.add_argument('--plot_score',action="store_true",help='To plot the scene change probability of produced by a model for all the videos processed by this model during validation for all epochs.\ The --model_id argument must be set, along with the --exp_id, --dataset_test and --epoch_to_plot arguments.') argreader.parser.add_argument('--epoch_to_plot',type=int,metavar="N",help='The epoch at which to plot the predictions when using the --plot_score argument') argreader.parser.add_argument('--untrained_exp_and_model_id',default=[None,None],type=str,nargs=2,help='To plot the distance between features computed by the network before training when using the --plot_score arg.\ The values are the exp_id and the model_id of the model not trained on scene change detection (i.e. the model with the ImageNet weights)') argreader.parser.add_argument('--plot_dist',action="store_true",help='To plot the distance when using the --plot_score argument') ########## COMPUTE METRICS AND PUT THEM IN AN LATEX TABLE ############# argreader.parser.add_argument('--eval_model_leave_one_out',type=float,nargs=3,help='To evaluate a model by tuning its decision threshold on the video on which it is not\ evaluated. The --model_id argument must be set, along with the --model_name, --exp_id and --dataset_test arguments. \ The values of this args are the epoch at which to evaluate , followed by the minimum and maximum decision threshold \ to evaluate. Use the --len_pond to ponderate the overflow and coverage by scene lengths.') argreader.parser.add_argument('--model_name',type=str,metavar="NAME",help='The name of the model as will appear in the latex table produced by the --eval_model_leave_one_out argument.') argreader.parser.add_argument('--len_pond',action="store_true",help='Use this argument to ponderate the coverage and overflow by the GT scene length when using --eval_model_leave_one_out.') argreader.parser.add_argument('--fine_tuned_thres',action="store_true",help='To automatically fine tune the decision threshold of the model. Only useful for the --bbc_annot_dist arg. \ Check the help of this arg.') ######### Make a gif out of predictions ################ argreader.parser.add_argument('--gif',action="store_true",help='Make a gif out of the predictions of a model on one dataset.') argreader.parser.add_argument('--model_id1',type=str,metavar="ID",help='The id of the first model to plot with --gif') argreader.parser.add_argument('--model_id2',type=str,metavar="ID",help='The id of the second model to plot with --gif') argreader.parser.add_argument('--model_name1',type=str,metavar="NAME",help='The name of the first model to plot with --gif') argreader.parser.add_argument('--model_name2',type=str,metavar="NAME",help='The name of the second model to plot with --gif') argreader = load_data.addArgs(argreader) #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args if args.tsne: tsne(args.dataset_test,args.exp_id,args.model_id,args.seed) if args.plot_score: plotScore(args.exp_id,args.model_id,args.untrained_exp_and_model_id[0],args.untrained_exp_and_model_id[1],args.dataset_test,args.plot_dist,args.epoch_to_plot) if args.eval_model_leave_one_out: epoch = int(args.eval_model_leave_one_out[0]) thresMin = args.eval_model_leave_one_out[1] thresMax = args.eval_model_leave_one_out[2] evalModel_leaveOneOut(args.exp_id,args.model_id,args.model_name,args.dataset_test,epoch,thresMin,thresMax,args.len_pond) if args.gif: makeGif(args.exp_id,args.model_id1,args.model_id2,args.model_name1,args.model_name2,args.dataset_test)
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args args.cuda = not args.no_cuda and torch.cuda.is_available()
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument( '--only_init', action='store_true', help='To initialise a model without training it.\ This still computes the confidence intervals' ) argreader.parser.add_argument( '--init_id', type=str, metavar="N", help='The index of the model to use as initialisation. \ The weight of the last epoch will be used.' ) #Reading the comand line arg argreader.getRemainingArgs() args = argreader.args torch.manual_seed(args.seed) random.seed(args.seed) np.random.seed(args.seed) if args.cuda: torch.cuda.manual_seed(args.seed) #The folders where the experience file will be written if not (os.path.exists("../vis/{}".format(args.exp_id))): os.makedirs("../vis/{}".format(args.exp_id)) if not (os.path.exists("../results/{}".format(args.exp_id))): os.makedirs("../results/{}".format(args.exp_id)) if not (os.path.exists("../models/{}".format(args.exp_id))): os.makedirs("../models/{}".format(args.exp_id)) #Loading data trainSet, distorNbList = load_data.loadData(args.dataset) #Write the arguments in a config file so the experiment can be re-run argreader.writeConfigFile("../models/{}/model{}.ini".format( args.exp_id, args.ind_id)) if args.cuda: trainSet = trainSet.cuda() #Building the model model = modelBuilder.modelMaker(trainSet.size(1), len(trainSet), distorNbList, args) if args.cuda: model = model.cuda() #Inititialise the model if args.start_mode == "base_init": model.init(trainSet,args.dataset,args.score_dis,args.param_not_gt,\ args.true_scores_init,args.bias_init,args.diffs_init,args.incons_init,truescores_tanh=args.truescores_tanh,bias_tanh=args.bias_tanh,bias_ampl=args.bias_ampl) startEpoch = 1 elif args.start_mode == "iter_init": model.init(trainSet,args.dataset,args.score_dis,args.param_not_gt,\ args.true_scores_init,args.bias_init,args.diffs_init,args.incons_init,truescores_tanh=args.truescores_tanh,bias_tanh=args.bias_tanh,bias_ampl=args.bias_ampl,iterInit=True) startEpoch = 1 elif args.start_mode == "fine_tune": init_path = sorted(glob.glob("../models/{}/model{}_epoch*".format( args.exp_id, args.init_id)), key=processResults.findNumbers)[-1] model.load_state_dict(torch.load(init_path)) startEpoch = processResults.findNumbers( os.path.basename(init_path).replace("model{}".format(args.init_id), "")) else: raise ValueError("Unknown init method : {}".format(args.start_mode)) #Adding normal noise to the gradients gradNoise = GradNoise(ampl=args.noise) for p in model.parameters(): p.register_hook(gradNoise) torch.save(model.state_dict(), "../models/{}/model{}_epoch0".format(args.exp_id, args.ind_id)) #Write the parameters of the model and its confidence interval in a csv file loss = model(trainSet) paramsToCsv(loss, model, args.exp_id, args.ind_id, epoch=0, scoresDis=args.score_dis, score_min=args.score_min, score_max=args.score_max, truescores_tanh=args.truescores_tanh, bias_tanh=args.bias_tanh, bias_ampl=args.bias_ampl) if not args.only_init: #Getting the contructor and the kwargs for the choosen optimizer optimConst, kwargs = get_OptimConstructor(args.optim, args.momentum) #If no learning rate is schedule is indicated (i.e. there's only one learning rate), #the args.lr argument will be a float and not a float list. #Converting it to a list with one element makes the rest of processing easier if type(args.lr) is float: args.lr = [args.lr] model.setPrior(args.prior, args.dataset) loss, epoch = train(model, optimConst, kwargs, trainSet, args, startEpoch=startEpoch, truescores_tanh=args.truescores_tanh, bias_tanh=args.bias_tanh, bias_ampl=args.bias_ampl) torch.save( model.state_dict(), "../models/{}/model{}_epoch{}".format(args.exp_id, args.ind_id, epoch)) paramsToCsv(loss, model, args.exp_id, args.ind_id, epoch, args.score_dis, args.score_min, args.score_max, truescores_tanh=args.truescores_tanh, bias_tanh=args.bias_tanh, bias_ampl=args.bias_ampl)
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument( '--noise', type=float, metavar='NOISE', help= 'the amount of noise to add in the gradient of the clustNet (in percentage)(default: 0.1)' ) argreader.parser.add_argument( '--entweig', type=float, default=0, metavar='ENTWEI', help= 'the weight of the clusters entropy term in the cost function (default: 0)' ) argreader.parser.add_argument( '--clustdivers', type=float, default=0, metavar='ENTWEI', help= 'the weight of the clusters diversity term in the cost function (default: 0)' ) argreader.parser.add_argument( '--filter_dis', type=float, default=0, metavar='FILDIS', help= 'the weight of the filter distance term in the cost function (default: 0)' ) argreader.parser.add_argument( '--featmap_entr', type=float, default=0, metavar='FEATENT', help= 'the weight of the feature map entropy term in the cost function (default: 0)' ) argreader.parser.add_argument( '--featmap_var', type=float, default=0, metavar='FEATVAR', help= 'the weight of the feature map var term in the cost function (default: 0)' ) argreader.parser.add_argument( '--optim', type=str, default="SGD", metavar='OPTIM', help='the optimizer algorithm to use (default: \'SGD\')') argreader.parser.add_argument( '--noise_init', type=float, default="0", metavar='NOISEINIT', help= 'The percentage of noise to add (relative to the filter norm) when initializing detectNets with \ a pre-trained detectNet') argreader.parser.add_argument( '--reverse_target', type=str2bool, default="False", help= 'To inverse the positive and the negative class. Useful to train a detectNet \ which will be later used to produce negative feature map' ) argreader.parser.add_argument( '--clu_train_mode', type=str, default='joint', metavar='TRAINMODE', help= 'Determines the cluster training mode. Can be \'joint\' or \'separated\' (default: \'joint\')' ) argreader.parser.add_argument('--rand_prop_val_sched', type=float, nargs='+', default=[0.9, 0.5, 0.1], metavar='RANDPROP_VAL_SCHED', help=')') argreader.parser.add_argument('--rand_prop_epo_sched', type=int, nargs='+', default=[0, 1, 2], metavar='RANDPROP_EPO_SCHED', help=')') argreader.parser.add_argument( '--init', type=str, default=None, metavar='N', help='the weights to use to initialize the detectNets') argreader.parser.add_argument( '--init_clu', type=str, default=None, metavar='N', help='the weights to use to initialize the clustNets') argreader.parser.add_argument( '--init_enc', type=str, default=None, metavar='N', help='the weights to use to initialize the encoder net') argreader.parser.add_argument( '--init_pos', type=str, default=None, metavar='N', help= 'the weights to use to initialize the positive detectnets. Ignored when not training a full clust detect net' ) argreader.parser.add_argument( '--init_neg', type=str, default=None, metavar='N', help= 'the weights to use to initialize the negative detectNets. Ignored when not training a full clust detect net' ) argreader.parser.add_argument( '--encapplyDropout2D', default=True, type=str2bool, metavar='N', help='whether or not to apply 2D dropout in the preprocessing net') #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args args.cuda = not args.no_cuda and torch.cuda.is_available() torch.manual_seed(args.seed) if args.cuda: torch.cuda.manual_seed(args.seed) if args.clust < 2: raise ValueError( "The number of cluster must be at least 2. Got {}".format( args.clust)) train_loader, test_loader = dataLoader.loadData(args.dataset, args.batch_size, args.test_batch_size, args.cuda, args.num_workers) #The group of class to detect np.random.seed(args.seed) classes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] np.random.shuffle(classes) classToFind = classes[0:args.clust] #The folders where the experience file will be written if not (os.path.exists("../vis/{}".format(args.exp_id))): os.makedirs("../vis/{}".format(args.exp_id)) if not (os.path.exists("../results/{}".format(args.exp_id))): os.makedirs("../results/{}".format(args.exp_id)) if not (os.path.exists("../nets/{}".format(args.exp_id))): os.makedirs("../nets/{}".format(args.exp_id)) if args.pretrain: netType = "detectNet" elif args.pretrain_cae: netType = "cae" else: netType = "clustDetectNet" #Write the arguments in a config file so the experiment can be re-run argreader.writeConfigFile("../nets/{}/{}{}.ini".format( args.exp_id, netType, args.ind_id)) #Building the net net = netBuilder.netMaker(args) if args.cuda: net.cuda() startEpoch = initialize_Net_And_EpochNumber(net,args.pretrain,args.init,args.init_clu,args.init_enc,args.init_pos,args.init_neg,\ args.exp_id,args.ind_id,args.cuda,args.noise_init,netType) net.classToFind = classToFind #Getting the contructor and the kwargs for the choosen optimizer optimConst, kwargs = get_OptimConstructor_And_Kwargs( args.optim, args.momentum) #If no learning rate is schedule is indicated (i.e. there's only one learning rate), #the args.lr argument will be a float and not a float list. #Converting it to a list with one element makes the rest of processing easier if type(args.lr) is float: args.lr = [args.lr] if type(args.lr_cl) is float: args.lr_cl = [args.lr_cl] if (not args.pretrain) and (not args.pretrain_cae): #Adding a hook to add noise at every weight update if args.noise != 0: gradNoise = GradNoise(ampl=args.noise) for p in net.getClustWeights(): p.register_hook(gradNoise) #Train and evaluate the clustering detecting network for several epochs lrCounter = 0 for epoch in range(startEpoch, args.epochs + 1): #This condition determines when the learning rate should be updated (to follow the learning rate schedule) #The optimiser have to be rebuilt every time the learning rate is updated if (epoch - 1) % ( (args.epochs + 1) // len(args.lr)) == 0 or epoch == startEpoch: kwargs['lr'] = args.lr[lrCounter] print("Learning rate : ", kwargs['lr']) optimizerDe = optimConst(net.getDetectWeights(), **kwargs) kwargs['lr'] = args.lr_cl[lrCounter] print("Learning rate of clustNet: ", kwargs['lr']) optimizerCl = optimConst(net.getClustWeights(), **kwargs) if lrCounter < len(args.lr) - 1: lrCounter += 1 train(net, optimizerCl, optimizerDe, train_loader, epoch, args, classToFind) test(net, test_loader, epoch, args, classToFind) else: print("Pretraining") if args.pretrain_cae: trainFunc = trainCAE testFunc = testCAE kwargsFunc = {} else: trainFunc = trainDetect testFunc = testDetect kwargsFunc = {"classToFind": classToFind} #Train and evaluate the detecting network for several epochs lrCounter = 0 for epoch in range(startEpoch, args.epochs + 1): if (epoch - 1) % ( (args.epochs + 1) // len(args.lr)) == 0 or epoch == startEpoch: kwargs['lr'] = args.lr[lrCounter] print("Learning rate : ", kwargs['lr']) optimizerDe = optimConst(net.parameters(), **kwargs) if lrCounter < len(args.lr) - 1: lrCounter += 1 trainFunc(net, optimizerDe, train_loader, epoch, args, **kwargsFunc) testFunc(net, test_loader, epoch, args, **kwargsFunc)
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument('--comp_feat', action='store_true',help='To compute and write in a file the features of all images in the test set. All the arguments used to \ build the model and the test data loader should be set.') argreader.parser.add_argument('--no_train', type=str,nargs=2,help='To use to re-evaluate a model at each epoch after training. At each epoch, the model is not trained but \ the weights of the corresponding epoch are loaded and then the model is evaluated.\ The values of this argument are the exp_id and the model_id of the model to get the weights from.') argreader = addInitArgs(argreader) argreader = addLossArgs(argreader) argreader = addOptimArgs(argreader) argreader = addValArgs(argreader) argreader = modelBuilder.addArgs(argreader) argreader = load_data.addArgs(argreader) #Reading the comand line arg argreader.getRemainingArgs() args = argreader.args if args.redirect_out: sys.stdout = open("python.out", 'w') #The folders where the experience file will be written if not (os.path.exists("../vis/{}".format(args.exp_id))): os.makedirs("../vis/{}".format(args.exp_id)) if not (os.path.exists("../results/{}".format(args.exp_id))): os.makedirs("../results/{}".format(args.exp_id)) if not (os.path.exists("../models/{}".format(args.exp_id))): os.makedirs("../models/{}".format(args.exp_id)) #Write the arguments in a config file so the experiment can be re-run argreader.writeConfigFile("../models/{}/{}.ini".format(args.exp_id,args.model_id)) writer = SummaryWriter("../results/{}".format(args.exp_id)) print("Model :",args.model_id,"Experience :",args.exp_id) if args.comp_feat: testLoader = load_data.TestLoader(args.val_l,args.dataset_test,args.test_part_beg,args.test_part_end,args.img_size,\ args.resize_image,args.exp_id,args.random_frame_val) if args.feat != "None": featModel = modelBuilder.buildFeatModel(args.feat,args.pretrain_dataset,args.lay_feat_cut) if args.cuda: featModel = featModel.cuda() if args.init_path_visual != "None": featModel.load_state_dict(torch.load(args.init_path_visual)) elif args.init_path != "None": model = modelBuilder.netBuilder(args) params = torch.load(args.init_path) state_dict = {k.replace("module.cnn.","cnn.module."): v for k,v in params.items()} model.load_state_dict(state_dict) featModel = model.featModel featModel.eval() else: featModel = None with torch.no_grad(): evalAllImages(args.exp_id,args.model_id,featModel,testLoader,args.cuda,args.log_interval) else: np.random.seed(args.seed) torch.manual_seed(args.seed) if args.cuda: torch.cuda.manual_seed(args.seed) paramToOpti = [] trainLoader,trainDataset = load_data.buildSeqTrainLoader(args) valLoader = load_data.TestLoader(args.val_l,args.dataset_val,args.val_part_beg,args.val_part_end,\ args.img_size,args.resize_image,\ args.exp_id,args.random_frame_val) #Building the net net = modelBuilder.netBuilder(args) if args.cuda: net = net.cuda() trainFunc = epochSeqTr valFunc = epochSeqVal kwargsTr = {'log_interval':args.log_interval,'loader':trainLoader,'args':args,'writer':writer} kwargsVal = kwargsTr.copy() kwargsVal['loader'] = valLoader kwargsVal.update({"metricEarlyStop":args.metric_early_stop,"maximiseMetric":args.maximise_metric}) if args.adv_weight > 0: kwargsTr["discrModel"] = modelBuilder.Discriminator(net.nbFeat,args.discr_dropout) kwargsTr["discrModel"] = kwargsTr["discrModel"].cuda() if args.cuda else kwargsTr["discrModel"].cpu() kwargsTr["discrLoader"] = load_data.buildFrameTrainLoader(args) kwargsTr["discrOptim"] = torch.optim.SGD(kwargsTr["discrModel"].parameters(), lr=args.lr,momentum=args.momentum) else: kwargsTr["discrModel"],kwargsTr["discrLoader"],kwargsTr["discrOptim"] = None,None,None for p in net.parameters(): paramToOpti.append(p) paramToOpti = (p for p in paramToOpti) #Getting the contructor and the kwargs for the choosen optimizer optimConst,kwargsOpti = get_OptimConstructor_And_Kwargs(args.optim,args.momentum) startEpoch = initialize_Net_And_EpochNumber(net,args.exp_id,args.model_id,args.cuda,args.start_mode,args.init_path,args.init_path_visual_temp) #If no learning rate is schedule is indicated (i.e. there's only one learning rate), #the args.lr argument will be a float and not a float list. #Converting it to a list with one element makes the rest of processing easier if type(args.lr) is float: args.lr = [args.lr] lrCounter = 0 metricLastVal = None outDictEpochs = {} targDictEpochs = {} for epoch in range(startEpoch, args.epochs + 1): kwargsOpti,kwargsTr,lrCounter = update.updateLR(epoch,args.epochs,args.lr,startEpoch,kwargsOpti,kwargsTr,lrCounter,net,optimConst) kwargsTr["epoch"],kwargsVal["epoch"] = epoch,epoch kwargsTr["model"],kwargsVal["model"] = net,net kwargsTr = resetAdvIter(kwargsTr) if not args.no_train: trainFunc(**kwargsTr) else: net.load_state_dict(torch.load("../models/{}/model{}_epoch{}".format(args.no_train[0],args.no_train[1],epoch))) kwargsVal["metricLastVal"] = metricLastVal #Checking if validation has already been done if len(glob.glob("../results/{}/{}_epoch{}_*".format(args.exp_id,args.model_id,epoch))) < len(kwargsVal["loader"].videoPaths): with torch.no_grad(): metricLastVal,outDict,targDict = valFunc(**kwargsVal) outDictEpochs[epoch] = outDict targDictEpochs[epoch] = targDict update.updateHist(writer,args.model_id,outDictEpochs,targDictEpochs) else: print("Validation epoch {} already done !".format(epoch))
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument('--weig',action='store_true',help='Plot distance between the weights and their previous version at each epoch. \ The weights file name should be like "clustDetectNet7_epoch12"') argreader.parser.add_argument('--spar', nargs='+',type=str, metavar='HIST',help='Plot the mean sparsity of activation. The values after "--spar" \ is the list of parameters which are varying across the different nets. The score file must contain the targets, the prediction and cluster scores.') argreader.parser.add_argument('--acc_evol', nargs='+',type=str, metavar='SCOR', help='Plot the error, accuracy and clustering score across the training epochs for all nets in the experiment. Also plot \ the total variation of these curves. The values after "--acc_evol" is the list of parameters which are varying among the \ different nets. Some nets can be not plotted using the --nets_to_remove arg.') argreader.parser.add_argument('--nets_to_remove', nargs='+',default=[],type=int, metavar='ID', help='The list of net IDs not to plot when using the --acc_evol arg.') argreader.parser.add_argument('--failurecases',type=int, nargs=2,metavar='SCOR', help='To write in a folder the test images that are misclassified by the nets at every epoch. '\ 'The first parameter after this argument is the net index and the second one is the epoch number') argreader.parser.add_argument('--cludis',type=int, nargs=2,metavar='SCOR', help='To plot the average cluster distribution across epochs for all nets in an experiment') argreader.parser.add_argument('--feat_map_var',type=int, nargs=2,metavar='ENTR_EPOCH', help='For each detecting network, plot the feature map average variance across epochs. Positive and negative inputs are also \ separated. The first argument is the net id and the second is the layer number') argreader.parser.add_argument('--tsne',type=str,nargs=2,metavar="PATH", help='To plot t-sne on the reprenstations produced by an encoder. The fisrt argument must be the path to an CNN model and the second\ is the number of samples to use.') argreader.parser.add_argument('--train',action='store_true',help='To do all computation on the train set') #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args args.cuda = not args.no_cuda and torch.cuda.is_available() if args.weig : weigthTrajectoryLength(args) if args.spar: activationSparsity(args) if args.acc_evol: accuracyEvolution(args) if args.failurecases: failuresCases(args) if args.cludis: meanClusterDistribEvol(args) if args.feat_map_var: featureMapVariance(args) if args.tsne: hiddenRepTSNE(args)
def main(argv=None): # Getting arguments from config file and command line # Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument('--no_train', type=str2bool, help='To use to re-evaluate a model at each epoch after training. At each epoch, the model is not trained but \ the weights of the corresponding epoch are loaded and then the model is evaluated.\ The arguments --exp_id_no_train and the --model_id_no_train must be set') argreader.parser.add_argument('--exp_id_no_train', type=str, help="To use when --no_train is set to True. This is the exp_id of the model to get the weights from.") argreader.parser.add_argument('--model_id_no_train', type=str, help="To use when --no_train is set to True. This is the model_id of the model to get the weights from.") argreader.parser.add_argument('--no_val', type=str2bool, help='To not compute the validation') argreader.parser.add_argument('--only_test', type=str2bool, help='To only compute the test') argreader.parser.add_argument('--do_test_again', type=str2bool, help='Does the test evaluation even if it has already been done') argreader.parser.add_argument('--compute_latency', type=str2bool, help='To write in a file the latency at each forward pass.') argreader.parser.add_argument('--grad_cam', type=str2bool, help='To compute grad cam instead of training or testing.') argreader.parser.add_argument('--optuna', type=str2bool, help='To run a hyper-parameter study') argreader.parser.add_argument('--optuna_trial_nb', type=int, help='The number of hyper-parameter trial to run.') argreader.parser.add_argument('--opt_data_aug', type=str2bool, help='To optimise data augmentation hyper-parameter.') argreader.parser.add_argument('--max_batch_size', type=int, help='To maximum batch size to test.') argreader = addInitArgs(argreader) argreader = addOptimArgs(argreader) argreader = addValArgs(argreader) argreader = addLossTermArgs(argreader) argreader = modelBuilder.addArgs(argreader) argreader = load_data.addArgs(argreader) # Reading the comand line arg argreader.getRemainingArgs() args = argreader.args if args.redirect_out: sys.stdout = open("python.out", 'w') # The folders where the experience file will be written if not (os.path.exists("../vis/{}".format(args.exp_id))): os.makedirs("../vis/{}".format(args.exp_id)) if not (os.path.exists("../results/{}".format(args.exp_id))): os.makedirs("../results/{}".format(args.exp_id)) if not (os.path.exists("../models/{}".format(args.exp_id))): os.makedirs("../models/{}".format(args.exp_id)) args = updateSeedAndNote(args) # Update the config args argreader.args = args # Write the arguments in a config file so the experiment can be re-run argreader.writeConfigFile("../models/{}/{}.ini".format(args.exp_id, args.model_id)) print("Model :", args.model_id, "Experience :", args.exp_id) if args.distributed: size = args.distrib_size processes = [] for rank in range(size): p = Process(target=init_process, args=(args, rank, size, run)) p.start() processes.append(p) for p in processes: p.join() else: if args.optuna: def objective(trial): return run(args,trial=trial) study = optuna.create_study(direction="maximize" if args.maximise_val_metric else "minimize",\ storage="sqlite:///../results/{}/{}_hypSearch.db".format(args.exp_id,args.model_id), \ study_name=args.model_id,load_if_exists=True) con = sqlite3.connect("../results/{}/{}_hypSearch.db".format(args.exp_id,args.model_id)) curr = con.cursor() failedTrials = 0 for elem in curr.execute('SELECT trial_id,value FROM trials WHERE study_id == 1').fetchall(): if elem[1] is None: failedTrials += 1 trialsAlreadyDone = len(curr.execute('SELECT trial_id,value FROM trials WHERE study_id == 1').fetchall()) if trialsAlreadyDone-failedTrials < args.optuna_trial_nb: studyDone = False while not studyDone: try: print("N trials",args.optuna_trial_nb-trialsAlreadyDone+failedTrials) study.optimize(objective,n_trials=args.optuna_trial_nb-trialsAlreadyDone+failedTrials) studyDone = True except RuntimeError as e: if str(e).find("CUDA out of memory.") != -1: gc.collect() torch.cuda.empty_cache() args.max_batch_size -= 5 else: raise RuntimeError(e) curr.execute('SELECT trial_id,value FROM trials WHERE study_id == 1') query_res = curr.fetchall() query_res = list(filter(lambda x:not x[1] is None,query_res)) trialIds = [id_value[0] for id_value in query_res] values = [id_value[1] for id_value in query_res] trialIds = trialIds[:args.optuna_trial_nb] values = values[:args.optuna_trial_nb] bestTrialId = trialIds[np.array(values).argmax()] curr.execute('SELECT param_name,param_value from trial_params WHERE trial_id == {}'.format(bestTrialId)) query_res = curr.fetchall() bestParamDict = {key:value for key,value in query_res} args.lr,args.batch_size = bestParamDict["lr"],int(bestParamDict["batch_size"]) args.optim = OPTIM_LIST[int(bestParamDict["optim"])] args.only_test = True bestPath = glob.glob("../models/{}/model{}_trial{}_best_epoch*".format(args.exp_id,args.model_id,bestTrialId-1))[0] copyfile(bestPath, bestPath.replace("_trial{}".format(bestTrialId-1),"")) run(args) else: run(args)
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument( '--noise', type=float, metavar='NOISE', help= 'the amount of noise to add in the gradient of the clustNet (in percentage)(default: 0.1)' ) argreader.parser.add_argument( '--optim', type=str, default="SGD", metavar='OPTIM', help='the optimizer algorithm to use (default: \'SGD\')') argreader.parser.add_argument( '--init', type=str, default=None, metavar='N', help='the weights to use to initialize the detectNets') #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args args.cuda = not args.no_cuda and torch.cuda.is_available() torch.manual_seed(args.seed) if args.cuda: torch.cuda.manual_seed(args.seed) train_loader, test_loader, perm = dataLoader.loadData( args.dataset, args.batch_size, args.test_batch_size, args.permutate, args.cuda, args.num_workers, args.crop_size_imagenet, args.train_prop) if args.write_img_ex: for i in range(10): tensor = test_loader.dataset[i][0] vis.writeImg( '../vis/{}/{}_img{}.jpg'.format(args.exp_id, args.dataset, i), tensor.detach().numpy()) origSize = tensor.size() tensor = tensor.view(-1) tensor = tensor[np.argsort(perm)] tensor = tensor.view(origSize) vis.writeImg( '../vis/{}/{}_img{}_noperm.jpg'.format(args.exp_id, args.dataset, i), tensor.detach().numpy()) #The folders where the experience file will be written if not (os.path.exists("../vis/{}".format(args.exp_id))): os.makedirs("../vis/{}".format(args.exp_id)) if not (os.path.exists("../results/{}".format(args.exp_id))): os.makedirs("../results/{}".format(args.exp_id)) if not (os.path.exists("../nets/{}".format(args.exp_id))): os.makedirs("../nets/{}".format(args.exp_id)) netType = "net" #Write the arguments in a config file so the experiment can be re-run argreader.writeConfigFile("../nets/{}/{}{}.ini".format( args.exp_id, netType, args.model_id)) #The writer for tensorboardX writer = SummaryWriter("../results/{}".format(args.exp_id)) print("Model :", args.model_id, "Experience :", args.exp_id) #Building the net net = netBuilder.netMaker(args) if args.cuda: net.cuda() startEpoch = initialize_Net_And_EpochNumber(net, args.start_mode, args.init_path, args.exp_id, args.model_id, args.cuda, netType) #Getting the contructor and the kwargs for the choosen optimizer optimConst, kwargs = get_OptimConstructor_And_Kwargs( args.optim, args.momentum) #If no learning rate is schedule is indicated (i.e. there's only one learning rate), #the args.lr argument will be a float and not a float list. #Converting it to a list with one element makes the rest of processing easier if type(args.lr) is float: args.lr = [args.lr] #Train and evaluate the clustering detecting network for several epochs lrCounter = 0 for epoch in range(startEpoch, args.epochs + 1): #This condition determines when the learning rate should be updated (to follow the learning rate schedule) #The optimiser have to be rebuilt every time the learning rate is updated if (epoch - 1) % ( (args.epochs + 1) // len(args.lr)) == 0 or epoch == startEpoch: kwargs['lr'] = args.lr[lrCounter] print("Learning rate : ", kwargs['lr']) optimizer = optimConst(net.parameters(), **kwargs) if lrCounter < len(args.lr) - 1: lrCounter += 1 trainDetect(net, optimizer, train_loader, epoch, writer, args) with torch.no_grad(): testDetect(net, test_loader, epoch, writer, args)
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument( '--bias_std', metavar='STD', type=float, default=0.25, help= 'The standard deviation of the bias gaussian distribution. Ignored if bias are sampled from a beta distribution' ) argreader.parser.add_argument( '--incons_alpha', metavar='STD', type=float, default=1, help='The alpha parameter of the inconsistency beta distribution') argreader.parser.add_argument( '--incons_beta', metavar='STD', type=float, default=10, help='The beta parameter of the inconsistency beta distribution') argreader.parser.add_argument( '--diff_alpha', metavar='STD', type=float, default=1, help='The alpha parameter of the difficulty beta distribution') argreader.parser.add_argument( '--diff_beta', metavar='STD', type=float, default=10, help='The beta parameter of the difficulty beta distribution') argreader.parser.add_argument('--nb_annot', metavar='STD', type=int, default=30, help='The number of annotators') argreader.parser.add_argument('--nb_video_per_content', metavar='STD', type=int, default=8, help='The number of videos per content') argreader.parser.add_argument('--nb_content', metavar='STD', type=int, default=25, help='The number of content') argreader.parser.add_argument('--dataset_id', metavar='STD', type=str, default=0, help='The dataset name') argreader.parser.add_argument( '--sample_mode', metavar="MODE", type=str, default="clip", help= 'The sample mode for the true scores. Can be \'continuous\' to generate continuous raw scores, \ \'clip\' : sample continuous score and clip them to integer values\ \'multinomial\' : to sample from a multinomial distribution built with the continuous density.' ) argreader.parser.add_argument( '--init_from', metavar='DATASETNAME', type=str, help= 'A new dataset can be created by removing lines or columns from of previously created one. \ This argument allow this and its value should be the name of the older dataset.' ) argreader.parser.add_argument( '--seed_mat', metavar='SEED', type=int, help='The seed to use to generate the score matrix. \ If unspecified, The RNG state will not be reset after generating parameters.' ) argreader.parser.add_argument('--plot', action='store_true', help='To plot the generated dataset.') #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args torch.manual_seed(args.seed) random.seed(args.seed) np.random.seed(args.seed) if args.cuda: torch.cuda.manual_seed(args.seed) #Case where the dataset is created from scratch if not args.init_from: #Write the arguments in a config file so the experiment can be re-run argreader.writeConfigFile("../data/{}.ini".format(args.dataset_id)) trueScoreDis = Uniform(args.score_min, args.score_max) diffDis = Beta(args.diff_alpha, args.diff_beta) inconsDis = Beta(args.incons_alpha, args.incons_beta) if args.bias_dis == "Normal": biasDis = Normal(torch.zeros(1), args.bias_std * torch.eye(1)) elif args.bias_dis == "Beta": biasDis = Beta(2, 2) else: raise ValueError("Unkown bias distribution : ", args.bias_dis) nb_videos = args.nb_video_per_content * args.nb_content print("Generating parameters") trueScores = trueScoreDis.sample((nb_videos, )).double() trueScores[-1] = 4.9 diffs = diffDis.sample((args.nb_content, )).double() incons = inconsDis.sample((args.nb_annot, )).double() bias = biasDis.sample((args.nb_annot, )).double() if args.bias_dis == "Beta": bias = (bias - 0.5) * args.bias_ampl #Sort the true score and the bias for better visualisation trueScores = trueScores.sort()[0] bias = bias.sort(dim=0)[0] if args.seed_mat: torch.manual_seed(args.seed_mat) random.seed(args.seed_mat) np.random.seed(args.seed_mat) distorNbList = [ args.nb_video_per_content for i in range(args.nb_content) ] model = modelBuilder.modelMaker(args.nb_annot, nb_videos, distorNbList, args) print("Preparing tensors") model.preprocessAndSet(trueScores, "trueScores", args.score_dis, args.truescores_tanh, args.bias_tanh, args.bias_ampl) model.preprocessAndSet(bias, "bias", args.score_dis, args.truescores_tanh, args.bias_tanh, args.bias_ampl) model.preprocessAndSet(incons, "incons", args.score_dis, args.truescores_tanh, args.bias_tanh, args.bias_ampl) model.preprocessAndSet(diffs, "diffs", args.score_dis, args.truescores_tanh, args.bias_tanh, args.bias_ampl) print("Sampling scores") scoreDis = model.compScoreDis(x_is_cuda=False) scoreMat = scoreDis.sample() if args.sample_mode == "continuous": scoreMat = betaDenormalize(scoreMat, args.score_min, args.score_max) elif args.sample_mode == "clip": ampl = args.score_max - args.score_min + 1 scoreMat = torch.clamp(torch.ceil(ampl * scoreMat), args.score_min, args.score_max) if args.plot: print("Ploting the data generated") colors = cm.rainbow(np.linspace(0, 1, nb_videos)) markers = [ m for m, func in Line2D.markers.items() if func != 'nothing' and m not in Line2D.filled_markers ] if args.nb_annot == 5: markers = [".", ",", "v", "1", "s"] if len(markers) < args.nb_annot: markers = ["" for i in range(args.nb_annot)] else: markers = markers[:args.nb_annot] gridspec.GridSpec(3 + nb_videos, 1) fontSize = 20 fig = plt.figure(figsize=(10, 11)) plt.subplots_adjust(hspace=1.5, wspace=0) #ax = fig.add_subplot((1+nb_videos)*100+1*10+1,figsize=(10,5)) densityAxis = plt.subplot2grid((3 + nb_videos, 1), (0, 0), colspan=1, rowspan=3) box = densityAxis.get_position() densityAxis.set_position( [box.x0, box.y0, box.width * 0.8, box.height]) densityAxis.set_xlabel("Normalized continuous raw score", fontsize=fontSize) densityAxis.set_ylabel("Density", fontsize=fontSize) #Plot the legend handlesVid = [] for i in range(nb_videos): handlesVid += densityAxis.plot((0, 0), marker='', color=colors[i], label=i) legVid = plt.legend(handles=handlesVid, loc='right', title="Videos", fontsize=fontSize, bbox_to_anchor=(1.35, 0.5)) plt.setp(legVid.get_title(), fontsize=fontSize) plt.gca().add_artist(legVid) handlesAnnot = [] for j in range(args.nb_annot): handlesAnnot += densityAxis.plot((0, 0), marker=markers[j], color="black", label=j) legAnnot = plt.legend(handles=handlesAnnot, loc='right', title="Annotators", fontsize=fontSize, bbox_to_anchor=(1.4, -0.7), markerscale=4) plt.setp(legAnnot.get_title(), fontsize=fontSize) plt.gca().add_artist(legAnnot) dx = 0.01 x_coord = torch.arange(0, 1, dx) plt.xlim(0, 1) cdfs = torch.exp( scoreDis.log_prob(x_coord.unsqueeze(1).unsqueeze(1).double())) for i in range(nb_videos): for j in range(args.nb_annot): densityAxis.plot(x_coord.numpy(), cdfs[:, i, j].cpu().detach().numpy(), color=colors[i], marker=markers[j]) densityAxis.set_ylim(0, 20) #Plot score histograms #scoreNorm = betaNormalize(scoreMat[i],args.score_min,args.score_max) scoreNorm = (scoreMat[i] - args.score_min) / ( args.score_max + 1 - args.score_min) + 1 / ( 2 * (args.score_max + 1 - args.score_min)) histAx = plt.subplot2grid((3 + nb_videos, 1), (3 + i, 0), colspan=1, rowspan=1) if i == nb_videos - 1: histAx.set_xlabel("Raw scores", fontsize=fontSize) if i == int(nb_videos // 2): histAx.set_ylabel("Empirical count", fontsize=fontSize) box = histAx.get_position() histAx.set_position( [box.x0, box.y0, box.width * 0.8, box.height]) plt.hist(scoreNorm, color=colors[i], width=1 / (args.score_max - args.score_min + 1), range=(0, 1), bins=args.score_max - args.score_min + 1) plt.xlim(0, 1) plt.ylim(0, args.nb_annot + 1) scores = np.arange(args.score_min, args.score_max + 1) plt.xticks( betaNormalize(scores, args.score_min, args.score_max, rawScore=True), scores) plt.savefig("../vis/{}_scoreDis.png".format(args.dataset_id)) csv = "videos\tencode" + "".join( ["\t{}".format(i) for i in range(args.nb_annot)]) + "\n" for i in range(0, nb_videos): csv += str(i // args.nb_video_per_content + 1) + "\tvid{}".format(i) + "".join( "\t{}".format(scoreMat[i, j]) for j in range(args.nb_annot)) + "\n" with open("../data/{}_scores.csv".format(args.dataset_id), "w") as text_file: print(csv, file=text_file) np.savetxt("../data/{}_trueScores.csv".format(args.dataset_id), trueScores.numpy(), delimiter="\t") np.savetxt("../data/{}_diffs.csv".format(args.dataset_id), diffs.numpy(), delimiter="\t") np.savetxt("../data/{}_incons.csv".format(args.dataset_id), incons.numpy(), delimiter="\t") np.savetxt("../data/{}_bias.csv".format(args.dataset_id), bias.numpy(), delimiter="\t") print("Finished generating {}".format(args.dataset_id)) #Case where the dataset is created from removing lines or columns from an existing dataset (artificial or not) else: #Write the arguments in a config file argreader.writeConfigFile("../data/{}{}.ini".format( args.init_from, args.dataset_id)) #The number of contents of the old dataset: old_scores = np.genfromtxt("../data/{}_scores.csv".format( args.init_from), delimiter="\t", dtype=str) videoRef = old_scores[1:, 0] nb_content_old = len(np.unique(videoRef)) nb_annot_old = old_scores.shape[1] - 2 #Checking if the number of video per reference if constant vidDict = {} for video in videoRef: if video in vidDict: vidDict[video] += 1 else: vidDict[video] = 1 constantVideoPerRef = (len( list(set([vidDict[ref] for ref in vidDict.keys()]))) == 1) nb_video_per_content_old = len( videoRef) // nb_content_old if constantVideoPerRef else None #the permutation use for permuting the annotators randomly perm = np.random.permutation(nb_annot_old) #If the dataset to use is an artififical one, ground truth parameters are known #and should be processed too if os.path.exists("../data/{}.ini".format(args.init_from)): trueScores = np.genfromtxt("../data/{}_trueScores.csv".format( args.init_from), delimiter="\t") #Reshaping the true score vector as a 2D tensor with shape (NB_CONTENT,NB_VIDEOS_PER_CONTENT) #With sush a shape, it is easy to remove all videos corresponding to specific contents if constantVideoPerRef: trueScores = trueScores.reshape(nb_content_old, nb_video_per_content_old) trueScores = trueScores[:args.nb_content, :args. nb_video_per_content] trueScores = trueScores.reshape(-1) bias = np.genfromtxt("../data/{}_bias.csv".format(args.init_from), delimiter="\t") incons = np.genfromtxt("../data/{}_incons.csv".format( args.init_from), delimiter="\t") bias, incons = bias[perm][:args.nb_annot], incons[perm][:args. nb_annot] diffs = np.genfromtxt("../data/{}_diffs.csv".format( args.init_from), delimiter="\t")[:args.nb_content] np.savetxt("../data/{}{}_trueScores.csv".format( args.init_from, args.dataset_id), trueScores, delimiter="\t") np.savetxt("../data/{}{}_bias.csv".format(args.init_from, args.dataset_id), bias, delimiter="\t") np.savetxt("../data/{}{}_incons.csv".format( args.init_from, args.dataset_id), incons, delimiter="\t") np.savetxt("../data/{}{}_diffs.csv".format(args.init_from, args.dataset_id), diffs, delimiter="\t") scoreMat = np.genfromtxt("../data/{}_scores.csv".format( args.init_from), delimiter="\t", dtype=str) scoreMat[:, 2:] = np.transpose(np.transpose(scoreMat[:, 2:])[perm]) #Reshaping the matrix score as a 3D tensor with shape (NB_CONTENT,NB_VIDEOS_PER_CONTENT,NB_ANNOTATORS) #With sush a shape, it is easy to remove all videos corresponding to specific contents if constantVideoPerRef: scoreMat = scoreMat[1:].reshape(nb_content_old, nb_video_per_content_old, nb_annot_old + 2) scoreMat = scoreMat[:args.nb_content, :args. nb_video_per_content, :args.nb_annot + 2] scoreMat = scoreMat.reshape(scoreMat.shape[0] * scoreMat.shape[1], scoreMat.shape[2]) else: scoreMat = scoreMat[1:, :args.nb_annot + 2] header = "videos\tencode" + "".join( ["\t{}".format(i) for i in range(args.nb_annot)]) np.savetxt("../data/{}{}_scores.csv".format(args.init_from, args.dataset_id), scoreMat.astype(str), header=header, delimiter="\t", fmt='%s', comments='') print("Finished generating {}{}".format(args.init_from, args.dataset_id))
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument('--dataset', type=str, metavar='N', help='The dataset') argreader.parser.add_argument( '--merge_videos', type=str, metavar='EXT', help= 'Accumulate the clips from a folder to obtain one video per movie in the dataset. The value \ is the extension of the video files, example : \'avi\'.' ) argreader.parser.add_argument( '--compute_only_gt', action='store_true', help='To compute only gt when using --merge_videos') argreader.parser.add_argument( '--format_youtube', action='store_true', help= 'For the youtube_large datasets. Put the clips into separate folder') argreader.parser.add_argument( '--format_bbc', type=str, metavar='EXT', help= 'Format the bbc dataset. The value is the extension of the video file. E.g : \"--format_bbc mp4\".' ) argreader.parser.add_argument( '--detect_shot_bbc', action='store_true', help= 'To detect BBC shot using ffmpeg and not rely on the shot segmentation provided in the bbc dataset.' ) argreader.parser.add_argument( '--format_bbc2', nargs=2, type=str, metavar='EXT', help= 'Format the bbc season 2 dataset. As there is no annotation, artificial annotation are built.\ The first value is the extension of the video file. E.g : \"--format_bbc2 mp4\". The second value\ is the average length of the scene desired in number of shots.' ) argreader.parser.add_argument('--format_ovsd', action='store_true', help='Format the OVSD dataset') argreader.parser.add_argument( '--shot_thres', type=float, default=0.1, metavar='EXT', help='The detection threshold for the shot segmentation done by ffmpeg' ) argreader.parser.add_argument('--format_ally_mcbeal', type=str, metavar="EXT", help='Format the Ally McBeal dataset. \ The value is the extension of the video file. E.g : \"--format_ally_mcbeal avi\".' ) argreader.parser.add_argument('--format_rai', action='store_true', help='Format the RAI dataset.') #Reading the comand line arg argreader.getRemainingArgs() args = argreader.args if args.format_youtube and args.dataset == "youtube_large": #Removing non-scene video (montages, trailer etc.) videoPaths = sorted(glob.glob("../data/youtube_large/*.*")) videoToRm = list(filter(lambda x: os.path.basename(x).find("Movie_CLIP") == -1 \ and os.path.basename(x).find("Movie CLIP") == -1 \ and os.path.basename(x).find("Movieclips") == -1,videoPaths)) for videoPath in videoToRm: try: os.remove(videoPath) except IsADirectoryError: pass removeBadChar("youtube_large") videoPaths = sorted(glob.glob("../data/youtube_large/*.mp4")) movieDict = {} descrNotFound = [] for video in videoPaths: if os.path.exists(os.path.splitext(video)[0] + ".description") and os.path.basename( video).lower().find("mashup") == -1: with open(os.path.splitext(video)[0] + ".description", "r") as text_file: descr = text_file.read() descr = descr.split("\n")[0] #descr = descr.replace(" "," ") if descr.find("movie clips:") != -1: movieName = descr[:descr.find("movie clips:") - 1] elif descr.find(" Movie Clip :") != -1: movieName = descr[:descr.find(" Movie Clip :") - 1] elif descr.find(" - ") != -1: movieName = descr[:descr.find(" - ")] elif descr.find(":") != -1: movieName = descr[:descr.find(":")] else: movieName = descr[:descr.find("-") - 1] if not movieName in movieDict.keys(): movieDict[movieName] = [video] else: movieDict[movieName].append(video) else: descrNotFound.append( os.path.splitext(video)[0] + ".description") #Removing scene without description if not os.path.exists("../data/nodescr_youtube_large"): os.makedirs("../data/nodescr_youtube_large") for descrPath in descrNotFound: videoPath = descrPath.replace(".description", ".mp4") os.rename( videoPath, "../data/nodescr_youtube_large/" + os.path.basename(videoPath)) #The folder in which the scenes with badly formated description will be put, if not os.path.exists("../data/baddescr_youtube_large"): os.makedirs("../data/baddescr_youtube_large") #Grouping the scenes by movie for i, movieName in enumerate(movieDict.keys()): #Removing scene with a badly formated description if len(movieDict[movieName]) == 1: for scene in movieDict[movieName]: os.rename( scene, "../data/baddescr_youtube_large/" + os.path.basename(scene)) else: if not os.path.exists( "../data/youtube_large/{}".format(movieName)): os.makedirs("../data/youtube_large/{}".format(movieName)) for scene in movieDict[movieName]: os.rename( scene, "../data/youtube_large/{}/{}".format( movieName, os.path.basename(scene))) #Puting the descriptions in a folder if not os.path.exists("../data/descr_youtube_large"): os.makedirs("../data/descr_youtube_large") for descr in sorted(glob.glob("../data/youtube_large/*.description")): os.rename( descr, "../data/descr_youtube_large/{}".format( os.path.basename(descr))) #Removing bad characters in movie name: for movieFold in sorted(glob.glob("../data/youtube_large/*/")): os.rename(movieFold, removeBadChar_filename(movieFold)) for video in sorted(glob.glob("../data/youtube_large/*/*")): os.rename(video, removeBadChar_filename(video)) if args.merge_videos: if not os.path.exists("../data/{}/annotations".format(args.dataset)): os.makedirs("../data/{}/annotations".format(args.dataset)) #Collecting video folders where are stored all the clips videoFoldPaths = sorted(glob.glob("../data/{}/*/".format( args.dataset))) videoFoldPaths = list( filter(lambda x: x.find("annotations") == -1, videoFoldPaths)) for videoFoldPath in videoFoldPaths: print(videoFoldPath) #The temporary path to the concatenated video catVidPath = videoFoldPath[:-1] + "_tmp.{}".format( args.merge_videos) #Concatenate all the videos and build the ground truth file if (not os.path.exists(catVidPath.replace( "_tmp", ""))) or args.compute_only_gt: processVideo(catVidPath, videoFoldPath, args.merge_videos, args.compute_only_gt, args.dataset, vidExt=args.merge_videos) nbFrames = getNbFrames(catVidPath.replace("_tmp", "")) fps = utils.getVideoFPS(catVidPath.replace("_tmp", "")) #Detecting shots vidName = os.path.basename( os.path.splitext(catVidPath.replace("_tmp", ""))[0]) if not os.path.exists("../data/{}/{}/result.csv".format( args.dataset, vidName)): shotBoundsFrame = detect_format_shots( catVidPath.replace("_tmp", ""), args.shot_thres, nbFrames, fps) np.savetxt( "../data/{}/{}/result.csv".format(args.dataset, vidName), shotBoundsFrame) removeBadShotVideos(args.dataset, vidName) if args.format_bbc: videosPaths = sorted( glob.glob("../data/PlanetEarth/*.{}".format(args.format_bbc))) #This creates the bbc folder and the annotation folder in it if not os.path.exists("../data/bbc/annotations"): os.makedirs("../data/bbc/annotations") rawshotFilePaths = sorted( glob.glob("../data/PlanetEarth/annotations/shots/*.txt")) rawSceneFilePaths = sorted( glob.glob("../data/PlanetEarth/annotations/scenes/annotator_0/*")) for i, path in enumerate(videosPaths): print(path, rawshotFilePaths[i]) vidName = str(i) newPath = path.replace("PlanetEarth", "bbc") newPath = os.path.dirname(newPath) + "/" + vidName + ".{}".format( args.format_bbc) videoFold = os.path.splitext(newPath)[0] if not os.path.exists(videoFold): os.makedirs(videoFold) if not os.path.exists(newPath): #Copy video shutil.copyfile(path, newPath) #Extract audio extractAudio(newPath) if not os.path.exists(videoFold + "/result.csv"): nbFrames = getNbFrames(newPath) #Extract shots if args.detect_shot_bbc: fps = utils.getVideoFPS(newPath) shotCSV = detect_format_shots(newPath, args.shot_thres, nbFrames, fps) else: rawShotCSV = np.genfromtxt(rawshotFilePaths[i]) shotCSV = removeHoles(rawShotCSV) shotCSV[-1, 1] = nbFrames - 1 np.savetxt(videoFold + "/result.csv", shotCSV) else: shotCSV = np.genfromtxt(videoFold + "/result.csv") if not os.path.exists( "../data/bbc/annotations/{}_scenes.txt".format(vidName)): #Extract scenes: starts = np.genfromtxt(rawSceneFilePaths[i], delimiter=",")[:-1] shotNb = len(shotCSV) ends = np.concatenate((starts[1:] - 1, [shotNb - 1]), axis=0) starts, ends = starts[:, np.newaxis], ends[:, np.newaxis] #The scene boundaries expressed with shot index scenesS = np.concatenate((starts, ends), axis=1) #The scene boundaries expressed with frame index scenesF = utils.shots_to_frames( "../data/bbc/{}/result.csv".format(vidName), scenesS) np.savetxt( "../data/bbc/annotations/{}_scenes.txt".format(vidName), scenesF) if args.format_bbc2: torch.manual_seed(0) videosPaths = sorted( glob.glob("../data/PlanetEarth2/*.{}".format(args.format_bbc2[0]))) #This creates the bbc folder and the annotation folder in it if not os.path.exists("../data/bbc2/annotations"): os.makedirs("../data/bbc2/annotations") #rawshotFilePaths = sorted(glob.glob("../data/PlanetEarth2/annotations/shots/*.txt")) #rawSceneFilePaths = sorted(glob.glob("../data/PlanetEarth2/annotations/scenes/annotator_0/*")) for i, path in enumerate(videosPaths): print(path) vidName = str(i) newPath = path.replace("PlanetEarth2", "bbc2") newPath = os.path.dirname(newPath) + "/" + vidName + ".{}".format( args.format_bbc2[0]) videoFold = os.path.splitext(newPath)[0] if not os.path.exists(videoFold): os.makedirs(videoFold) #Copy video if not os.path.exists(newPath): shutil.copyfile(path, newPath) fps = utils.getVideoFPS(path) frameNb = round(float(pims.Video(path)._duration) * fps) #Extract shots if not os.path.exists( "../data/bbc2/{}/result.csv".format(vidName)): shotCSV = detect_format_shots(path, args.shot_thres, frameNb, fps) if not os.path.exists("../data/bbc2/{}/".format(vidName)): os.makedirs("../data/bbc2/{}/".format(vidName)) np.savetxt("../data/bbc2/{}/result.csv".format(vidName), shotCSV) else: shotCSV = np.genfromtxt(videoFold + "/result.csv") shotNb = len(shotCSV) #Randomly generates scenes: starts = generateRandomScenes(shotNb, float(args.format_bbc2[1])) ends = np.concatenate((starts[1:] - 1, [shotNb - 1]), axis=0) starts, ends = starts[:, np.newaxis], ends[:, np.newaxis] #The scene boundaries expressed with shot index scenesS = np.concatenate((starts, ends), axis=1) #The scene boundaries expressed with frame index scenesF = utils.shots_to_frames( "../data/bbc2/{}/result.csv".format(vidName), scenesS) np.savetxt( "../data/bbc2/annotations/{}_scenes.txt".format(vidName), scenesF) if args.format_ovsd: videosPaths = sorted(glob.glob("../data/OVSD/*.*"), key=lambda x: os.path.basename(x).lower()) videosPaths = list(filter(lambda x: x.find(".wav") == -1, videosPaths)) rawSceneFilePaths = sorted( glob.glob("../data/OVSD/annotations/*_scenes.txt"), key=lambda x: os.path.basename(x).lower()) for i, path in enumerate(videosPaths): print(path, rawSceneFilePaths[i]) vidName = os.path.basename(os.path.splitext(path)[0]) fps = utils.getVideoFPS(path) if hasattr(pims.Video(path), "_len"): frameNb = pims.Video(path)._len else: frameNb = round(float(pims.Video(path)._duration) * fps) #Removing holes in scenes segmentation rawSceneCSV = np.genfromtxt(rawSceneFilePaths[i]) sceneCSV = removeHoles(rawSceneCSV) if sceneCSV[-1, 1] < frameNb - 1 - fps: sceneCSV = np.concatenate( (sceneCSV, np.array([[sceneCSV[-1, 1] + 1, frameNb - 1]])), axis=0) else: sceneCSV[-1, 1] = frameNb - 1 np.savetxt(rawSceneFilePaths[i], sceneCSV) #Extract shots if not os.path.exists( "../data/OVSD/{}/result.csv".format(vidName)): shotBoundsFrame = detect_format_shots(path, args.shot_thres, frameNb, fps) if not os.path.exists("../data/OVSD/{}/".format(vidName)): os.makedirs("../data/OVSD/{}/".format(vidName)) np.savetxt("../data/OVSD/{}/result.csv".format(vidName), shotBoundsFrame) else: shotBoundsFrame = np.genfromtxt( "../data/OVSD/{}/result.csv".format(vidName)) shotBoundsFrame[-1, 1] = frameNb - 1 np.savetxt("../data/OVSD/{}/result.csv".format(vidName), shotBoundsFrame) if args.format_ally_mcbeal: videoPaths = sorted( glob.glob("../data/AllyMcBeal/*.{}".format( args.format_ally_mcbeal))) rawAnnotationFilePaths = sorted( glob.glob("../data/AllyMcBeal/Ally_McBeal.Annotations-1.1/*.pio")) if not os.path.exists("../data/allymcbeal/annotations"): os.makedirs("../data/allymcbeal/annotations") for i, videoPath in enumerate(videoPaths): print(videoPath, rawAnnotationFilePaths[i]) videoName = i newVideoPath = "../data/allymcbeal/{}.{}".format( videoName, args.format_ally_mcbeal) videoFold = os.path.splitext(newVideoPath)[0] #Copy video if not os.path.exists(newVideoPath): shutil.copyfile(videoPath, newVideoPath) if not os.path.exists(videoFold): os.makedirs(videoFold) fps = utils.getVideoFPS(newVideoPath) frameNb = round(float(pims.Video(newVideoPath)._duration) * fps) #Extract shots tripletToInterv(rawAnnotationFilePaths[i], "shots", fps, frameNb, videoFold + "/result.csv") #Extract scenes tripletToInterv( rawAnnotationFilePaths[i], "scenes", fps, frameNb, "../data/allymcbeal/annotations/{}_scenes.txt".format(i)) if args.format_rai: videoPaths = sorted(glob.glob("../data/RAIDataset/videos/*.mp4"), key=utils.findNumbers) rawAnnotationFilePaths = sorted( glob.glob("../data/RAIDataset/scenes_*.txt"), key=utils.findNumbers) if not os.path.exists("../data/rai/annotations"): os.makedirs("../data/rai/annotations") for i, videoPath in enumerate(videoPaths): print(videoPath, rawAnnotationFilePaths[i]) vidName = i newVideoPath = "../data/rai/{}.mp4".format(vidName) videoFold = os.path.splitext(newVideoPath)[0] #Copy video if not os.path.exists(newVideoPath): shutil.copyfile(videoPath, newVideoPath) if not os.path.exists(videoFold): os.makedirs(videoFold) fps = utils.getVideoFPS(newVideoPath) frameNb = round(float(pims.Video(newVideoPath)._duration) * fps) #Extract shots if not os.path.exists("../data/rai/{}/result.csv".format(vidName)): shotBoundsFrame = detect_format_shots(newVideoPath, args.shot_thres, frameNb, fps) np.savetxt("../data/rai/{}/result.csv".format(vidName), shotBoundsFrame) else: shotBoundsFrame = np.genfromtxt( "../data/rai/{}/result.csv".format(vidName)) if shotBoundsFrame[-1, 1] != frameNb - 1: shotBoundsFrame[-1, 1] = frameNb - 1 np.savetxt("../data/rai/{}/result.csv".format(vidName), shotBoundsFrame) scenes = np.genfromtxt( "../data/RAIDataset/scenes_{}.txt".format(vidName + 1)) scenes[-1, 1] = frameNb np.savetxt("../data/rai/annotations/{}_scenes.txt".format(vidName), scenes - 1)
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument( '--max_act', type=str, nargs='*', metavar='VAL', help= 'To visualise an image that maximise the activation of one unit in the last layer. \ The values are :\ the path to the model, \ the number of images to be created, \ the layer to optimise. Can be \'conv\' or \'dense\' \ the unit to optimise. If not indicated, the unit number i will be optimised if image has label number i.' ) argreader.parser.add_argument( '--stop_thres', type=float, default=0.000005, metavar='NOISE', help= 'If the distance travelled by parameters during activation maximisation become lesser than this parameter, the optimisation stops.' ) argreader.parser.add_argument( '--reg_weight', type=float, default=0, metavar='NOISE', help='The weight of the regularisation during activation maximisation.' ) argreader.parser.add_argument( '--plot_feat_map', type=str, nargs='*', metavar='VAL', help='To visualise the last feature map of a model. \ The values are the path to the model weights, the number of input image to be pass through \ the net and the number of final feature map to plot. \ The --exp_id, --model_id and --model must be set.') #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args args.cuda = not args.no_cuda and torch.cuda.is_available() #The folders where the experience file will be written if not (os.path.exists("../vis/{}".format(args.exp_id))): os.makedirs("../vis/{}".format(args.exp_id)) if args.max_act: modelPath = args.max_act[0] nbImages = int(args.max_act[1]) layToOpti = args.max_act[2] random.seed(args.seed) #Building the net model = netBuilder.netMaker(args) model.load_state_dict(torch.load(modelPath)) _, test_loader, _ = dataLoader.loadData(args.dataset, args.batch_size, 1, False, args.cuda, args.num_workers) #Comouting image that maximises activation of the given unit in the given layer maxInd = len(test_loader.dataset) - 1 model.eval() for i, (image, label) in enumerate(test_loader): print("Image ", i) img = Variable(test_loader.dataset[i][0]).unsqueeze(0) img.requires_grad = True writeImg('../vis/{}/img_'.format(args.exp_id) + str(i) + '.jpg', image[0].detach().numpy()) if len(args.max_act) == 4: unitInd = int(args.max_act[3]) else: unitInd = label.item() opt(img,model,args.exp_id,args.model_id,i,unitInd=unitInd,lr=args.lr,momentum=args.momentum,optimType='LBFGS',layToOpti=layToOpti,\ epoch=args.epochs,nbPrint=args.log_interval,stopThre=args.stop_thres,reg_weight=args.reg_weight) if i == nbImages - 1: break if args.plot_feat_map: modelPath = args.plot_feat_map[0] nbImages = int(args.plot_feat_map[1]) nbFeatMaps = int(args.plot_feat_map[2]) margin = 2 #Building the net model = netBuilder.netMaker(args) model.load_state_dict(torch.load(modelPath)) _, test_loader, _ = dataLoader.loadData(args.dataset, args.batch_size, 1, False, args.cuda, args.num_workers) #Comouting image that maximises activation of the given unit in the given layer maxInd = len(test_loader.dataset) - 1 model.eval() bigImg = None totalW = 0 totalH = 0 sortedMapInds = getMostImportantFeatMapsInd(model, args.exp_id, args.model_id) imgLabelList = [test_loader.dataset[i] for i in range(nbImages)] imgList, _ = zip(*sorted(imgLabelList, key=lambda x: x[1])) for i in range(nbImages): img = imgList[i] inSize = img.shape[1], img.shape[2] if bigImg is None: bigImg = np.zeros((nbImages * (img.shape[1] + margin), (nbFeatMaps + 1) * (img.shape[2] + margin))) bigImg[i * (img.shape[1] + margin):(i + 1) * img.shape[1] + i * margin, :img.shape[2]] = img.squeeze() _, featMaps = model(img.unsqueeze(0)) #Taking only the most important feature map print(featMaps.shape) featMaps = featMaps[0, sortedMapInds] for j in range(1, min(11, len(featMaps[0] + 1))): img = featMaps[j].detach().numpy() img = resize(img, inSize, mode="constant", order=0, anti_aliasing=True) bigImg[i * (img.shape[0] + margin):(i + 1) * img.shape[0] + i * margin, j * (img.shape[1] + margin):(j + 1) * (img.shape[1]) + j * margin] = img totalW += img.shape[0] + margin writeImg('../vis/{}/model_{}.png'.format(args.exp_id, args.model_id), bigImg[np.newaxis], size=(300 * nbImages, 300 * min(11, len(featMaps[0] + 1))))
def main(argv=None): #Getting arguments from config file and command line #Building the arg reader argreader = ArgReader(argv) argreader.parser.add_argument( '--comp_gt', type=str, nargs="*", metavar='PARAM', help= 'To compare the parameters found with the ground truth parameters. Require a fake dataset. The argument should\ be the list of parameters varying across the different models in the experiment.' ) argreader.parser.add_argument( '--comp_gt_agr', type=str, nargs="*", metavar='PARAM', help= 'To compare the parameters found with the ground truth parameters. Require a fake dataset. The argument should\ be the list of parameters varying across the different models in the experiment. The accuracies of models having the same value for those parameters will be agregated.' ) argreader.parser.add_argument( '--comp_gt_evol', type=str, nargs="*", metavar='PARAM', help= 'To plot the evolution of the error across epochs. The argument should\ be the list of parameters varying across the different models in the experiment.' ) argreader.parser.add_argument( '--error_metric', type=str, metavar='ERROR', default="rmse", help= 'The error metric used in \'--comp_gt\' and \'--comp_gt_agr\'. Can be \'rmse\' or \'relative\'. Default is \'RMSE\'.' ) argreader.parser.add_argument( '--artif_data', action='store_true', help= 'To plot the real and empirical distribution of the parameters of a fake dataset. \ The fake dataset to plot is set by the --dataset argument' ) argreader.parser.add_argument( '--plot_param', type=str, nargs="*", help= 'To plot the error of every parameters at each epoch for each model. The argument values are the index of the models to plot.' ) argreader.parser.add_argument( '--plot_dist', type=int, nargs="*", help= 'To plot the distance travelled by each parameters and the negative log-likelihood at each epoch. \ The argument values are the index of the models to plot. The two last arguments are the epochs at which to start and finish the plot.' ) argreader.parser.add_argument( '--two_dim_repr', type=str, nargs="*", help= 'To plot the t-sne visualisation of the values taken by the parameters during training. \ The first argument value is the id of the model to plot and the second is the start epoch. The following argument are the parameters to plot.' ) argreader.parser.add_argument( '--conv_speed', type=str, nargs='*', metavar='ID', help= 'To plot the error as a function of the number of annotator. The value is a list of parameters varying between \ the reference models.') argreader.parser.add_argument( '--plot_video_raw_scores', type=str, nargs='*', metavar='ID', help= 'To plot histograms of scores for some videos of a dataset. The value of this argument is the list of videos \ line index to plot. The dataset should also be indicated with the dataset argument' ) argreader.parser.add_argument( '--plot_range_pca', type=float, nargs=4, metavar="RANGE", help= 'The range to use when ploting the PCA. The values should be indicated in this order : xmin,xmax,ymin,ymax.' ) argreader.parser.add_argument( '--plot_range_dist', type=float, nargs=2, metavar="RANGE", help= 'The range to use when ploting the distance. The values should be indicated in this order : ymin,ymax.' ) argreader.parser.add_argument( '--labels', type=str, nargs='*', metavar="RANGE", help= 'The label names for the model, in the order where they will be appear in the plot.' ) #Reading the comand line arg argreader.getRemainingArgs() #Getting the args from command line and config file args = argreader.args torch.manual_seed(args.seed) random.seed(args.seed) np.random.seed(args.seed) #The folders where the experience file will be written if not (os.path.exists("../vis/{}".format(args.exp_id))): os.makedirs("../vis/{}".format(args.exp_id)) if not (os.path.exists("../results/{}".format(args.exp_id))): os.makedirs("../results/{}".format(args.exp_id)) if not (os.path.exists("../models/{}".format(args.exp_id))): os.makedirs("../models/{}".format(args.exp_id)) scoreMat, distorNbList = load_data.loadData(args.dataset) if args.comp_gt: compareWithGroundTruth(args.exp_id, args.comp_gt, args.error_metric) if args.comp_gt_agr: compareWithGroundTruth(args.exp_id, args.comp_gt_agr, args.error_metric) agregateCpWGroundTruth( args.exp_id, "../results/{}/err_epoch-1.csv".format(args.exp_id)) agregateCpWGroundTruth( args.exp_id, "../results/{}/inclPerc_epoch-1.csv".format(args.exp_id)) if args.comp_gt_evol: #Find an id of one model in the experiment modelInd = findNumbers( os.path.basename( sorted(glob.glob("../models/{}/model*.ini".format( args.exp_id)))[0])) #The list of epoch number that have been logged epochs = sorted( list( map( lambda x: findNumbers(os.path.basename(x).split("_")[1]), glob.glob("../results/{}/model{}_epoch*_{}.csv".format( args.exp_id, modelInd, paramKeys[0]))))) epochs = np.array(epochs) csvDict = {} for epoch in epochs: if not os.path.exists("../results/{}/err_epoch{}_agreg.csv".format( args.exp_id, epoch)): compareWithGroundTruth(args.exp_id, args.comp_gt_evol, args.error_metric, epoch=epoch) agregateCpWGroundTruth( args.exp_id, "../results/{}/err_epoch{}.csv".format(args.exp_id, epoch)) csvDict[epoch] = csvToDict( "../results/{}/err_epoch{}_agreg.csv".format( args.exp_id, epoch)) #Collect the values of the varying hyper parameters: #These values identifie the models from each other varHyperParamValues = csvDict[list(csvDict.keys())[0]].keys() for param in paramKeys: print("Ploting ", param) plt.figure() for i, hyperParam in enumerate(varHyperParamValues): points = list( map(lambda x: csvDict[x][hyperParam][param]['mean'], epochs)) stds = list( map(lambda x: csvDict[x][hyperParam][param]['std'], epochs)) plt.errorbar(epochs + 100 * i, points, yerr=stds, label="{}={}".format(args.comp_gt_evol, hyperParam)) plt.legend() plt.savefig("../vis/{}/err_evol_{}.png".format(args.exp_id, param)) if args.artif_data: fakeDataDIstr(args) if args.plot_param: plotParam(args.dataset, args.exp_id, args.plot_param, args.labels) if args.plot_dist: plotDist(args.exp_id, args.plot_dist[0], args.plot_dist[1], args.plot_dist[2], args.plot_range_dist) if args.two_dim_repr: twoDimRepr(args.exp_id, int(args.two_dim_repr[0]), int(args.two_dim_repr[1]), args.two_dim_repr[2:], args.plot_range_pca) if args.conv_speed: #Collect the configuration files configFiles = glob.glob("../models/{}/model*.ini".format(args.exp_id)) def get_Seed_NbAnnot(x): datasetName = readConfFile(x, ["dataset"])[0] seed, nb_annot = readConfFile("../data/{}.ini".format(datasetName), ["seed", "nb_annot"]) return int(seed), int(nb_annot) #Gets the ids, the seeds and the nb of annotators for every models in the experience ids = list(map(lambda x: findNumbers(os.path.basename(x)), configFiles)) seeds, nb_annots = zip(*list(map(get_Seed_NbAnnot, configFiles))) ids_seeds_nbAnnots = zip(ids, seeds, nb_annots) #Find the ids and seeds of models which are trained on the full dataset argmaxs = np.argwhere(nb_annots == np.amax(nb_annots)).flatten() ids = np.array(ids)[argmaxs] seeds = np.array(seeds)[argmaxs] #Sort with the ids value to make debut easier ids, seeds = zip(*sorted(zip(ids, seeds), key=lambda x: x[0])) convSpeed(args.exp_id, ids, seeds, args.conv_speed) if args.plot_video_raw_scores: plotVideoRawScores(args.dataset, args.plot_video_raw_scores, args.score_min, args.score_max)