TRL documentation
GMPO
GMPO
En el artículo Geometric-Mean Policy Optimization, los autores proponen una variante de GRPO que maximiza la media geométrica de las relaciones de importancia a nivel de token, en lugar de la media aritmética. Dado que la media geométrica es mucho menos sensible a las relaciones atípicas, la actualización de la política es más estable y tolera un rango de recorte mucho más amplio. El recorte se aplica por token, en espacio logarítmico y de un solo lado según el signo de la ventaja (la región de confianza estándar de PPO), y, crucialmente, antes de calcular la media geométrica.
Para usar GMPO, puedes utilizar la clase experimental.gmpo.GMPOTrainer en trl.experimental.gmpo.
Uso
from trl.experimental.gmpo import GMPOConfig, GMPOTrainer
training_args = GMPOConfig(
epsilon=0.4, # log-space clip range -> ratios clipped to (exp(-0.4), exp(0.4)); paper, Sec. 4
beta=0.0,
)
trainer = GMPOTrainer(
model="Qwen/Qwen3-0.6B",
reward_funcs=...,
train_dataset=...,
args=training_args,
)
trainer.train()En GMPO, el recorte se aplica a las relaciones de importancia por token en espacio log (es decir, en espacio logarítmico) antes de calcular la media geométrica, por lo que epsilon y epsilon_high se expresan en espacio logarítmico: el rango efectivo de recorte de la relación es (exp(-epsilon), exp(epsilon_high)). El artículo recomienda un rango notablemente más amplio que el de GRPO/DAPO, (exp(-0.4), exp(0.4)), para fomentar la exploración.
GMPOTrainer
Trainer para Geometric-Mean Policy Optimization (GMPO).
GMPO (https://huggingface.co/papers/2507.20673) es una variante de GRPO que maximiza la media geométrica de las proporciones de importancia a nivel de token, en lugar de la media aritmética. Dado que la media geométrica es mucho menos sensible a las proporciones atípicas, la actualización de la política es más estable y se puede utilizar un rango de recorte mucho más amplio.
El único cambio con respecto a GRPOTrainer es _compute_loss. Todo lo demás (generación, cálculo de recompensas, sincronización de pesos, registro de métricas) se hereda sin cambios
entrenar
< source >( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput
Parámetros
- resume_from_checkpoint (
strobool, opcional) — Si es unastr, ruta local a un punto de control guardado por una instancia anterior deTrainer. Si es unbooly es igual aTrue, carga el último punto de control en args.output_dir guardado por una instancia anterior deTrainer. Si está presente, el entrenamiento se reanudará desde los estados del modelo/optimizador/planificador cargados aquí. - trial (
optuna.Trialodict[str, Any], opcional) — La ejecución del ensayo o el diccionario de hiperparámetros para la búsqueda de hiperparámetros. - ignore_keys_for_eval (
list[str], opcional) — Una lista de claves en la salida de tu modelo (si es un diccionario) que deben ignorarse al recopilar predicciones para la evaluación durante el entrenamiento.
Devuelve
~trainer_utils.TrainOutput
Objeto que contiene el número de pasos globales, la pérdida de entrenamiento y las métricas.
Punto de entrada principal del entrenamiento.
Guardará el modelo, por lo que podrás recargarlo usando from_pretrained().
Solo se guardará desde el proceso principal.
push_to_hub
< source >( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = None**kwargs )
Parámetros
- commit_message (
str, opcional, valor predeterminado"End of training") — Mensaje para el commit al hacer push. - blocking (
bool, opcional, valor predeterminadoTrue) — Si la función debe devolver el control solo cuando elgit pushhaya terminado. - token (
str, opcional, valor predeterminadoNone) — Token con permiso de escritura para sobrescribir los argumentos originales de Trainer. - revision (
str, opcional) — La revisión de git desde la que se realizará el commit. Por defecto, es la cabecera de la rama “main”. - kwargs (
dict[str, Any], opcional) — Argumentos de palabra clave adicionales que se pasan a~Trainer.create_model_card.
Sube self.model y self.processing_class al hub de modelos de 🤗 en el repositorio self.args.hub_model_id.
GMPOConfig
clase trl.experimental.gmpo.GMPOConfig
< source >( output_dir: str | None = Noneper_device_train_batch_size: int = 8num_train_epochs: float = 3.0max_steps: int = -1learning_rate: float = 1e-06lr_scheduler_type: transformers.trainer_utils.SchedulerType | str = 'linear'lr_scheduler_kwargs: dict | str | None = Nonewarmup_steps: float = 0optim: transformers.training_args.OptimizerNames | str = 'adamw_torch_fused'optim_args: str | None = Noneweight_decay: float = 0.0adam_beta1: float = 0.9adam_beta2: float = 0.999adam_epsilon: float = 1e-08optim_target_modules: None | str | list[str] = Nonegradient_accumulation_steps: int = 1average_tokens_across_devices: bool = Truemax_grad_norm: float = 1.0label_smoothing_factor: float = 0.0bf16: bool | None = Nonefp16: bool = Falsebf16_full_eval: bool = Falsefp16_full_eval: bool = Falsetf32: bool | None = Nonegradient_checkpointing: bool = Truegradient_checkpointing_kwargs: dict[str, typing.Any] | str | None = Nonetorch_compile: bool = Falsetorch_compile_backend: str | None = Nonetorch_compile_mode: str | None = Noneuse_liger_kernel: bool = Falseliger_kernel_config: dict[str, bool] | None = Noneuse_cache: bool = Falseneftune_noise_alpha: float | None = Nonetorch_empty_cache_steps: int | None = Noneauto_find_batch_size: bool = Falselogging_strategy: transformers.trainer_utils.IntervalStrategy | str = 'steps'logging_steps: float = 10logging_first_step: bool = Falselog_on_each_node: bool = Truelogging_nan_inf_filter: bool = Trueinclude_num_input_tokens_seen: str | bool = 'no'log_level: str = 'passive'log_level_replica: str = 'warning'disable_tqdm: bool | None = Nonereport_to: None | str | list[str] = 'none'run_name: str | None = Noneproject: str = 'huggingface'trackio_space_id: str | None = Nonetrackio_bucket_id: str | None = Nonetrackio_static_space_id: typing.Union[str, NoneType, typing.Literal[False]] = Noneeval_strategy: transformers.trainer_utils.IntervalStrategy | str = 'no'eval_steps: float | None = Noneeval_delay: float = 0per_device_eval_batch_size: int = 8prediction_loss_only: bool = Falseeval_on_start: bool = Falseeval_do_concat_batches: bool = Trueeval_use_gather_object: bool = Falseeval_accumulation_steps: int | None = Noneinclude_for_metrics: list[str] = <factory>batch_eval_metrics: bool = Falsesave_only_model: bool = Falsesave_strategy: transformers.trainer_utils.SaveStrategy | str = 'steps'save_steps: float = 500save_on_each_node: bool = Falsesave_total_limit: int | None = Noneenable_jit_checkpoint: bool = Falsepush_to_hub: bool = Falsehub_token: str | None = Nonehub_private_repo: bool | None = Nonehub_model_id: str | None = Nonehub_strategy: transformers.trainer_utils.HubStrategy | str = 'every_save'hub_always_push: bool = Falsehub_revision: str | None = Noneload_best_model_at_end: bool = Falsemetric_for_best_model: str | None = Nonegreater_is_better: bool | None = Noneignore_data_skip: bool = Falserestore_callback_states_from_checkpoint: bool = Falsefull_determinism: bool = Falseseed: int = 42data_seed: int | None = Noneuse_cpu: bool = Falseaccelerator_config: dict | str | None = Noneparallelism_config: accelerate.parallelism_config.ParallelismConfig | None = Nonedataloader_drop_last: bool = Falsedataloader_num_workers: int = 0dataloader_pin_memory: bool = Truedataloader_persistent_workers: bool = Falsedataloader_prefetch_factor: int | None = Nonedataloader_multiprocessing_context: str | None = Nonedataloader_in_order: bool = Trueremove_unused_columns: bool | None = Falselabel_names: list[str] | None = Nonetrain_sampling_strategy: str = 'random'length_column_name: str = 'length'ddp_find_unused_parameters: bool | None = Noneddp_bucket_cap_mb: int | None = Noneddp_broadcast_buffers: bool | None = Noneddp_static_graph: bool | None = Noneddp_backend: str | None = Noneddp_timeout: int = 1800fsdp: str | None = Nonefsdp_config: dict[str, typing.Any] | str | None = Nonedeepspeed: dict | str | None = Nonedebug: str | list[transformers.debug_utils.DebugOption] = ''skip_memory_metrics: bool = Truedo_train: bool = Falsedo_eval: bool = Falsedo_predict: bool = Falseresume_from_checkpoint: str | None = Nonelocal_rank: int = -1model_init_kwargs: dict[str, typing.Any] | str | None = Nonetrust_remote_code: bool = Falserouter_aux_loss_coef: float | None = Nonedisable_dropout: bool = Falsecast_lm_head_to_fp32: bool = Falsenum_generations: int | None = 8num_generations_eval: int | None = Nonemax_completion_length: int | None = 512ds3_gather_for_generation: bool = Trueshuffle_dataset: bool | None = Truepad_to_multiple_of: int | str | None = 'auto'generation_batch_size: int | None = Nonesteps_per_generation: int | None = Nonetemperature: float = 1.0top_p: float = 1.0top_k: int = 0min_p: float | None = Nonegeneration_kwargs: dict | str | None = Nonechat_template_kwargs: dict | str | None = Nonerepetition_penalty: float = 1.0cache_implementation: str | None = Noneuse_vllm: bool = Falsevllm_mode: str = 'colocate'vllm_model_impl: str = 'vllm'vllm_enable_sleep_mode: bool = Falsevllm_structured_outputs_regex: str | None = Nonevllm_server_base_url: str | None = Nonevllm_server_host: str = '0.0.0.0'vllm_server_port: int = 8000vllm_server_timeout: float = 240.0vllm_group_port: int = 51216vllm_gpu_memory_utilization: float = 0.3vllm_max_model_length: int | None = Nonevllm_tensor_parallel_size: int = 1beta: float = 0.0num_iterations: int = 1epsilon: float = 0.4delta: float | None = Noneepsilon_high: float | None = Nonesapo_temperature_neg: float = 1.05sapo_temperature_pos: float = 1.0vespo_k_pos: float = 2.0vespo_lambda_pos: float = 3.0vespo_k_neg: float = 3.0vespo_lambda_neg: float = 2.0importance_sampling_level: str = 'token'reward_weights: list[float] | None = Nonemulti_objective_aggregation: str = 'sum_then_normalize'scale_rewards: str = 'group'loss_type: str = 'dapo'mask_truncated_completions: bool = Falsesync_ref_model: bool = Falseref_model_mixup_alpha: float = 0.6ref_model_sync_steps: int = 512top_entropy_quantile: float = 1.0entropy_coef: float = 0.0use_adaptive_entropy: bool = Falseentropy_coef_min: float = 0.0entropy_coef_max: float = 1.0entropy_coef_delta: float = 0.005entropy_target: float = 0.2max_tool_calling_iterations: int | None = Nonevllm_importance_sampling_correction: bool = Truevllm_importance_sampling_mode: str = 'sequence_mask'vllm_importance_sampling_clip_max: float | None = 3.0vllm_importance_sampling_clip_min: float | None = Noneoff_policy_mask_threshold: float | None = Noneuse_bias_correction_kl: bool = Truelog_completions: bool = Falselog_multimodal: bool = Truenum_completions_to_print: int | None = Nonelog_unique_prompts: bool = Falselog_completions_hub_repo: str | None = Noneuse_transformers_continuous_batching: bool = Falsetransformers_continuous_batching_config: dict | str | None = Noneuse_transformers_paged: bool = Falsevllm_importance_sampling_cap: float | None = None )
Parámetros
- epsilon (
float, opcional, valor predeterminado0.4) — Valor de recorte del límite inferior, expresado en espacio logarítmico. El límite inferior de la proporción de importancia por token esexp(-epsilon). - epsilon_high (
float, opcional) — Valor de recorte superior, expresado en espacio logarítmico. Si esNone, toma por defecto el valor deepsilon. El límite superior de la proporción de importancia por token esexp(epsilon_high).
Clase de configuración para experimental.gmpo.GMPOTrainer.
experimental.gmpo.GMPOConfig hereda todos los parámetros de GRPOConfig; solo cambia el significado y el valor predeterminado del rango de recorte. En GMPO, el recorte se aplica a las relaciones de importancia por token en log (es decir, en el espacio logarítmico) antes de calcular la media geométrica, por lo que epsilon y epsilon_high se expresan en el espacio logarítmico: el rango efectivo de recorte de la relación es (exp(-epsilon), exp(epsilon_high)). El artículo de GMPO recomienda un rango notablemente más amplio que el de GRPO/DAPO, (exp(-0.4), exp(0.4)), para fomentar la exploración.