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