def process_state(state): if type(state) is tuple or type(state) is list: if use_gpu(): return tuple(s.cuda() for s in state) else: return tuple(s for s in state) else: return (state.cuda(),) if use_gpu() else (state,)
def fit(model, train, test, num_boost_round=360, verbose_eval=1, export=False, training_params=None, export_params=None, **kwargs): if not use_gpu(): print_errors('XGBoost can only be executed on a GPU for the moment', do_exit=True) training_params = {} if training_params is None else training_params export_params = {} if export_params is None else export_params d_test = xgb.DMatrix(np.asarray(test.get_vectors()), label=np.asarray(test.labels)) if not validation_only: print_h1('Training: ' + special_parameters.setup_name) print_info("get vectors...") X = np.asarray(train.get_vectors()) y = np.asarray(train.labels) d_train = xgb.DMatrix(X, label=y) gpu_id = first_device().index kwargs['verbosity'] = verbose_level() kwargs['gpu_id'] = gpu_id eval_list = [(d_test, 'eval'), (d_train, 'train')] print_info("fit model...") bst = xgb.train(kwargs, d_train, num_boost_round=num_boost_round, verbose_eval=verbose_eval, evals=eval_list, xgb_model=model) print_info("Save model...") save_model(bst) else: bst = load_model() print_h1('Validation/Export: ' + special_parameters.setup_name) predictions = bst.predict(d_test, ntree_limit=bst.best_ntree_limit) res = validate(predictions, np.array(test.labels), training_params['metrics'] if 'metrics' in training_params else tuple(), final=True) print_notification(res, end='') if export: export_results(test, predictions, **export_params)
def create_model(model_class, model_params=None, model_name='model'): """ create and eventually load model :param model_name: :param model_class: :param model_params: :param model_name: :return: """ model_params = {} if model_params is None else model_params model = model_class(**model_params) if special_parameters.load_model: # recover from checkpoint _load_model(model, model_name) # configure usage on GPU if use_gpu(): model.to(first_device()) model = torch.nn.DataParallel(model, device_ids=all_devices()) # print info about devices print_info('Device(s)): ' + str(device_description())) return model
def __init__(self, prior, *args, **kwargs): super().__init__() # Variable(torch.from_numpy(np.log(self.prior)).float()) # eventually set the prior on the GPU if use_gpu(): self.prior = torch.from_numpy(np.log(prior)).float().cuda() else: self.prior = torch.from_numpy(np.log(prior)).float() self.criterion = nn.CrossEntropyLoss(*args, **kwargs)
def loss(self, output, label): # constructing a one hot encoding structure one_hot = torch.zeros(size=output.size()) # eventually put it on the GPU if use_gpu(): one_hot = one_hot.cuda() # set the same number of dimension to label label = label.long().unsqueeze(1) # fill one_hot based on the label one_hot = one_hot.scatter_(1, label, 1.) return self.criterion(output.view(-1), one_hot.view(-1))
def construct_action(epsilon, model_z, state, output_size): random_action = random.random() <= epsilon action_index = [ torch.randint(output_size, torch.Size([]), dtype=torch.int) if random_action else torch.argmax(model_z(*state)[0]) ][0] action = torch.zeros([output_size], dtype=torch.float32) if use_gpu(): action = action.cuda() action[action_index] = 1 return action
def _optimization(model_z, batch, gamma, optimizer_, loss): """ Optimizing the model for a random batch :param batch: the current batch that will be used to optimize the model :param model_z: the model to train :param gamma: the gamma value for the Q function :param optimizer_: the optimizer :param loss: the loss criterion :return: the loss value """ model_z.train() # processing mini batches state_batch, action_batch, state_1_batch, reward_batch, finished_batch = batch state_batch = process_state(state_batch) state_1_batch = process_state(state_1_batch) # eventually combine state and reward so that the model can train on both if use_gpu(): # put on GPU if the user asked it action_batch = action_batch.cuda() reward_batch = reward_batch.cuda() finished_batch = finished_batch.cuda() output_1_batch = model_z(*state_1_batch) finished = finished_batch.unsqueeze(1).float() reward_batch = reward_batch.unsqueeze(1).float() # Bellman equation y_batch = reward_batch + gamma * torch.max(torch.mul(output_1_batch, 1 - finished), dim=1)[0].unsqueeze(1) y_batch = y_batch.detach() # y_batch is not trainable as it is the target output = model_z(*state_batch) # if state and reward are combined to have more complex training procedures, # this line should be replaced with a loss function q_value = torch.sum(output * action_batch.float(), dim=1).unsqueeze(1) optimizer_.zero_grad() loss_value = loss(q_value, y_batch) loss_value.backward() optimizer_.step() return loss_value.item()
def fit(model_z, train, test, val=None, training_params=None, predict_params=None, validation_params=None, export_params=None, optim_params=None, model_selection_params=None): """ This function is the core of an experiment. It performs the ml procedure as well as the call to validation. :param training_params: parameters for the training procedure :param val: validation set :param test: the test set :param train: The training set :param optim_params: :param export_params: :param validation_params: :param predict_params: :param model_z: the model that should be trained :param model_selection_params: """ # configuration training_params, predict_params, validation_params, export_params, optim_params, \ cv_params = merge_dict_set( training_params, TRAINING_PARAMS, predict_params, PREDICT_PARAMS, validation_params, VALIDATION_PARAMS, export_params, EXPORT_PARAMS, optim_params, OPTIM_PARAMS, model_selection_params, MODEL_SELECTION_PARAMS ) train_loader, test_loader, val_loader = _dataset_setup( train, test, val, **training_params) statistics_path = output_path('metric_statistics.dump') metrics_stats = Statistics( model_z, statistics_path, ** cv_params) if cv_params.pop('cross_validation') else None validation_path = output_path('validation.txt') # training parameters optim = optim_params.pop('optimizer') iterations = training_params.pop('iterations') gamma = training_params.pop('gamma') loss = training_params.pop('loss') log_modulo = training_params.pop('log_modulo') val_modulo = training_params.pop('val_modulo') first_epoch = training_params.pop('first_epoch') # callbacks for ml tests vcallback = validation_params.pop( 'vcallback') if 'vcallback' in validation_params else None if iterations is None: print_errors( 'Iterations must be set', exception=TrainingConfigurationException('Iterations is None')) # before ml callback if vcallback is not None and special_parameters.train and first_epoch < max( iterations): init_callbacks(vcallback, val_modulo, max(iterations) // val_modulo, train_loader.dataset, model_z) max_iterations = max(iterations) if special_parameters.train and first_epoch < max(iterations): print_h1('Training: ' + special_parameters.setup_name) loss_logs = [] if first_epoch < 1 else load_loss('loss_train') loss_val_logs = [] if first_epoch < 1 else load_loss('loss_validation') opt = create_optimizer(model_z.parameters(), optim, optim_params) scheduler = MultiStepLR(opt, milestones=list(iterations), gamma=gamma) # number of batches in the ml epoch_size = len(train_loader) # one log per epoch if value is -1 log_modulo = epoch_size if log_modulo == -1 else log_modulo epoch = 0 for epoch in range(max_iterations): if epoch < first_epoch: # opt.step() _skip_step(scheduler, epoch) continue # saving epoch to enable restart export_epoch(epoch) model_z.train() # printing new epoch print_h2('-' * 5 + ' Epoch ' + str(epoch + 1) + '/' + str(max_iterations) + ' (lr: ' + str(scheduler.get_lr()) + ') ' + '-' * 5) running_loss = 0.0 for idx, data in enumerate(train_loader): # get the inputs inputs, labels = data # wrap labels in Variable as input is managed through a decorator # labels = model_z.p_label(labels) if use_gpu(): labels = labels.cuda() # zero the parameter gradients opt.zero_grad() outputs = model_z(inputs) loss_value = loss(outputs, labels) loss_value.backward() opt.step() # print math running_loss += loss_value.item() if idx % log_modulo == log_modulo - 1: # print every log_modulo mini-batches print('[%d, %5d] loss: %.5f' % (epoch + 1, idx + 1, running_loss / log_modulo)) # tensorboard support add_scalar('Loss/train', running_loss / log_modulo) loss_logs.append(running_loss / log_modulo) running_loss = 0.0 # end of epoch update of learning rate scheduler scheduler.step(epoch + 1) # saving the model and the current loss after each epoch save_checkpoint(model_z, optimizer=opt) # validation of the model if epoch % val_modulo == val_modulo - 1: validation_id = str(int((epoch + 1) / val_modulo)) # validation call predictions, labels, loss_val = predict( model_z, val_loader, loss, **predict_params) loss_val_logs.append(loss_val) res = '\n[validation_id:' + validation_id + ']\n' + validate( predictions, labels, validation_id=validation_id, statistics=metrics_stats, **validation_params) # save statistics for robust cross validation if metrics_stats: metrics_stats.save() print_notification(res) if special_parameters.mail == 2: send_email( 'Results for XP ' + special_parameters.setup_name + ' (epoch: ' + str(epoch + 1) + ')', res) if special_parameters.file: save_file( validation_path, 'Results for XP ' + special_parameters.setup_name + ' (epoch: ' + str(epoch + 1) + ')', res) # checkpoint save_checkpoint(model_z, optimizer=opt, validation_id=validation_id) # callback if vcallback is not None: run_callbacks(vcallback, (epoch + 1) // val_modulo) # save loss save_loss( { # // log_modulo * log_modulo in case log_modulo does not divide epoch_size 'train': (loss_logs, log_modulo), 'validation': (loss_val_logs, epoch_size // log_modulo * log_modulo * val_modulo) }, ylabel=str(loss)) # saving last epoch export_epoch(epoch + 1) # if --restart is set, the train will not be executed # callback if vcallback is not None: finish_callbacks(vcallback) # final validation if special_parameters.evaluate or special_parameters.export: print_h1('Validation/Export: ' + special_parameters.setup_name) if metrics_stats is not None: # change the parameter states of the model to best model metrics_stats.switch_to_best_model() predictions, labels, val_loss = predict(model_z, test_loader, loss, validation_size=-1, **predict_params) if special_parameters.evaluate: res = validate(predictions, labels, statistics=metrics_stats, **validation_params, final=True) print_notification(res, end='') if special_parameters.mail >= 1: send_email( 'Final results for XP ' + special_parameters.setup_name, res) if special_parameters.file: save_file( validation_path, 'Final results for XP ' + special_parameters.setup_name, res) if special_parameters.export: export_results(test_loader.dataset, predictions, **export_params) return metrics_stats
def predict(model, loader, loss, export=False, filters=tuple(), validation_size=10000, compute_loss=False): """ Give the prediction of the model on a test set :param compute_loss: :param filters: set some output to 0 :param validation_size: :param model: the model :param loader: the test set loader :param loss: the loss function :param export: if False the predictions are not saved, otherwise the results are exported on file. if export is true the loader must not be shuffled... :return: the arrays of predictions and corresponding labels """ if len(loader) > _memory_overflow_size and ( validation_size == -1 or validation_size > _memory_overflow_size): print_warning( '[predict] The dataset size is {}. Large datasets can cause memory ' 'overflow during standard prediction...'.format(len(loader))) with torch.no_grad(): total = 0 model.eval() y_preds = [] y_labels = [] running_loss = 0.0 idx = 0 if hasattr(model, 'last_sigmoid') and compute_loss: model.last_sigmoid = False elif hasattr(model, 'last_sigmoid'): model.last_sigmoid = True for idx, data in enumerate(loader): inputs, labels = data if use_gpu(): labels = labels.cuda() # wrap them in Variable labels_variable = loss.output(labels) outputs = model(inputs) # if not test set if compute_loss and labels[0] != -1: loss_value = loss(outputs, labels) running_loss += loss_value.item() outputs = loss.output(outputs) total += labels_variable.size(0) y_preds.extend(outputs.data.tolist()) y_labels.extend(labels_variable.data.tolist()) if total >= validation_size != -1 and not export: break running_loss /= (idx + 1) # normalizing the loss if compute_loss: print_info('Validation loss: ' + str(running_loss)) add_scalar('Loss/Validation', running_loss) predictions, labels = np.asarray(y_preds), np.asarray(y_labels) # filtering some predicted labels for f in filters: f(predictions) # TODO filtering official labels return predictions, labels, running_loss