Run the command with supplied configuration

def run(self):
        """ Run the command with supplied configuration """
        device = self.model_config.torch_device()
        learner = Learner(device, self.model_factory.instantiate())

        # All callbacks useful for learning
        callbacks = self.gather_callbacks()

        # Metrics to track through this training
        metrics = learner.metrics()

        # Check if training was already started and potentially continue where we left off
        training_info, hidden_state = self.resume_training(learner, callbacks, metrics)

        # Prepare current training phase
        current_phase_idx = self._select_phase_left_bound(training_info.start_epoch_idx)
        current_phase = self.phases[current_phase_idx]
        local_idx = training_info.start_epoch_idx - self.ladder[current_phase_idx]

        current_phase.set_up_phase(training_info, learner.model, self.source)
        print(current_phase.banner())

        if training_info.start_epoch_idx > 0:
            current_phase.restore(training_info, local_idx, learner.model, hidden_state)

        training_info.on_train_begin()

        for global_epoch_idx in range(training_info.start_epoch_idx + 1, self.full_number_of_epochs + 1):
            iteration_phase_idx = self._select_phase_right_bound(global_epoch_idx-1)
            local_idx = global_epoch_idx - self.ladder[iteration_phase_idx]

            # Phase preparations
            while current_phase_idx != iteration_phase_idx:
                current_phase.tear_down_phase(training_info, learner.model)

                current_phase_idx += 1
                current_phase = self.phases[current_phase_idx]

                current_phase.set_up_phase(training_info, learner.model, self.source)
                print(current_phase.banner())

            # Create epoch info
            epoch_info = current_phase.epoch_info(training_info, global_epoch_idx, local_idx)

            # Execute learning
            current_phase.execute_epoch(epoch_info, learner)

            # Epoch checkpoint
            self.storage.checkpoint(epoch_info, learner.model)

        # Tear down the last phase
        if current_phase is not None:
            current_phase.tear_down_phase(training_info, learner.model)

        training_info.on_train_end()

        return training_info