重要提示

您正在查看 NeMo 2.0 文档。此版本引入了 API 的重大更改和一个新的库,NeMo Run。我们目前正在将 NeMo 1.0 的所有功能移植到 2.0。有关先前版本或 2.0 中尚未提供的功能的文档,请参阅 NeMo 24.07 文档

实验管理器#

NeMo 框架实验管理器利用 PyTorch Lightning 进行模型检查点、TensorBoard 日志记录、Weights and Biases、DLLogger 和 MLFlow 日志记录。实验管理器默认包含在所有 NeMo 示例脚本中。

要使用实验管理器,请调用 exp_manager 并传入 PyTorch Lightning Trainer

exp_dir = exp_manager(trainer, cfg.get("exp_manager", None))

实验管理器可以使用带有 Hydra 的 YAML 进行配置。

exp_manager:
    exp_dir: /path/to/my/experiments
    name: my_experiment_name
    create_tensorboard_logger: True
    create_checkpoint_callback: True

(可选)启动 TensorBoard 以查看 exp_dir 中的训练结果,默认情况下 exp_dir 设置为 ./nemo_experiments

tensorboard --bind_all --logdir nemo_experiments

如果 create_checkpoint_callback 设置为 True,则 NeMo 会在使用 PyTorch Lightning 的 ModelCheckpoint 进行训练期间自动创建检查点。我们可以通过 YAML 或 CLI 配置 ModelCheckpoint

exp_manager:
    ...
    # configure the PyTorch Lightning ModelCheckpoint using checkpoint_call_back_params
    # any ModelCheckpoint argument can be set here

    # save the best checkpoints based on this metric
    checkpoint_callback_params.monitor=val_loss

    # choose how many total checkpoints to save
    checkpoint_callback_params.save_top_k=5

恢复训练#

要自动恢复训练,请配置 exp_manager。此功能对于可能在程序完成之前中断或关闭的长时间训练运行非常重要。要自动恢复训练,请通过 YAML 或 CLI 设置以下参数

exp_manager:
    ...
    # resume training if checkpoints already exist
    resume_if_exists: True

    # to start training with no existing checkpoints
    resume_ignore_no_checkpoint: True

    # by default experiments will be versioned by datetime
    # we can set our own version with
    exp_manager.version: my_experiment_version

实验记录器#

除了 Tensorboard,NeMo 还支持 Weights and Biases、MLFlow、DLLogger、ClearML 和 NeptuneLogger。要使用这些记录器,请通过 YAML 或 ExpManagerConfig 设置以下内容。

Weights and Biases (WandB)#

exp_manager:
    ...
    create_checkpoint_callback: True
    create_wandb_logger: True
    wandb_logger_kwargs:
        name: ${name}
        project: ${project}
        entity: ${entity}
        <Add any other arguments supported by WandB logger here>

MLFlow#

exp_manager:
    ...
    create_checkpoint_callback: True
    create_mlflow_logger: True
    mlflow_logger_kwargs:
        experiment_name: ${name}
        tags:
            <Any key:value pairs>
        save_dir: './mlruns'
        prefix: ''
        artifact_location: None
        # provide run_id if resuming a previously started run
        run_id: Optional[str] = None

DLLogger#

exp_manager:
    ...
    create_checkpoint_callback: True
    create_dllogger_logger: True
    dllogger_logger_kwargs:
        verbose: False
        stdout: False
        json_file: "./dllogger.json"

ClearML#

exp_manager:
    ...
    create_checkpoint_callback: True
    create_clearml_logger: True
    clearml_logger_kwargs:
        project: None  # name of the project
        task: None  # optional name of task
        connect_pytorch: False
        model_name: None  # optional name of model
        tags: None  # Should be a list of str
        log_model: False  # log model to clearml server
        log_cfg: False  # log config to clearml server
        log_metrics: False  # log metrics to clearml server

Neptune#

exp_manager:
    ...
    create_checkpoint_callback: True
    create_neptune_logger: false
    neptune_logger_kwargs:
        project: ${project}
        name: ${name}
        prefix: train
        log_model_checkpoints: false # set to True if checkpoints need to be pushed to Neptune
        tags: null # can specify as an array of strings in yaml array format
        description: null
        <Add any other arguments supported by Neptune logger here>

指数移动平均#

NeMo 支持使用指数移动平均 (EMA) 来处理模型参数。这对于提高模型泛化性和稳定性非常有用。要使用 EMA,请通过 YAML 或 ExpManagerConfig 设置以下参数。

exp_manager:
    ...
    # use exponential moving average for model parameters
    ema:
        enabled: True  # False by default
        decay: 0.999  # decay rate
        cpu_offload: False  # If EMA parameters should be offloaded to CPU to save GPU memory
        every_n_steps: 1  # How often to update EMA weights
        validate_original_weights: False  # Whether to use original weights for validation calculation or EMA weights

使用 NeMo 的 Hydra Multi-Run#

在训练神经网络时,通常执行超参数搜索以提高模型在验证数据上的性能。但是,手动准备实验网格并管理所有检查点及其指标可能很繁琐。为了简化这些任务,NeMo 与 Hydra Multi-Run 支持集成,提供了一种统一的方式来直接从配置运行一组实验。

此框架存在一些限制,我们在下面列出

  • 所有实验都假定在单个 GPU 上运行,并且单次运行支持多 GPU(目前不支持模型并行模型)。

  • NeMo Multi-Run 目前仅支持对一组超参数进行网格搜索。对高级超参数搜索策略的支持将在未来添加。

  • **NeMo Multi-Run 需要一个或多个 GPU** 才能运行,并且在没有 GPU 设备的情况下将无法工作。

配置设置#

为了启用 NeMo Multi-Run,我们首先更新 YAML 配置,其中包含一些信息,以让 Hydra 知道我们希望从此配置运行多个实验 -

# Required for Hydra launch of hyperparameter search via multirun
defaults:
  - override hydra/launcher: nemo_launcher

# Hydra arguments necessary for hyperparameter optimization
hydra:
  # Helper arguments to ensure all hyper parameter runs are from the directory that launches the script.
  sweep:
    dir: "."
    subdir: "."

  # Define all the hyper parameters here
  sweeper:
    params:
      # Place all the parameters you wish to search over here (corresponding to the rest of the config)
      # NOTE: Make sure that there are no spaces between the commas that separate the config params !
      model.optim.lr: 0.001,0.0001
      model.encoder.dim: 32,64,96,128
      model.decoder.dropout: 0.0,0.1,0.2

  # Arguments to the process launcher
  launcher:
    num_gpus: -1  # Number of gpus to use. Each run works on a single GPU.
    jobs_per_gpu: 1  # If each GPU has large memory, you can run multiple jobs on the same GPU for faster results (until OOM).

接下来,我们将设置 Experiment Manager 的配置。当我们执行超参数搜索时,每次运行可能需要一些时间才能完成。因此,我们希望避免运行结束的情况(例如,由于机器上的 OOM 或超时),并且我们需要重新执行所有实验。因此,我们设置实验管理器配置,以便每个实验都有一个唯一的“key”,其值对应于单个可恢复的实验。

让我们看看如何通过实验名称设置这样一个唯一的“key”。只需将所有超参数参数附加到实验名称,如下所示 -

exp_manager:
  exp_dir: null  # Can be set by the user.

  # Add a unique name for all hyper parameter arguments to allow continued training.
  # NOTE: It is necessary to add all hyperparameter arguments to the name !
  # This ensures successful restoration of model runs in case HP search crashes.
  name: ${name}-lr-${model.optim.lr}-adim-${model.adapter.dim}-sd-${model.adapter.adapter_strategy.stochastic_depth}

  ...
  checkpoint_callback_params:
    ...
    save_top_k: 1  # Dont save too many .ckpt files during HP search
    always_save_nemo: True # saves the checkpoints as nemo files for fast checking of results later
  ...

  # We highly recommend use of any experiment tracking took to gather all the experiments in one location
  create_wandb_logger: True
  wandb_logger_kwargs:
    project: "<Add some project name here>"

  # HP Search may crash due to various reasons, best to attempt continuation in order to
  # resume from where the last failure case occurred.
  resume_if_exists: true
  resume_ignore_no_checkpoint: true

运行 NeMo Multi-Run 配置#

配置更新后,我们现在可以像运行任何普通的 Hydra 脚本一样运行它,只需一个特殊标志 (-m)。

python script.py --config-path=ABC --config-name=XYZ -m \
    trainer.max_steps=5000 \  # Any additional arg after -m will be passed to all the runs generated from the config !
    ...

技巧和窍门#

本节提供有关使用实验管理器的建议。

为大量实验保留磁盘空间#

某些模型可能具有大量参数,这使得在物理存储驱动器上保存大量检查点的成本非常高昂。例如,如果您使用 Adam 优化器,则每个 PyTorch Lightning “.ckpt” 文件的大小将是仅模型参数大小的三倍。如果您有多次运行,这可能会变得非常昂贵。

在上述配置中,我们显式设置 save_top_k: 1always_save_nemo: True。这会将 “.ckpt” 文件的数量限制为一个,并保存一个 NeMo 文件,该文件仅包含模型参数,不包含优化器状态。可以立即恢复此 NeMo 文件以进行进一步工作。

我们可以通过使用 NeMo 的实用程序函数在训练运行完成后自动删除 “.ckpt” 或 NeMo 文件来进一步节省存储空间。如果您在实验跟踪工具中收集结果,并且可以在搜索完成后简单地重新运行最佳配置,则这已足够。

# Import `clean_exp_ckpt` along with exp_manager
from nemo.utils.exp_manager import clean_exp_ckpt, exp_manager

@hydra_runner(...)
def main(cfg):
    ...

    # Keep track of the experiment directory
    exp_log_dir = exp_manager(trainer, cfg.get("exp_manager", None))

    ... add any training code here as needed ...

    # Add following line to end of the training script
    # Remove PTL ckpt file, and potentially also remove .nemo file to conserve storage space.
    clean_exp_ckpt(exp_log_dir, remove_ckpt=True, remove_nemo=False)

调试 Multi-Run 脚本#

运行 Hydra 脚本时,您可能会遇到导致程序崩溃的配置问题。在 NeMo Multi-Run 中,任何单次运行中的崩溃都不会导致整个程序崩溃。相反,我们将记录错误并继续执行下一个作业。完成所有作业后,我们将按错误发生的顺序引发错误,并使用第一个错误的堆栈跟踪使程序崩溃。

要调试 NeMo Multi-Run,我们建议注释掉 sweep.params 内的整个超参数配置集。相反,使用该配置运行单个实验,这将立即引发错误。

Hydra 无法解析实验名称#

有时我们的超参数包括 PyTorch Lightning trainer 参数,例如步数、epoch 数以及是否使用梯度累积。当我们尝试将这些作为键添加到实验管理器的 name 时,Hydra 可能会抱怨无法解析 trainer.xyz

一个简单的解决方案是在调用 exp_manager() 之前完成 Hydra 配置,如下所示

@hydra_runner(...)
def main(cfg):
    # Make any changes as necessary to the config
    cfg.xyz.abc = uvw

    # Finalize the config
    cfg = OmegaConf.resolve(cfg)

    # Carry on as normal by calling trainer and exp_manager
    trainer = pl.Trainer(**cfg.trainer)
    exp_log_dir = exp_manager(trainer, cfg.get("exp_manager", None))
    ...

ExpManagerConfig#

class nemo.utils.exp_manager.ExpManagerConfig(
explicit_log_dir: str | None = None,
exp_dir: str | None = None,
name: str | None = None,
version: str | None = None,
use_datetime_version: bool | None = True,
resume_if_exists: bool | None = False,
resume_past_end: bool | None = False,
resume_ignore_no_checkpoint: bool | None = False,
resume_from_checkpoint: str | None = None,
create_tensorboard_logger: bool | None = True,
summary_writer_kwargs: ~typing.Dict[~typing.Any,
~typing.Any] | None = None,
create_wandb_logger: bool | None = False,
wandb_logger_kwargs: ~typing.Dict[~typing.Any,
~typing.Any] | None = None,
create_mlflow_logger: bool | None = False,
mlflow_logger_kwargs: ~nemo.utils.loggers.mlflow_logger.MLFlowParams | None = <factory>,
create_dllogger_logger: bool | None = False,
dllogger_logger_kwargs: ~nemo.utils.loggers.dllogger.DLLoggerParams | None = <factory>,
create_clearml_logger: bool | None = False,
clearml_logger_kwargs: ~nemo.utils.loggers.clearml_logger.ClearMLParams | None = <factory>,
create_neptune_logger: bool | None = False,
neptune_logger_kwargs: ~typing.Dict[~typing.Any,
~typing.Any] | None = None,
create_checkpoint_callback: bool | None = True,
checkpoint_callback_params: ~nemo.utils.exp_manager.CallbackParams | None = <factory>,
create_early_stopping_callback: bool | None = False,
early_stopping_callback_params: ~nemo.utils.exp_manager.EarlyStoppingParams | None = <factory>,
create_preemption_callback: bool | None = True,
files_to_copy: ~typing.List[str] | None = None,
log_step_timing: bool | None = True,
log_delta_step_timing: bool | None = False,
step_timing_kwargs: ~nemo.utils.exp_manager.StepTimingParams | None = <factory>,
log_local_rank_0_only: bool | None = False,
log_global_rank_0_only: bool | None = False,
disable_validation_on_resume: bool | None = True,
ema: ~nemo.utils.exp_manager.EMAParams | None = <factory>,
max_time_per_run: str | None = None,
seconds_to_sleep: float = 5,
create_straggler_detection_callback: bool | None = False,
straggler_detection_params: ~nemo.utils.exp_manager.StragglerDetectionParams | None = <factory>,
create_fault_tolerance_callback: bool | None = False,
fault_tolerance: ~nemo.utils.exp_manager.FaultToleranceParams | None = <factory>,
log_tflops_per_sec_per_gpu: bool | None = True,
)

Bases: object

用于验证传递参数的实验管理器配置。