The training loop of PPO. The driver process only need to call the compute functions of the worker group through RPC to construct the PPO dataflow. The light-weight advantage computation is done on the driver process.
(self)
| 24 | |
| 25 | |
| 26 | def fit(self): |
| 27 | """ |
| 28 | The training loop of PPO. |
| 29 | The driver process only need to call the compute functions of the worker group through RPC to construct the PPO dataflow. |
| 30 | The light-weight advantage computation is done on the driver process. |
| 31 | """ |
| 32 | from verl.utils.tracking import Tracking |
| 33 | from omegaconf import OmegaConf |
| 34 | |
| 35 | logger = Tracking(project_name=self.config.trainer.project_name, |
| 36 | experiment_name=self.config.trainer.experiment_name, |
| 37 | default_backend=self.config.trainer.logger, |
| 38 | config=OmegaConf.to_container(self.config, resolve=True)) |
| 39 | |
| 40 | self.global_steps = 0 |
| 41 | |
| 42 | # load checkpoint before doing anything |
| 43 | self._load_checkpoint() |
| 44 | |
| 45 | # perform validation before training |
| 46 | # currently, we only support validation using the reward_function. |
| 47 | if self.val_reward_fn is not None and self.config.trainer.get('val_before_train', True): |
| 48 | val_metrics = self._validate() |
| 49 | pprint(f'Initial validation metrics: {val_metrics}') |
| 50 | logger.log(data=val_metrics, step=self.global_steps) |
| 51 | if self.config.trainer.get('val_only', False): |
| 52 | return |
| 53 | |
| 54 | # we start from step 1 |
| 55 | self.global_steps += 1 |
| 56 | last_val_metrics = None |
| 57 | |
| 58 | for epoch in range(self.config.trainer.total_epochs): |
| 59 | for batch_dict in self.train_dataloader: |
| 60 | metrics = {} |
| 61 | timing_raw = {} |
| 62 | |
| 63 | batch: DataProto = DataProto.from_single_dict(batch_dict) |
| 64 | |
| 65 | # pop those keys for generation |
| 66 | gen_batch = batch.pop(batch_keys=['input_ids', 'attention_mask', 'position_ids']) |
| 67 | is_last_step = self.global_steps >= self.total_training_steps |
| 68 | |
| 69 | with _timer('step', timing_raw): |
| 70 | # generate a batch |
| 71 | with _timer('gen', timing_raw): |
| 72 | gen_batch_output = self.actor_rollout_wg.generate_sequences(gen_batch) |
| 73 | |
| 74 | if self.config.algorithm.adv_estimator == AdvantageEstimator.REMAX: |
| 75 | with _timer('gen_max', timing_raw): |
| 76 | gen_baseline_batch = deepcopy(gen_batch) |
| 77 | gen_baseline_batch.meta_info['do_sample'] = False |
| 78 | gen_baseline_output = self.actor_rollout_wg.generate_sequences(gen_baseline_batch) |
| 79 | |
| 80 | batch = batch.union(gen_baseline_output) |
| 81 | reward_baseline_tensor = self.reward_fn(batch) |
| 82 | reward_baseline_tensor = reward_baseline_tensor.sum(dim=-1) |
| 83 |
nothing calls this directly
no test coverage detected