def main(): args = init_args() # Prepare the dataloader train_dataloaders, validation_dataloaders, test_dataloader, args = initialize_dataloader( args, subset=None) # Prepare the model model, criterion, optimizer = initialize_model(args) best_validation_loss = evaluate(model, validation_dataloaders, criterion) log(-1, args, validation_loss=best_validation_loss) training_losses = [] validation_losses = [] model.train() epoch = 0 # Iterate through the data while best_validation_loss > args.threshold: epoch += 1.0 training_loss = 0.0 n_batches = 0.0 env = np.random.choice(args.training_agents) for observations, actions, target in tqdm(train_dataloaders[env]): # Zero out the gradient for this round of updates optimizer.zero_grad() # Conduct a forward pass of the transformer prediction = model.forward(observations, actions) # Compare the output of the model to the target prediction = torch.Tensor(prediction.flatten()) target = torch.Tensor(target.flatten().float()) loss = criterion(prediction, target) # Update the model loss.backward() optimizer.step() training_loss += loss.item() n_batches += 1.0 # Check against the validation dataset validation_loss = evaluate(model, validation_dataloaders, criterion) # Scale by the batch size training_loss = training_loss / n_batches # Save the losses training_losses.append(training_loss) validation_losses.append(validation_loss) np.save(f'{args.model_dir}/log/training_losses.npy', training_losses) np.save(f'{args.model_dir}/log/validation_losses.npy', validation_losses) # Update the logs log(epoch, args, validation_loss=validation_loss, training_loss=training_loss) # Save model if validation_loss < best_validation_loss: save_model(model, args, epoch) best_validation_loss = validation_loss # Apply to test dataset test_loss = evaluate(model, test_dataloader, criterion) log(-2, args, test_loss=test_loss)
def meta_train(): if datasource == 'sine_line': data_generator = DataGenerator(num_samples=num_samples_per_class) # create dummy sampler all_class_train = [0] * 10 else: all_class_train, all_data_train = load_dataset( dataset_name=datasource, subset=train_set ) all_class_val, all_data_val = load_dataset( dataset_name=datasource, subset=val_set ) all_class_train.update(all_class_val) all_data_train.update(all_data_val) # initialize data loader train_loader = initialize_dataloader( all_classes=[class_label for class_label in all_class_train], num_classes_per_task=num_classes_per_task ) for epoch in range(resume_epoch, resume_epoch + num_epochs): # variables used to store information of each epoch for monitoring purpose meta_loss_saved = [] # meta loss to save val_accuracies = [] train_accuracies = [] meta_loss = 0 # accumulate the loss of many ensambling networks to descent gradient for meta update num_meta_updates_count = 0 meta_loss_avg_print = 0 # compute loss average to print meta_loss_avg_save = [] # meta loss to save task_count = 0 # a counter to decide when a minibatch of task is completed to perform meta update while (task_count < num_tasks_per_epoch): for class_labels in train_loader: if datasource == 'sine_line': x_t, y_t, x_v, y_v = get_task_sine_line_data( data_generator=data_generator, p_sine=p_sine, num_training_samples=num_training_samples_per_class, noise_flag=True ) x_t = torch.tensor(x_t, dtype=torch.float, device=device) y_t = torch.tensor(y_t, dtype=torch.float, device=device) x_v = torch.tensor(x_v, dtype=torch.float, device=device) y_v = torch.tensor(y_v, dtype=torch.float, device=device) else: x_t, y_t, x_v, y_v = get_train_val_task_data( all_classes=all_class_train, all_data=all_data_train, class_labels=class_labels, num_samples_per_class=num_samples_per_class, num_training_samples_per_class=num_training_samples_per_class, device=device ) w_task = adapt_to_task(x=x_t, y=y_t, w0=theta) y_pred = net.forward(x=x_v, w=w_task) loss_NLL = loss_fn(input=y_pred, target=y_v) if torch.isnan(loss_NLL).item(): sys.exit('NaN error') # accumulate meta loss meta_loss = meta_loss + loss_NLL task_count = task_count + 1 if task_count % num_tasks_per_minibatch == 0: meta_loss = meta_loss/num_tasks_per_minibatch # accumulate into different variables for printing purpose meta_loss_avg_print += meta_loss.item() op_theta.zero_grad() meta_loss.backward() torch.nn.utils.clip_grad_norm_(parameters=theta.values(), max_norm=10) op_theta.step() # Printing losses num_meta_updates_count += 1 if (num_meta_updates_count % num_meta_updates_print == 0): meta_loss_avg_save.append(meta_loss_avg_print/num_meta_updates_count) print('{0:d}, {1:2.4f}'.format( task_count, meta_loss_avg_save[-1] )) num_meta_updates_count = 0 meta_loss_avg_print = 0 if (task_count % num_tasks_save_loss == 0): meta_loss_saved.append(np.mean(meta_loss_avg_save)) meta_loss_avg_save = [] print('Saving loss...') if datasource != 'sine_line': val_accs = validate_classification( all_classes=all_class_val, all_data=all_data_val, num_val_tasks=100, p_rand=0.5, uncertainty=False, csv_flag=False ) val_acc = np.mean(val_accs) val_ci95 = 1.96*np.std(val_accs)/np.sqrt(num_val_tasks) print('Validation accuracy = {0:2.4f} +/- {1:2.4f}'.format(val_acc, val_ci95)) val_accuracies.append(val_acc) train_accs = validate_classification( all_classes=all_class_train, all_data=all_data_train, num_val_tasks=100, p_rand=0.5, uncertainty=False, csv_flag=False ) train_acc = np.mean(train_accs) train_ci95 = 1.96*np.std(train_accs)/np.sqrt(num_val_tasks) print('Train accuracy = {0:2.4f} +/- {1:2.4f}\n'.format(train_acc, train_ci95)) train_accuracies.append(train_acc) # reset meta loss meta_loss = 0 if (task_count >= num_tasks_per_epoch): break if ((epoch + 1)% num_epochs_save == 0): checkpoint = { 'theta': theta, 'meta_loss': meta_loss_saved, 'val_accuracy': val_accuracies, 'train_accuracy': train_accuracies, 'op_theta': op_theta.state_dict() } print('SAVING WEIGHTS...') checkpoint_filename = 'Epoch_{0:d}.pt'.format(epoch + 1) print(checkpoint_filename) torch.save(checkpoint, os.path.join(dst_folder, checkpoint_filename)) scheduler.step() print()