返回介绍

数学基础

统计学习

深度学习

工具

Scala

一、Trainer

发布于 2023-07-17 23:38:23 字数 82051 浏览 0 评论 0 收藏 0

  1. Trainer 类提供了一个 API,用于在 PyTorch 中对大多数标准的 use case 进行 feature-complete training 。在实例化 Trainer 之前,请创建一个 TrainingArguments。该 API 支持在多个GPU/TPU 上进行分布式训练、也支持通过 NVIDIA ApexNative AMP 从而针对 PyTorch 的混合精度训练。

  2. Trainer 类包含 basic training loop 。为了注入自定义行为,你可以对 Trainer进行子类化,并重写以下方法:

    
    get_train_dataloader; get_eval_dataloader; get_test_dataloader; log; create_optimizer_and_scheduler;
    create_optimizer; create_scheduler; compute_loss; training_step; prediction_step; evaluate; predict

    下面是一个对 Trainer 子类化的例子,其中使用一个带权重的损失函数:

    ​x
    from torch import nn
    from transformers import Trainer
    
    
    class CustomTrainer(Trainer):
        def compute_loss(self, model, inputs, return_outputs=False):
            labels = inputs.get("labels")
            # forward pass
            outputs = model(**inputs)
            logits = outputs.get("logits")
            # compute custom loss (suppose one has 3 labels with different weights)
            loss_fct = nn.CrossEntropyLoss(weight=torch.tensor([1.0, 2.0, 3.0]))
            loss = loss_fct(logits.view(-1, self.model.config.num_labels), labels.view(-1))
            return (loss, outputs) if return_outputs else loss

    对于 PyTorch,另一种定制化 training loop 行为的方法是采用 callbacks,它可以检查 training loop state (用于进度报告、向 TensorBoard 写日志)并作出决定(如 early stopping )。

  3. Trainer 类是针对 Transformers 模型进行了优化。如果你在其他模型上使用 Trainer,可能会有意想不到的行为。当你在其他模型上使用时,要确保:

    • 你的模型总是返回元组、或者 ModelOutput 的子类。
    • 如果提供了一个 labels 参数,那么你的模型可以计算损失,并且该损失作为元组的第一个元素被模型返回(如果你的模型返回元组)。
    • 你的模型可以接受多个 label 参数(使用 TrainingArguments 中的 label_names 来向 Trainer 指定它们的名称),但是它们全都不应该被命名为 "label"

1.1 API

a. TrainingArguments

  1. class transformers.TrainingArguments:用于 Trainer 的参数(和 training loop 相关)。

    通过使用 class transformers.HfArgumentParser,我们可以将 TrainingArguments 实例转换为 argparse 参数(可以在命令行中指定)。

    
    
    xxxxxxxxxx
    class transformers.TrainingArguments( output_dir: str, overwrite_output_dir: bool = False, do_train: bool = False, do_eval: bool = False, do_predict: bool = False, evaluation_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'no', prediction_loss_only: bool = False, per_device_train_batch_size: int = 8, per_device_eval_batch_size: int = 8, per_gpu_train_batch_size: typing.Optional[int] = None, per_gpu_eval_batch_size: typing.Optional[int] = None, gradient_accumulation_steps: int = 1, eval_accumulation_steps: typing.Optional[int] = None, eval_delay: typing.Optional[float] = 0, learning_rate: float = 5e-05, weight_decay: float = 0.0, adam_beta1: float = 0.9, adam_beta2: float = 0.999, adam_epsilon: float = 1e-08, max_grad_norm: float = 1.0, num_train_epochs: float = 3.0, max_steps: int = -1, lr_scheduler_type: typing.Union[transformers.trainer_utils.SchedulerType, str] = 'linear', warmup_ratio: float = 0.0, warmup_steps: int = 0, log_level: typing.Optional[str] = 'passive', log_level_replica: typing.Optional[str] = 'passive', log_on_each_node: bool = True, logging_dir: typing.Optional[str] = None, logging_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'steps', logging_first_step: bool = False, logging_steps: int = 500, logging_nan_inf_filter: bool = True, save_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'steps', save_steps: int = 500, save_total_limit: typing.Optional[int] = None, save_on_each_node: bool = False, no_cuda: bool = False, use_mps_device: bool = False, seed: int = 42, data_seed: typing.Optional[int] = None, jit_mode_eval: bool = False, use_ipex: bool = False, bf16: bool = False, fp16: bool = False, fp16_opt_level: str = 'O1', half_precision_backend: str = 'auto', bf16_full_eval: bool = False, fp16_full_eval: bool = False, tf32: typing.Optional[bool] = None, local_rank: int = -1, xpu_backend: typing.Optional[str] = None, tpu_num_cores: typing.Optional[int] = None, tpu_metrics_debug: bool = False, debug: str = '', dataloader_drop_last: bool = False, eval_steps: typing.Optional[int] = None, dataloader_num_workers: int = 0, past_index: int = -1, run_name: typing.Optional[str] = None, disable_tqdm: typing.Optional[bool] = None, remove_unused_columns: typing.Optional[bool] = True, label_names: typing.Optional[typing.List[str]] = None, load_best_model_at_end: typing.Optional[bool] = False, metric_for_best_model: typing.Optional[str] = None, greater_is_better: typing.Optional[bool] = None, ignore_data_skip: bool = False, sharded_ddp: str = '', fsdp: str = '', fsdp_min_num_params: int = 0, fsdp_transformer_layer_cls_to_wrap: typing.Optional[str] = None, deepspeed: typing.Optional[str] = None, label_smoothing_factor: float = 0.0, optim: typing.Union[transformers.training_args.OptimizerNames, str] = 'adamw_hf', optim_args: typing.Optional[str] = None, adafactor: bool = False, group_by_length: bool = False, length_column_name: typing.Optional[str] = 'length', report_to: typing.Optional[typing.List[str]] = None, ddp_find_unused_parameters: typing.Optional[bool] = None, ddp_bucket_cap_mb: typing.Optional[int] = None, dataloader_pin_memory: bool = True, skip_memory_metrics: bool = True, use_legacy_prediction_loop: bool = False, push_to_hub: bool = False, resume_from_checkpoint: typing.Optional[str] = None, hub_model_id: typing.Optional[str] = None, hub_strategy: typing.Union[transformers.trainer_utils.HubStrategy, str] = 'every_save', hub_token: typing.Optional[str] = None, hub_private_repo: bool = False, gradient_checkpointing: bool = False, include_inputs_for_metrics: bool = False, fp16_backend: str = 'auto', push_to_hub_model_id: typing.Optional[str] = None, push_to_hub_organization: typing.Optional[str] = None, push_to_hub_token: typing.Optional[str] = None, mp_parameters: str = '', auto_find_batch_size: bool = False, full_determinism: bool = False, torchdynamo: typing.Optional[str] = None, ray_scope: typing.Optional[str] = 'last', ddp_timeout: typing.Optional[int] = 1800 )

    参数:

    • output_dir:一个字符串,指定 model predictionmodel checkpoint 输出的目录。

    • overwrite_output_dir:一个布尔值,如果为 True 则覆盖 output_dir 的内容。如果 output_dir 指向一个 checkpoint 目录,则使用该参数来继续训练。

    • do_train:一个布尔值,指定是否执行训练。该参数不是由 Trainer 直接使用,而是由你的 training/evaluation 脚本来使用。

    • do_eval:一个布尔值,指定是否在验证集上执行评估。如果 evaluation_strategy 不是 "no",那么该参数将被设置为 True 。该参数不是由 Trainer 直接使用,而是由你的 training/evaluation 脚本来使用。

    • do_predict:一个布尔值,指定是否在测试集上执行预测。如果 evaluation_strategy 不是 "no",那么该参数将被设置为 True 。该参数不是由 Trainer 直接使用,而是由你的 training/evaluation 脚本来使用。

    • evaluation_strategy:一个字符串、或 IntervalStrategy ,指定训练过程中要采用的评估策略。可以为:

      • "no":训练期间不进行评估。
      • "steps":每隔 eval_steps 训练步进行评估(并且记录日志)。
      • "epoch":在每个 epoch 结束时进行评估。
    • prediction_loss_only:一个布尔值,指定当执行评估和生成预测时是否仅返回 loss

    • per_device_train_batch_size:一个整数,指定用于训练的每个 GPU/TPU core/CPUbatch size

    • per_device_eval_batch_size:一个整数,指定用于评估的每个 GPU/TPU core/CPUbatch size

    • gradient_accumulation_steps:一个整数,指定在进行反向传播(即,梯度更新)之前,用于累积梯度的 updates steps 的数量。当使用 gradient accumulation,一个 step 指的是执行一次反向传播。因此,logging, evaluation, save 将在每隔 gradient_accumulation_steps * xxx_step 的训练样本之后进行。

      它相当于扩大了 batch size

    • eval_accumulation_steps:一个整数,指定在将结果移动到 CPU 之前,对输出张量进行累积的 predictions steps 的数量。如果未设置,则整个预测结果在移动到 CPU 之前会在 GPU/TPU 上累积(速度更快,但是需要更多的显存)。

    • eval_delay:一个浮点数,指定在执行第一次评估之前需要等待多少个 epochssteps(根据 evaluation_strategy 的不同来选择 epochssteps)。

    • learning_rate:一个浮点数,指定 AdamW 优化器的初始学习率。

    • weight_decay:一个浮点数,指定 AdamW 优化器中适用于所有层的权重衰减,除了所有的 bias、以及 LayerNorm weights

    • adam_beta1:一个浮点数,指定 AdamW 优化器的 beta1 超参数。

    • adam_beta2:一个浮点数,指定 AdamW 优化器的 beta2 超参数。

    • adam_epsilon:一个浮点数,指定 AdamW 优化器的 epsilon 超参数。

    • max_grad_norm:一个浮点数,指定最大梯度范数(用于梯度裁剪)。

    • num_train_epochs:一个浮点数,指定训练的 epoch 数量。如果不是整数,那么在停止训练之前执行最后一个 epoch 的小数部分的百分比。

    • max_steps:一个整数,如果设置为正数,则指定训练的 step 总数,它会覆盖 num_train_epochs 。如果使用有限的可迭代数据集,那么当所有数据耗尽时,可能会在 max_steps 之前就结束训练。

    • lr_scheduler_type:一个字符串或 SchedulerType,指定学习率调度器的类型。

    • warmup_ratio:一个浮点数,指定从 0 到峰值学习率(通常就是 learning_rate 指定的)的线性预热所使用的训练步占 total training steps 的比例。

    • warmup_steps:一个浮点数,指定从 0 到峰值学习率(通常就是 learning_rate 指定的)的线性预热所使用的训练步的数量。它覆盖 warmup_ratio

    • log_level:一个字符串,指定主进程中使用的 logger log level 。可以为:'debug', 'info', 'warning', 'error', 'critical', 'passive' 。其中 'passive' 表示不设置任何级别而是让 application 来设置。

    • log_level_replica:一个字符串,指定在副本进程中使用的 logger log level 。参考 log_level

    • log_on_each_node:一个布尔值,指定在多节点分布式训练中,是否在每个节点使用 log_levellog、或者仅在主节点上 log

    • logging_dir:一个字符串,指定 TensorBoard log 目录,默认为 output_dir/runs/CURRENT_DATETIME_HOSTNAME

    • logging_strategy:一个字符串或 IntervalStrategy,指定训练期间的 logging 策略。可以为:

      • "no":不做任何 logging
      • "epoch":在每个 epoch 结束时 logging
      • "steps":每隔 logging_stepslogging
    • logging_first_step:一个布尔值,指定是否 logevaluate 第一个 global_step

    • logging_steps:一个整数,指定当 logging_strategy="steps" 时每两次 logging 之间的 update steps 数量。

    • logging_nan_inf_filter:一个布尔值,指定是否要过滤 naninf 的损失从而用于 logging 。如果为 True,那么每个 stepnaninf 的损失都会被过滤掉从而仅选取当前 logging window 的平均损失。

      注意,该参数仅影响 logging,不影响梯度的计算或模型的预测。

    • save_strategy:一个字符串或 IntervalStrategy,指定训练时采用的 checkpoint save 策略。可以为:

      • "no":不做保存。
      • "epoch":在每个 epoch 结束时保存。
      • "steps":每隔 save_steps 就保存。
    • save_steps:一个整数,指定当 save_strategy="steps" 时每两次 checkpoint save 之间的 update steps 数量。

    • save_total_limit:一个整数,如果传入一个值,那么指定 checkpoint 总的保存数量。这可能会删除 output_dir 中的 older checkpoints

    • save_on_each_node:一个布尔值,指定当进行多节点分布式训练时,是否在每个节点上保存模型和 checkpoint、还是仅在主节点上保存。

      当不同的节点使用相同的 storage 时,这个能力应该禁用,因为每个节点的文件都将被保存为相同的名称。

    • no_cuda:一个布尔值,指定是否禁用 CUDA

    • seed:一个整数,指定随机数种子,它在训练开始时设置。

      为了确保不同运行的可重复性,如果模型有一些随机初始化的参数,请使用 Trainer.model_init() 函数将模型其实例化。

    • data_seed:一个整数,指定用于 data samplers 的随机数种子。如果未设置,数据采样的随机数生成器将使用与 seed 相同的种子。这可以用来确保数据采样的可重复性,与 model seed 无关。

    • jit_mode_eval:一个布尔值,指定是否使用 PyTorch jit trace 进行推断。

    • use_ipex:一个布尔值,指定当 Intel extension for PyTorch: IPEX 可用时是否使用 IPEX。如果启用,则要求安装 IPEX

    • bf16:一个布尔值,指定是否使用 bf1616 位(混合)精度训练,而不是 fp3232 位训练。需要 Ampere 或更高的 NVIDIA 架构、或使用 CPUno_cuda)。这是一个实验性的API,它可能会发生变化。

    • fp16:一个布尔值,指定是否使用 fp1616位(混合)精度训练而不是 fp3232 位训练。

    • fp16_opt_level:一个字符串,指定 Apex AMP 优化等级('O0', 'O1', 'O2', 'O3)从而用于 fp16 训练。

    • fp16_backend:目前已被废弃,建议使用 half_precision_backend

    • half_precision_backend:一个字符串,指定 用于混合精度训练的后端。必须是 "auto", "cuda_amp", "apex", "cpu_amp"中的一个。"auto" 将根据检测到的 PyTorch 版本使用 CPU/CUDA AMPAPEX ,而其他选择将强制使用所对应的后端。

    • bf16_full_eval:一个布尔值,指定是否使用 full bfloat16 评估,而不是使用 fp3232 位进行评估。这将会更快并节省内存,但会损害评估指标。这是一个实验性的 API,它可能会改变。

    • f16_full_eval:一个布尔值,指定是否使用 full float16 评估,而不是使用 fp3232 位进行评估。这将会更快并节省内存,但会损害评估指标。

    • tf32:一个布尔值,指定是否启用 TF32 模式,在 Ampere 和较新的GPU架构中可用。默认值取决于 PyTorchtorch.backends.cuda.matmul.allow_tf32 的默认版本。这是一个实验性的 API ,它可能会改变。

    • local_rank:一个整数,指定分布式训练中进程的 rank

    • xpu_backend:一个字符串,指定 xpu 分布式训练要使用的后端。必须是 "mpi", "ccl", "gloo" 中的一个。

    • dataloader_drop_last:一个布尔值,指定是否放弃最后一个 incomplete batch (如果数据集的长度不能被 batch size 所整除)。

    • eval_steps:一个整数,指定如果 evaluation_strategy="steps" 则两次评估之间的 update steps 的数量。如果没有设置,将默认为与 logging_steps 相同。

    • dataloader_num_workers:一个整数,指定用于加载数据集的子进程的数量(仅限 PyTorch )。0表示数据将在主进程中加载。

    • past_index:一个整数,有些模型如 TransformerXLXLNet 可以利用 past hidden states 进行预测。如果这个参数被设置为一个正整数,训练器将使用相应的输出(通常是 index 2 )作为 past state ,并在下一个 training step 中根据关键字参数ems 将其馈入模型。

    • run_name:一个字符串,指定一个当前 run 的描述文本,通常用于 wandbmlflow 日志。

    • disable_tqdm:一个布尔值,指定是否禁用 tqdm 进度条和 table of metrics

      如果 logging level 被设置为 warn 或更低(默认),将默认为True,否则为False

    • remove_unused_columns:一个布尔值,指定是否自动删除未被使用的列(指的是在模型的前向传播中未被使用)。

      注意,这个行为尚未在 TFTrainer 中实现。

    • label_names:一个关于字符串的列表,指定 inputs 的字典中对应于 label 的键的列表。

      默认值是 ["labels"],但是如果是 XxxForQuestionAnswering 模型则默认值是 ["start_positions", "end_positions"]

    • load_best_model_at_end:一个布尔值,指定是否在训练结束时加载训练中发现的最佳模型。

      如果是 True ,那么 save_strategy 需要和 evaluation_strategy 相同;并且如果 save_strategyevaluation_strategy 都是 "step",那么 save_steps 必须是 eval_steps 的整数倍。

    • metric_for_best_model:一个字符串,指定评估最佳模型的指标,与 load_best_model_at_end 配合使用。

      它必须是模型评估所返回的指标的名字。如果 load_best_model_at_end=True 且该参数未指定,则默认为 "loss"

      注意,greater_is_better 默认为 True;如果评估指标越低越好,则需要将 greater_is_better 设置为 False

    • greater_is_better:一个布尔值,指定更好的模型是否具有更大的指标值,与 load_best_model_at_endmetric_for_best_model 一起使用。

      如果 metric_for_best_model 被设置为既不是 "loss" 也不是 "eval_loss",那么默认为 True ;如果 metric_for_best_model 没有被设置、或者是 "loss"、或者是 "eval_loss",那么默认为 False

    • ignore_data_skip:一个布尔值,指定在恢复训练时,是否跳过 epochsbatches 从而获得与 previous training 相同阶段的 data loading 。如果设置为 True ,训练将更快开始(因为 skipping step 可能需要很长时间),但不会产生与被中断的训练相同的结果。

    • sharded_ddp:一个布尔值或字符串或关于 ShardedDDPOption 的列表,指定使用来自 FairScaleSharded DDP 训练(仅在分布式训练中)。这是一个实验性的功能。可选的参数为:

      • "simple" :使用由 fairscale 发布的 sharded DDP 的第一个实例(ShardedDDP),类似于 ZeRO-2
      • "zero_dp_2":以 Zero-2 (采用 reshard_after_forward=False )使用由 fairscale 发布的 sharded DDP 的第二个实例(FullyShardedDDP)。
      • "zero_dp_3":以 Zero-3 (采用 reshard_after_forward=True )使用由 fairscale 发布的 sharded DDP 的第二个实例(FullyShardedDDP)。
      • "offload":添加 ZeRO-offload (只与 "zero_dp_2""zero_dp_3" 兼容)。

      如果传递的是一个字符串,它将在空格处被拆分。如果传递的是一个布尔值,如果是 True 则代表 ["simple"],如果是 False 则代表 []

    • fsdp:一个布尔值或字符串或关于FSDPOption 的列表,指定使用 PyTorch Distributed Parallel Training 训练(仅在分布式训练中)。可选的参数为:

      • "full_shard":对 parameters, gradients, optimizer states 进行分片。
      • "shard_grad_op":对 optimizer states, gradients 进行分片。
      • "offload":将 parameters, gradients 卸载到 CPU (仅与 "full_shard", "shard_grad_op" 兼容)。
      • "auto_wrap":使用 default_auto_wrap_policy 从而利用 FSDP 来自动递归地 wrap layers
    • fsdp_min_num_params:一个整数,指定 FSDP 的默认的最少的 parameters 数量从而用于 Default Auto Wrapping 。仅当 fsdp 参数有效时 fsdp_min_num_params 才有意义。

    • deepspeed:一个字符串或字典,指定使用 Deepspeed

      这是一个实验性的功能,其 API 可能会在未来演变。该值是 DeepSpeed json 配置文件的位置(例如 ds_config.json )或者是一个代表已加载 json 文件的字典。

    • label_smoothing_factor:一个浮点数,指定 label smoothing 因子。零代表没有标签平滑。

      否则, label 0 变成:label_smoothing_factor/num_labelslabel 1 变成 1 - label_smoothing_factor + label_smoothing_factor/num_labels

    • debug:一个字符串或者关于 DebugOption 的列表,指定启用一个或多个 debug 特性。这是一个实验性的功能。可选的参数有:

      • "underflow_overflow":检测模型的 input/outputs 中的溢出,并报告导致该事件的最后一帧。
      • "tpu_metrics_debug":打印 TPU 的调试指标。

      如果是字符串,那么用空格拆分。

    • optim:一个字符串或者 training_args.OptimizerNames,指定使用的优化器。可以为:adamw_hf, adamw_torch, adamw_apex_fused, adamw_anyprecision, adafactor

    • optim_args:一个字符串,指定提供给 AnyPrecisionAdamW 的可选参数。

    • adafactor:被废弃,推荐使用 optim="adafactor" 来代替。

    • group_by_length:一个布尔值,指定是否将训练数据集中长度大致相同的样本分组(从而尽量减少填充的使用,使之更有效)。只有在应用动态填充时才有用。

    • length_column_name:一个字符串,指定预计算的长度的列名。如果该列存在,group_by_length 将使用这些值,而不是在训练启动时计算它们。除非 group_by_lengt = True 并且数据集是 Dataset 的一个实例,否则会被忽略。

    • report_to:一个字符串或关于字符串的列表,指定要报告结果和日志的集成商的列表。支持的集成商有:"azure_ml", "comet_ml", "mlflow", "neptune", "tensorboard","clearml", "wandb""all" 表示报告所有的集成商;"none" 表示都不报告。

    • ddp_find_unused_parameters:一个布尔值,指定当使用分布式训练时,传递给 DistributedDataParallelfind_unused_parameters 的值。

      如果使用 gradient checkpointing,那么默认值为 False;否则默认值为 True

    • ddp_bucket_cap_mb:一个整数,指定当使用分布式训练时,传递给 DistributedDataParallelbucket_cap_mb 的值。

    • dataloader_pin_memory:一个布尔值,指定在 data loaders 中是否要 pin memory

    • skip_memory_metrics:一个布尔值,指定是否跳过向 metrics 添加 memory profiler 报告。默认情况下跳过(即,True),因为这会减慢训练和评估的速度。

    • push_to_hub:一个布尔值,指定每次保存模型时是否将模型推送到 Hub

      如果为 Trueoutput_dir 是一个 git 目录(这个 git 目录与 repo 同步),目录内容将在每次触发保存时被推送(取决于你的 save_strategy )。调用 save_model()也会触发一次推送。 如果 output_dir 存在,则该目录必须是 repo 的一个 local clone ,这个 repo 就是 Trainer 将被推送到的地方。

    • resume_from_checkpoint:一个字符串,指定有效 checkpoint 的文件夹的路径。

      这个参数不直接被 Trainer 使用,而是由 training/evaluation 脚本使用。

    • hub_model_id:一个字符串,指定 repo 的名字从而与 local output_dir 保持同步。默认为 output_dir 的名称。

    • hub_strategy:一个字符串或 HubStrategy,指定推送到 Hub 的范围和时间。可以为:

      • "end":在调用 save_model() 方法时,推送模型、模型配置、tokenizer (如果传递给 Trainer )和模型卡的草稿。
      • "every_save":每次有模型保存时,推送模型、模型配置、tokenizer (如果传递给 Trainer )和模型卡的草稿。推送是异步的,从而避免阻碍训练,而且如果保存非常频繁,只有在前一次完成后才会尝试新的推送。最后一次推送是在训练结束后用最后的模型进行的。
      • "checkpoint":和 "every_save " 一样,但最 latest checkpoint 也会被推送到一个名为 last-checkpoint 的子文件夹中,这样你就可以用 trainer.train(resume_from_checkpoint="last-checkpoint") 轻松恢复训练。
      • "all_checkpoints":和 "checkpoint " 一样,但是所有的 checkpoint 都会被推送(所以你会在 final repo 的每个文件夹中得到一个 checkpoint 文件夹)。
    • hub_token:一个字符串,指定用来推送模型到 Hubtoken 。将默认为通过 huggingface-cli 登录获得的缓存文件夹中的token

    • hub_private_repo:一个布尔值,指定是否将 Hub repo 设为私有。

    • gradient_checkpointing:一个布尔值,指定是否使用 gradient checkpointing 来节省内存。如果为 True,则会降低反向传播的速度。

    • include_inputs_for_metrics:一个布尔值,指定 inputs 是否会被传递给 compute_metrics 函数。这适用于需要 inputspredictionsreferences 的指标的计算。

    • auto_find_batch_size:一个布尔值,指定是否通过指数衰减自动寻找适合内存的 batch size ,以避免 CUDA Out-of-Memory 的错误。需要安装 acceleratepip install accelerate )。

    • full_determinism:一个布尔值,如果为 True 则调用 enable_full_determinism() 而不是 set_seed() ,从而确保分布式训练的结果可重复。

    • torchdynamo:一个字符串,用于 TorchDynamo 的后端编译器。可以为: "eager", "aot_eager", "inductor", "nvfuser", "aot_nvfuser", "aot_cudagraphs", "ofi", "fx2trt", "onnxrt", "ipex"

    • ray_scope:一个字符串,指定使用 Ray 进行超参数搜索时使用的范围。默认情况下,将使用 "last" 。然后,Ray 将使用所有试验的最后一个 checkpoint ,比较这些 checkpoint 并选择最佳 checkpoint 。然而,也有其他选项。更多选项见 Ray 文档。

    • ddp_timeout:一个整数,指定 torch.distributed.init_process_group 调用的超时时间。

    • use_mps_device:一个布尔值,指定是否使用基于 Apple Siliconmps 设备。

    方法:

    • get_process_log_level():返回 log level ,具体结果取决于是否是 node 0 的主进程、node non-0 的主进程、以及非主进程。

      • 对于主进程, log level 默认为 logging.INFO ,除非被 log_level 参数覆盖。
      • 对于非主进程,除非被 log_level_replica 参数覆盖,否则 log level 默认为 logging.warning

      主进程和非主进程的 setting 是根据 should_log 的返回值进行选择的。

    • get_warmup_steps( num_training_steps: int):返回用于线性预热的 step 数量。

    • main_process_first(local = True, desc = 'work' ):一个用于 Torch 分布式环境的上下文管理器,它需要在主进程上做一些事情,同时 block 副本,当它完成后再 release 副本。

      其中一个用途是数据集的 map 特性:为了提高效率,应该在主进程上运行一次,完成后保存一个 cached 版本数据集的结果,然后由副本自动加载。

      参数:

      • local:一个布尔值,如果为 True 则表示 first 是每个节点的 rakn 0 进程;如果为 False 则表示 firstnode rank 0rank 0 进程。

        在共享文件系统的多节点环境中,你很可能想使用 local=False ,这样只有第一个节点的主进程会进行处理。然而,如果文件系统不是共享的,那么每个节点的主进程将需要做处理,这是默认行为(即,默认为 True)。

      • desc:一个字符串,指定 work 描述文本从而用于调试日志。

    • to_dict():序列化该实例到一个字典,同时用枚举的值来代替 Enum 对象。

    • to_json_string():序列化该实例到一个 json 字符串。

    • to_sanitized_dict():采用 TensorBoardhparams 来序列化该实例。

  2. class transformers.Seq2SeqTrainingArguments

    
    
    xxxxxxxxxx
    class transformers.Seq2SeqTrainingArguments( output_dir: str, overwrite_output_dir: bool = False, do_train: bool = False, do_eval: bool = False, do_predict: bool = False, evaluation_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'no', prediction_loss_only: bool = False, per_device_train_batch_size: int = 8, per_device_eval_batch_size: int = 8, per_gpu_train_batch_size: typing.Optional[int] = None, per_gpu_eval_batch_size: typing.Optional[int] = None, gradient_accumulation_steps: int = 1, eval_accumulation_steps: typing.Optional[int] = None, eval_delay: typing.Optional[float] = 0, learning_rate: float = 5e-05, weight_decay: float = 0.0, adam_beta1: float = 0.9, adam_beta2: float = 0.999, adam_epsilon: float = 1e-08, max_grad_norm: float = 1.0, num_train_epochs: float = 3.0, max_steps: int = -1, lr_scheduler_type: typing.Union[transformers.trainer_utils.SchedulerType, str] = 'linear', warmup_ratio: float = 0.0, warmup_steps: int = 0, log_level: typing.Optional[str] = 'passive', log_level_replica: typing.Optional[str] = 'passive', log_on_each_node: bool = True, logging_dir: typing.Optional[str] = None, logging_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'steps', logging_first_step: bool = False, logging_steps: int = 500, logging_nan_inf_filter: bool = True, save_strategy: typing.Union[transformers.trainer_utils.IntervalStrategy, str] = 'steps', save_steps: int = 500, save_total_limit: typing.Optional[int] = None, save_on_each_node: bool = False, no_cuda: bool = False, use_mps_device: bool = False, seed: int = 42, data_seed: typing.Optional[int] = None, jit_mode_eval: bool = False, use_ipex: bool = False, bf16: bool = False, fp16: bool = False, fp16_opt_level: str = 'O1', half_precision_backend: str = 'auto', bf16_full_eval: bool = False, fp16_full_eval: bool = False, tf32: typing.Optional[bool] = None, local_rank: int = -1xpu_backend: typing.Optional[str] = None, tpu_num_cores: typing.Optional[int] = None, tpu_metrics_debug: bool = False, debug: str = '', dataloader_drop_last: bool = False, eval_steps: typing.Optional[int] = None, dataloader_num_workers: int = 0, past_index: int = -1, run_name: typing.Optional[str] = None, disable_tqdm: typing.Optional[bool] = None, remove_unused_columns: typing.Optional[bool] = True, label_names: typing.Optional[typing.List[str]] = None, load_best_model_at_end: typing.Optional[bool] = False, metric_for_best_model: typing.Optional[str] = None, greater_is_better: typing.Optional[bool] = None, ignore_data_skip: bool = False, sharded_ddp: str = '', fsdp: str = '', fsdp_min_num_params: int = 0, fsdp_transformer_layer_cls_to_wrap: typing.Optional[str] = None, deepspeed: typing.Optional[str] = None, label_smoothing_factor: float = 0.0, optim: typing.Union[transformers.training_args.OptimizerNames, str] = 'adamw_hf', optim_args: typing.Optional[str] = None, adafactor: bool = False, group_by_length: bool = False, length_column_name: typing.Optional[str] = 'length', report_to: typing.Optional[typing.List[str]] = None, ddp_find_unused_parameters: typing.Optional[bool] = None, ddp_bucket_cap_mb: typing.Optional[int] = None, dataloader_pin_memory: bool = True, skip_memory_metrics: bool = True, use_legacy_prediction_loop: bool = False, push_to_hub: bool = False, resume_from_checkpoint: typing.Optional[str] = None, hub_model_id: typing.Optional[str] = None, hub_strategy: typing.Union[transformers.trainer_utils.HubStrategy, str] = 'every_save', hub_token: typing.Optional[str] = None, hub_private_repo: bool = False, gradient_checkpointing: bool = False, include_inputs_for_metrics: bool = False, fp16_backend: str = 'auto', push_to_hub_model_id: typing.Optional[str] = None, push_to_hub_organization: typing.Optional[str] = None, push_to_hub_token: typing.Optional[str] = None, mp_parameters: str = '', auto_find_batch_size: bool = False, full_determinism: bool = False, torchdynamo: typing.Optional[str] = None, ray_scope: typing.Optional[str] = 'last', ddp_timeout: typing.Optional[int] = 1800, sortish_sampler: bool = False, predict_with_generate: bool = False, generation_max_length: typing.Optional[int] = None, generation_num_beams: typing.Optional[int] = None )

    参数:

    • sortish_sampler:一个布尔值,指定是否使用 sortish 采样器。目前只有在底层数据集是 Seq2SeqDataset 的情况下才有可能,但在不久的将来会变得普遍可用。 它根据长度对输入进行排序从而最小化 padding 的大小,其中对训练集有一点随机性。
    • predict_with_generate:一个布尔值,指定是否使用 generate 来计算生成指标(ROUGE, BLEU )。
    • generation_max_length:一个整数,指定当 predict_with_generate=True 时,在每个 evaluation loop 中使用的最大长度。默认为模型配置的 max_length 值。
    • generation_num_beams:一个布尔值,指定当 predict_with_generate=True 时,在每个 evaluation loop 使用的 beams 数量。将默认为模型配置中的 num_beams 值。

b. Trainer

  1. class transformers.TrainerTrainer 是针对 PyTorch 的一个简单的、但是特征完备 feature-completetrainingeval loop ,并且针对 Transformers 进行了优化。

    
    
    xxxxxxxxxx
    class transformers.Trainer( model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.modules.module.Module] = None, args: TrainingArguments = None, data_collator: typing.Optional[DataCollator] = None, train_dataset: typing.Optional[torch.utils.data.dataset.Dataset] = None, eval_dataset: typing.Optional[torch.utils.data.dataset.Dataset] = None, tokenizer: typing.Optional[transformers.tokenization_utils_base.PreTrainedTokenizerBase] = None, model_init: typing.Callable[[], transformers.modeling_utils.PreTrainedModel] = None, compute_metrics: typing.Union[typing.Callable[[transformers.trainer_utils.EvalPrediction], typing.Dict], NoneType] = None, callbacks: typing.Optional[typing.List[transformers.trainer_callback.TrainerCallback]] = None, optimizers: typing.Tuple[torch.optim.optimizer.Optimizer, torch.optim.lr_scheduler.LambdaLR] = (None, None), preprocess_logits_for_metrics: typing.Callable[[torch.Tensor, torch.Tensor], torch.Tensor] = None )

    参数:

    • model:一个 PreTrainedModeltorch.nn.Module 对象,指定用于训练、评估、或预测的模型。如果未提供,则必须传入 model_init 参数。

      Trainer 被优化为与 PreTrainedModel 一起工作。但是你仍然可以使用自定义的 torch.nn.Module 的模型,只要模型的工作方式与 Transformers 模型相同。

    • args:一个 TrainingArguments,指定训练时的参数。如果未提供,则默认为 TrainingArgumentsbasic instance,其中 output_dir 设置为当前目录下叫做 tmp_trainer 的目录。

    • data_collator:一个 DataCollator,指定用于从 train_dataseteval_dataset 的元素列表中构建一个 batch 的函数。如果没有提供 tokenizer ,则默认的 DataCollatordefault_data_collator() ,否则默认的 DataCollatorDataCollatorWithPadding 的一个实例。

    • train_dataset:一个 torch.utils.data.Datasettorch.utils.data.IterableDataset,指定训练集。如果它是 HuggingFaceDataset,那么 model.forward() 方法不需要的列则会被自动移除。

      注意,如果它是一个带有一些随机性的 torch.utils.data.IterableDataset ,并且你是以分布式方式进行训练的,你的 iterable dataset 要么使用一个内部的 attribute generator ,该generator 是一个 torch.Generator 用于随机化,且在所有进程上必须是相同的(并且 Trainer 将在每个 epoch 手动设置该 generator 的种子);要么有一个 set_epoch() 方法,在该方法内部设置所用随机数生成器的种子。

    • eval_dataset:一个 torch.utils.data.Datasettorch.utils.data.IterableDataset,指定验证集。如果它是 HuggingFaceDataset,那么 model.forward() 方法不需要的列则会被自动移除。

      如果它是一个字典(键为数据集名称、值为数据集),它将在每个数据集上进行评估,并将数据集名称添加到指标名称之前作为前缀。

    • tokenizer:一个 PreTrainedTokenizerBase,指定用于预处理数据的 tokenizer 。如果提供了该参数,将用于在 batching input 时自动将 input 填充到最大长度,并且它将与模型一起保存,以便更容易重新运行中断的训练、或复用微调后的模型。

    • model_init:一个可调用对象,它实例化将要被使用的模型。如果提供的话,对 train() 的每次调用将从这个函数给出的模型的一个新实例开始。

      该函数可以有零个参数,也可以有一个包含 optuna/Ray Tune/SigOpttrial object 的单个参数,以便能够根据超参数(如层数、层的维度、dropout rate 等)选择不同的架构。该函数返回一个 PreTrainedModel 对象。

    • compute_metrics:一个可调用对象,指定评估时用来计算指标的函数。

      compute_metrics 必须接受一个 EvalPrediction ,并返回一个关于各种指标的字典。

    • callbacks:一个关于 TrainerCallback 的列表,指定用于 training loop 的自定义 callback 列表。Trainer 将把这些添加到 default callbacks 的列表中。

      如果你想删除其中一个 default callback ,请使用 Trainer.remove_callback() 方法。

    • optimizers:一个元组 Tuple[torch.optimizer, torch.optim.lr_scheduler.LambdaLR] ,指定要使用的优化器和调度器。

      默认为作用在你的模型上的 AdamW 实例、以及由 args 控制的 get_linear_schedule_with_warmup() 给出的调度器。

    • preprocess_logits_for_metrics:一个可调用对象,它在每个评估 stepcaching logits 之前对 logits 进行预处理。

      preprocess_logits_for_metrics 必须接受两个张量(即, logitslabels ),并在按需要处理后返回 logitspreprocess_logits_for_metrics 所做的修改将反映在 compute_metrics 所收到的预测结果中。 注意,如果数据集没有 labels ,则 labels 参数(元组的第二个位置)将是 None

    重要的属性:

    • model:始终指向core model 。如果使用 transformers 模型,它将是一个 PreTrainedModel 的子类。

    • model_wrapped:始终指向最外层的模型,因为有的时候有一个或多个其他模块来 wrap 原始模型。 model_wrapped 就是被用来前向传播的模型。例如,在 DeepSpeed 下,内层模型被包裹在 DeepSpeed 中、然后又被包裹在torch.nn.DistributedDataParallel 中。

      如果内层模型还没有被 wrap ,那么 self.model_wrappedself.model 是一样的。

    • is_model_parallel:一个模型是否被切换到模型并行 model parallel 模式(与数据并行 data parallelism 不同,这意味着一些 model layers 被分割到不同的GPU上)。

    • place_model_on_device: 是否自动将模型放置在设备上。如果使用模型并行或 deepspeed 则默认为 False ,或者默认的TrainingArguments.place_model_on_device 被重写为返回 False 则这里的默认值也是 False

    • is_in_train:模型当前是否正在运行训练(例如,当在训练中调用 evaluation 时)。

    方法:

    • add_callback(callback: transformer.TrainerCallback): 添加一个 callback 到当前的 transformer.TrainerCallback 列表。

      参数:callback:一个 transformer.TrainerCallback 类、或者transformer.TrainerCallback 的实例。如果是类,那么Trainer 将会实例化它。

    • autocast_smart_context_manager( cache_enabled: typing.Optional[bool] = True ):一个辅助的 wrapper,它为 autocast 创建一个适当的上下文管理器,同时根据情况给它馈入所需的参数。

      它用于混合精度训练,即 torch.cuda.amp.autocast()

    • compute_loss(model, inputs, return_outputs=False): 作为 Trainer 的计算损失的函数。默认情况下,所有的模型通过 output 返回损失(output 的第一个元素)。

    • compute_loss_context_manager():一个 helper wrapper,用于聚合针对 compute_loss 的上下文管理器(如,混合精度训练)。

    • create_model_card():创建 model card 的一个草稿。

      
      
      xxxxxxxxxx
      create_model_card( language: Optional[str] = None, license: Optional[str] = None, tags: Union[str, List[str], None] = None, model_name: Optional[str] = None, finetuned_from: Optional[str] = None, tasks: Union[str, List[str], None] = None, dataset_tags: Union[str, List[str], None] = None, dataset: Union[str, List[str], None] = None, dataset_args: Union[str, List[str], None] = None )

      参数:

      • language:一个字符串,指定模型的语言。
      • license:一个字符串,指定模型的 license
      • tags:一个字符串或关于字符串的列表,指定模型卡片的 tag
      • model_name:一个字符串,指定模型的名称。
      • finetuned_from:一个字符串,指定当前模型从哪个模型微调而来。
      • tasks:一个字符串或关于字符串的列表,指定当前模型用于哪些任务。
      • dataset_tags:一个字符串或关于字符串的列表,指定数据集的 tag
      • dataset:一个字符串或关于字符串的列表,指定数据集的 identifier
      • dataset_args:一个字符串或关于字符串的列表,指定数据集参数。
    • create_optimizer():创建优化器 optimizer

      我们提供了一个合理的默认值,运行良好。如果你想使用自定义的优化器,你可以通过 optimizers 参数在 Trainerinit 方法中传递一个元组,或者在子类中重写这个方法。

    • create_optimizer_and_scheduler(num_training_steps: int ):创建优化器和学习率调度器 scheduler

      参数:num_training_steps:一个整数,指定总的 training step 数量。

      我们提供了一个合理的默认值,运行良好。如果你想使用自定义的优化器和调度器,你可以通过 optimizers 参数在 Trainerinit 方法中传递一个元组,或者在子类中重写这个方法。

    • create_scheduler( num_training_steps: int, optimizer: Optimizer = None):创建学习率调度器 scheduler

      参数:参考 create_optimizer_and_scheduler()

      我们提供了一个合理的默认值,运行良好。如果你想使用自定义的调度器,你可以通过 optimizers 参数在 Trainerinit 方法中传递一个元组,或者在子类中重写这个方法。

    • evaluate():评估模型并返回评估指标。注意,需要使用者提供一个方法来计算指标(通过 Traininginit 方法中的 compute_metrics 参数)。

      
      
      xxxxxxxxxx
      evaluate( eval_dataset: Optional[Dataset] = None, ignore_keys: Optional[List[str]] = None, metric_key_prefix: str = "eval" ) -> Dict[str, float]

      参数:

      • eval_dataset:一个 Dataset,指定验证集。如果非 None,那么它将覆盖 self.eval_dataset 。它必须实现 __len__() 方法。对于前向传播不需要的列,都会被自动移除。
      • ignore_keys:一个关于字符串的列表,指定需要忽略 model output 中的哪些 key (如果 model output 是一个字典)。
      • metric_key_prefix:一个字符串,指定添加到指标名称的前缀。默认为 eval
    • evaluation_loop()prediction/evaluationloop,由 Trainer.evaluate()Trainer.predict() 所使用。

      
      
      xxxxxxxxxx
      evaluation_loop( dataloader: DataLoader, description: str, prediction_loss_only: Optional[bool] = None, ignore_keys: Optional[List[str]] = None, metric_key_prefix: str = "eval" ) -> EvalLoopOutput

      参数:

      • dataloader:一个 DataLoader
      • description:一个字符串,指定描述文本。
      • prediction_loss_only:一个布尔值,指定是否仅计算损失函数。
      • 其它参数参考 evaluate()
    • floating_point_ops( inputs: typing.Dict[str, typing.Union[torch.Tensor, typing.Any]] ) -> int:返回模型的浮点操作的数量。

      参数:inputs:一个字典,键为字符串、值为 torch.Tensor 或其他对象,指定模型的 inputstargets 。浮点运算数量就是在它之上统计的。

      对于继承自 PreTrainedModel 的模型,使用该方法来计算每次反向传播+前向传播的浮点运算数量。如果使用其他模型,要么在模型中实现这样的方法,要么在子类中覆盖这个方法。

    • get_eval_dataloader( eval_dataset: Optional[Dataset] = None) -> DataLoader:返回评估时的 dataloader

      参数:eval_dataset:一个 torch.utils.data.Dataset,如果提供该参数,则覆盖 self.eval_dataset 。如果它是一个 Transformer Dataset 类,那么model.forward() 不需要的列将被自动移除。

    • get_test_dataloader( test_dataset: Dataset) -> DataLoader:返回测试时的 dataloader

      参数:参考 get_eval_dataloader

    • get_train_dataloader() -> DataLoader:返回训练时的 dataloader

      如果 train_dataset 没有实现 __len__ 方法,那么将不使用 sampler;否则使用一个 random sampler (适配分布式训练,如果有必要的话)。

    • get_optimizer_cls_and_kwargs(args: TrainingArguments ) -> Tuple[Any, Any]:基于 training arguments,返回优化器的 class 和优化器的参数。

    • hyperparameter_search():使用 optunaRay TuneSigOpt 启动一个超参数搜索。

      被优化的量由 compute_objective 决定:当没有提供指标时默认为一个返回 evaluation loss 的函数;否则,为所有指标的 sum

      
      
      xxxxxxxxxx
      hyperparameter_search( hp_space: Optional[Callable[["optuna.Trial"], Dict[str, float]]] = None, compute_objective: Optional[Callable[[Dict[str, float]], float]] = None, n_trials: int = 20, direction: str = "minimize", backend: Optional[Union["str", HPSearchBackend]] = None, hp_name: Optional[Callable[["optuna.Trial"], str]] = None, **kwargs, ) -> BestRun

      要使用这个方法,你需要在初始化你的 Trainer 时提供一个 model_init :我们需要在每次 new run 时重新初始化模型。这与 optimizer argument 不兼容,所以你需要对 Trainer 进行子类化,并重写 create_optimizer_and_scheduler() 方法从而用于自定义 optimizer/scheduler

      参数:

      • hp_space:一个可调用对象,它定义了超参数搜索空间。默认为 default_hp_space_optuna()default_hp_space_ray()、或 default_hp_space_sigopt(),取决于你的后端。
      • compute_objective:一个可调用对象,它计算目标的函数,这个目标就是我们需要最大化或最小化的。默认为 default_compute_objective()
      • n_trials:一个整数,指定要测试的 trial runs 的数量。
      • direction:一个字符串,指定是最大化还是最小化目标。可以为 "minimize""maximize"
      • backend:一个字符串,指定超参数搜索的后端。默认为 optunaRay Tune、或者 SigOpt ,取决于哪一个被安装。如果都安装了,那么默认为 optuna
      • hp_name:一个可调用对象,对它调用的返回值给出了 trial/run 的名称。默认为 None
      • kwargs:传递给 optuna.create_studyray.tune.run 的额外关键字参数。

      返回 trainer_utils.BestRun ,它包含 best run 的所有信息。

    • init_git_repo(at_init: bool = False):在 self.args.hub_model_id 中初始化一个 git repo

      参数:

      • at_init:一个布尔值,指定该函数是否在任何训练之前被调用。如果 self.args.overwrite_output_dir = True ,并且 at_init=True,那么 repo 的路径(也就是 self.args.output_dir )可能会被抹去。
    • is_local_process_zero() -> bool:返回当前进程是否是 local 的主进程。

      local 指的是分布式训练环境中的 local 机器。

    • is_world_process_zero() -> bool:返回当前进程是否是 global 的主进程。

      当在机台机器上执行分布式训练时,只有一个进程是 global 主进程,但是可能有多个进程是 local 主进程。

    • log( logs: Dict[str, float]):记录日志。

      参数:logs:需要被记录的内容。

    • log_metrics(split: str, metrics: Dict[str, float]):以一种特殊的格式记录指标。

      参数:

      • split:一个字符串,指定split 名称,如 trainevaltest
      • metrics:一个字典,指定需要被记录的指标值。

      注意:在分布式环境下,这只对 rank = 0 的进程进行记录。

      关于内存报告的说明:为了获得内存使用报告,你需要安装psutilpip install psutil)。然后,当 log_metrics() 运行时你将看到如下的报告:

      
      
      xxxxxxxxxx
      init_mem_cpu_alloc_delta = 1301MB init_mem_cpu_peaked_delta = 154MB init_mem_gpu_alloc_delta = 230MB init_mem_gpu_peaked_delta = 0MB train_mem_cpu_alloc_delta = 1345MB train_mem_cpu_peaked_delta = 0MB train_mem_gpu_alloc_delta = 693MB train_mem_gpu_peaked_delta = 7MB

      其中:

      • 第一个字段(如 train_)告诉你指标是针对哪个 stage 的。以init_ 开头的报告将被添加到第一个 stage 。因此,如果只运行模型评估,init_ 的内存使用量将与 eval_ 的指标一起被报告。

      • 第三个字段是 cpugpu,告诉你这是通用 RAM 指标、还是 GPU0 的内存指标。

      • alloc_deltastage 结束和 state 开始之间所使用/分配的内存计数器的差值。如果一个函数释放的内存比分配的内存更多,那么它可以是负数。

      • peaked_delta 是额外的内存,这些内存被消费然后被释放掉。它永远不会是负数。

        当你看任何 stage 的内存指标时,你把alloc_delta + peaked_delta 加起来,你就知道完成该 stage 需要多少内存了。

      报告只发生在 rank = 0 的进程、以及 gpu 0(如果有gpu)。通常这就足够了,因为主进程做了大部分工作,但如果使用模型并行,那么其他 GPU 可能会使用不同数量的 gpu 内存 。这在 DataParallel 下也是不一样的,gpu0 可能需要比其他 gpu 多得多的内存,因为它为所有参与的 GPU存储梯度和 optimizer states。也许在未来,这些报告也会发展到测量这些指标。

      CPU RAM 指标 RSS (常驻集大小Resident Set Size )包括进程特有的内存、以及与其他进程共享的内存。值得注意的是,它不包括交换出来的内存 swapped out memory ,所以报告可能不精确。

      CPU 的峰值内存是用一个采样线程测量的。由于 pythonGIL,如果该线程在最高内存使用时没有机会运行,它可能会错过一些峰值内存。因此,这个报告可能比实际情况要少。使用 tracemalloc 会报告准确的峰值内存,但它并不报告 python 以外的内存分配情况。因此,如果某个 C++ CUDA extension 分配了自己的内存,就不会被报告。因此,它被放弃了,而采用了内存采样的方法,即读取当前进程的内存使用量。

      GPU 分配的内存和峰值内存的报告是通过 torch.cuda.memory_allocated()torch.cuda.max_memory_allocated() 完成的。这个指标只报告 pytorch-specific allocation"deltas" ,因为 torch.cuda 内存管理系统并不跟踪 pytorch 以外分配的任何内存。例如,第一个 cuda 调用通常加载 CUDA kernel ,这可能需要 0.52GBGPU 内存。

      请注意,这个 tracker 并不考虑Trainer__init__ 、训练、评估、以及预测的调用之外的内存分配。

      因为 evaluation 调用可能发生在训练过程中,我们无法处理嵌套调用,因为 torch.cuda.max_memory_allocated 是一个单一的计数器,所以如果它被一个嵌套的 evaluation 调用重置,traintracker 将报告错误的信息。如果这个 pytorch 问题得到解决,就有可能把这个类改成可重入的。在那之前,我们将只追踪外层的 trainevaluationpredict 方法。这意味着如果 evaltrain 过程中被调用,那么将 train 阶段统计的内存报告其实是 eval 的。

      这也意味着,如果任何其他与 Trainer 一起使用的工具调用 torch.cuda.reset_peak_memory_statsgpu 峰值内存统计可能是无效的。而且 Trainer 会扰乱任何依赖调用 torch.cuda.reset_peak_memory_stats 的工具的正常行为。

      为了获得最佳性能,你可能要考虑在生产运行中关闭 memory profiling 功能。

    • metrics_format(metrics: Dict[str, float]) -> Dict[str, float]):格式化 Trainer 指标值到人类可阅读的格式。

      参数:metrics:一个字典,指定需要被格式化的指标值。

    • num_examples(dataloader: DataLoader) -> int:返回数据集中的样本数量。

      如果 dataloader.dataset 不存在,或者 dataloader.dataset 没有长度,那么该方法尽力估算一个数量。

    • pop_callback(callback) -> transformer.TrainerCallback:从当前的 TrainerCallback 列表中移除一个 callback 并返回它。

      参数:参考 add_callback()

    • predict(test_dataset: Dataset, ignore_keys: Optional[List[str]] = None, metric_key_prefix: str = "test") -> PredictionOutput:执行预测。

      参数:

      • test_dataset:一个 Dataset,指定测试集。
      • 其它参数参考 evaluate()

      返回一个命名元组,它包含以下字段:

      • predictions:一个 np.ndarray,包含测试集的预测结果。
      • label_ids:一个 np.ndarray,包含 labels(如果测试集有的话)。
      • metrics:一个字典,给出测试集上的预测结果的指标(如果测试集有 labels 的话)。

      如果测试集包含 labels,那么该方法也会像 evaluate() 那样返回指标。

      如果你的 predictionslabels 有不同的序列长度(例如,在 token 分类任务中做动态填充), predictions 将被填充(右填充),以允许拼接成一个数组。 padding index = -100

    • prediction_loop()prediction/evaluationloop,由 Trainer.evaluate()Trainer.predict() 所使用。

      
      
      xxxxxxxxxx
      prediction_loop( dataloader: DataLoader, description: str, prediction_loss_only: Optional[bool] = None, ignore_keys: Optional[List[str]] = None, metric_key_prefix: str = "eval" ) -> PredictionOutput

      参数:参考 evaluation_loop()

    • prediction_step():在模型上使用 inputs 执行单个 evaluation step

      
      
      xxxxxxxxxx
      prediction_step( model: nn.Module, inputs: Dict[str, Union[torch.Tensor, Any]],prediction_loss_only: bool, ignore_keys: Optional[List[str]] = None ) -> Tuple[Optional[torch.Tensor], Optional[torch.Tensor], Optional[torch.Tensor]]

      参数:

      • model:一个 nn.Module 对象,指定被使用的模型。
      • inputs:一个字典,键为字符串、值为 torch.Tensor 或其他对象,指定模型的 inputstargets
      • 其它参数参考 evaluation_loop

      返回一个元组,分别为 loss, logits, labels (可能有的项没有)。

    • push_to_hub(commit_message: Optional[str] = "End of training", blocking: bool = True, **kwargs) -> str:将 self.modelself.tokenizer 上传到 model hub 上的 self.args.hub_model.id 所对应的 repo

    • remove_callback(callback):从当前的 TrainerCallback 列表中移除一个 callback

      参数:参考 add_callback()

    • save_metrics(split, metrics, combined=True):为指定的 split 保存指标到 json 文件,如 train_results.json

      参数:

      • combined:一个布尔值,指定是否创建一个汇总所有 split 的指标到 all_results.json
      • 其它参数参考 log_metrics()

      注意:在分布式环境下,这只对 rank = 0 的进程进行保存。

    • save_model(output_dir: Optional[str] = None, _internal_call: bool = False):保存模型,使得接下来可以采用 from_pretrained() 方法来加载模型。

      注意:仅仅从主进程保存;另外除了保存模型之外还会保存模型相应的 tokenizer

    • save_state():保存 Trainer state

      注意:在分布式环境下,这只对 rank = 0 的进程进行保存。

    • train():训练模型。

      
      
      xxxxxxxxxx
      train( resume_from_checkpoint: Optional[Union[str, bool]] = None, trial: Union[optuna.Trial, Dict[str, Any]] = None, ignore_keys_for_eval: Optional[List[str]] = None, **kwargs)

      参数:

      • resume_from_checkpoint:一个字符串或布尔值。

        • 如果是一个字符串,那么该字符串为 Trainer 前一个实例所保存的 checkpointlocal path 。训练将从这个 checkpoint 开始继续。
        • 如果是一个布尔值且为 True,那么加载 args.output_dir 中的最近一个 checkpoint ,该checkpointTrainer 的前一个实例保存。训练将从这个 checkpoint 开始继续。

        对于这两种情况,训练将从这里加载的 model/optimizer/scheduler states 恢复。

      • trial:一个optuna.Trial 或者字典,指定用于超参数搜索的 trial run、或超参数字典。

      • ignore_keys_for_eval:一个关于字符串的列表,指定当在训练期间进行 evaluation 时,需要忽略 model output 中的哪些 key (如果 model output 是一个字典)。

      • kwargs:关键字参数。

    • training_step( model: nn.Module, inputs: Dict[str, Union[torch.Tensor, Any]]) -> torch.Tensor :训练一个 batch

      参数:参考 prediction_step()

      返回值:这个 batch 上的训练损失。

  2. class transformers.Seq2SeqTrainer

    
    
    xxxxxxxxxx
    class transformers.Seq2SeqTrainer( model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.modules.module.Module] = None, args: TrainingArguments = None, data_collator: typing.Optional[DataCollator] = None, train_dataset: typing.Optional[torch.utils.data.dataset.Dataset] = None, eval_dataset: typing.Optional[torch.utils.data.dataset.Dataset] = None, tokenizer: typing.Optional[transformers.tokenization_utils_base.PreTrainedTokenizerBase] = None, model_init: typing.Callable[[], transformers.modeling_utils.PreTrainedModel] = None, compute_metrics: typing.Union[typing.Callable[[transformers.trainer_utils.EvalPrediction], typing.Dict], NoneType] = None, callbacks: typing.Optional[typing.List[transformers.trainer_callback.TrainerCallback]] = None, optimizers: typing.Tuple[torch.optim.optimizer.Optimizer, torch.optim.lr_scheduler.LambdaLR] = (None, None), preprocess_logits_for_metrics: typing.Callable[[torch.Tensor, torch.Tensor], torch.Tensor] = None )

    参数参考 class transformers.Trainer

    方法:

    • evaluate(eval_dataset: Optional[Dataset] = None, ignore_keys: Optional[List[str]] = None, metric_key_prefix: str = "eval", **gen_kwargs) -> Dict[str, float]:评估模型并返回评估指标,参考 Trainer.evaluate()

      参数:

      • max_length:一个整数,指定生成的目标序列的最大长度。
      • num_beams:一个整数,指定用于 beam searchbeam size1 意味着不使用 beam search
      • 其它参数参考 Trainer.evaluate()
    • predict(test_dataset: Dataset, ignore_keys: Optional[List[str]] = None, metric_key_prefix: str = "test", **gen_kwargs) -> PredictionOutput:执行预测,参考 Trainer.predict()

      参数:参考 evaluate()Trainer.predict()

1.2 注意事项

a. Checkpoints

  1. 默认情况下,Trainer 会将所有 checkpoints 保存在 TrainingArguments 中设置的 output_dir 。这些 checkpoints 将被放在名为 checkpoint-xxx 的子文件夹中,xxx 是训练所处的 step

    可以通过在调用 Trainer.train() 使用如下的方式,从而从 checkpoints 恢复训练:

    • resume_from_checkpoint=True:这将从 latest checkpoint 恢复训练。
    • resume_from_checkpoint=checkpoint_dir:这将从指定目录中的 specific checkpoint 恢复训练。

    此外,当使用 push_to_hub=True 时,你可以轻松地将 checkpoints 保存在 Model Hub 。默认情况下,所有保存在 intermediate checkpoints 的模型被保存在不同的 commits 中,但不包括 optimizer state 。你可以将 TrainingArgumentshub-strategy 值调整为如下两种:

    • "checkpoint"latest checkpoint 也被推送到一个名为 last-checkpoint 的子文件夹中,允许你用trainer.train(resume_from_checkpoint="output_dir/last-checkpoint") 轻松恢复训练。
    • "all_checkpoints":所有 checkpoints 都被推送到输出文件夹中(所以你会在 final repo 的每个文件夹中得到一个 checkpoint 文件夹)。

b. Logging

  1. 默认情况下,Trainer 将对主进程使用 logging.INFO 、对副本使用 logging.WARNING (如果有副本的话)。这些默认值可以通过TrainingArguments 的参数被覆盖,以使用 5logging level 中的任何一个:

    • log_level 参数:用于主进程的 logging level 设置。
    • log_level_replica 参数:用于副本进程的 logging level 设置。

    此外,如果 TrainingArgumentslog_on_each_node = False ,只有主节点会使用其主进程的 log level setting ,所有其他节点将使用副本的 log level setting

    注意,Trainer 将在其 Trainer.__init__() 中为每个节点单独设置 transformerslog level 。因此,如果你在创建 Trainer 对象之前就调用了 transformers 的函数,你可能希望在 Trainer 创建之前就为 transformers 设置 log level 。示例:

    
    
    xxxxxxxxxx
    [...] logger = logging.getLogger(__name__) # Setup logging logging.basicConfig( format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", datefmt="%m/%d/%Y %H:%M:%S", handlers=[logging.StreamHandler(sys.stdout)], ) # set the main code and the modules it uses to the same log-level according to the node log_level = training_args.get_process_log_level() logger.setLevel(log_level) datasets.utils.logging.set_verbosity(log_level) transformers.utils.logging.set_verbosity(log_level) trainer = Trainer(...)
  2. 如果你只想看到主节点上的警告,而所有其他节点不打印任何很可能是重复的警告,你可以这样运行:

    
    
    xxxxxxxxxx
    my_app.py ... --log_level warning --log_level_replica error

    在多节点环境中,如果你也不希望每个节点的主进程的日志重复,你要把上面的内容改为:

    
    
    xxxxxxxxxx
    my_app.py ... --log_level warning --log_level_replica error --log_on_each_node 0

    如果你需要你的应用程序尽可能的安静,你可以这样做:

    
    
    xxxxxxxxxx
    my_app.py ... --log_level error --log_level_replica error --log_on_each_node 0

c. 随机性

  1. 当从 Trainer 生成的 checkpoint 恢复训练时,所有的努力都是为了将 python, numpy, pytorch RNG 的状态恢复到保存该 checkpoint 时的状态,这应该使 "stop and resume" 的训练方式尽可能地接近于 non-stop training

    然而,由于各种默认的 non-deterministic pytorch settings ,这可能不完全有效。如果你想要完全的确定性,请参考 https://pytorch.org/docs/stable/notes/randomness。正如文档中所解释的,那些让事情变得确定的一些settings(如 torch.backends.cudnn.deterministic )可能会让事情变慢,因此这不能在默认情况下进行。但如果需要,你可以自己启用这些settings

d. 指定 GPU

  1. 这里讨论一下:如何告诉你的程序哪些 GPU 要被使用、以及按照什么顺序来使用。

  2. 当使用 DistributedDataParallel 并且只使用 GPU 的一个子集时,你只需指定要使用的 GPU 的数量。例如,如果你有 4GPU,但你希望使用前两个,你可以这样做:

    
    
    xxxxxxxxxx
    python -m torch.distributed.launch --nproc_per_node=2 trainer-program.py ...

    如果你已经安装了 acceleratedeepspeed ,你也可以通过使用以下方法之一来完成同样的工作:

    
    
    xxxxxxxxxx
    accelerate launch --num_processes 2 trainer-program.py ... deepspeed --num_gpus 2 trainer-program.py ...

    你不需要使用 AccelerateDeepspeedintegration features 来使用这些 launchers

  3. 到目前为止,我们可以告诉程序要使用多少个 GPU 。现在讨论一下如何选择特定的 GPU 并控制其顺序。

    CUDA_VISIBLE_DEVICES 环境变量可以帮助你控制使用哪些GPU 、以及GPU 的顺序,方法是:将环境变量 CUDA_VISIBLE_DEVICES 设置为将要使用的 GPU 的列表。例如,假设有4GPU0, 1, 2, 3。为了只在物理 GPU 0GPU 2 上运行,你可以这样做:

    
    
    xxxxxxxxxx
    CUDA_VISIBLE_DEVICES=0,2 python -m torch.distributed.launch trainer-program.py ...

    所以现在 pytorch 将只看到 2GPU ,其中你的物理 GPU 0GPU 2 分别映射到 cuda:0cuda:1

    • 你甚至可以改变它们的顺序:

      
      
      xxxxxxxxxx
      CUDA_VISIBLE_DEVICES=2,0 python -m torch.distributed. launch trainer-program.py ...

      现在你的物理 GPU 0GPU 2 被映射到 cuda:1cuda:0 上。

    • 上面的例子都是针对 DistributedDataParallel 的使用模式,但同样的方法也适用于DataParallel

      
      
      xxxxxxxxxx
      CUDA_VISIBLE_DEVICES=2,0 python trainer-program.py ...
    • 要模拟一个没有 GPU 的环境,只需将这个环境变量设置为空值,像这样:

      
      
      xxxxxxxxxx
      CUDA_VISIBLE_DEVICES= python trainer-program.py ...
    • 与任何环境变量一样,你也可以导出这些环境变量,而不是将这些环境变量添加到命令行中,例如:

      
      
      xxxxxxxxxx
      export CUDA_VISIBLE_DEVICES=0,2 python -m torch.distributed.launch trainer-program.py ...

      但这种方法可能会让人困惑,因为你可能会忘记你之前设置的环境变量,不明白为什么会使用错误的 GPU。因此,通常的做法是在同一命令行中只为特定的运行设置环境变量。

  4. 有一个额外的环境变量 CUDA_DEVICE_ORDER 用于控制物理设备的排序方式。两个选择是:

    • 根据 PCIe 总线 ID 排序(与 nvidia-smi 的顺序一致)。这是默认的方式。

      
      
      xxxxxxxxxx
      export CUDA_DEVICE_ORDER=PCI_BUS_ID
    • 根据 GPU 的计算能力排序。

      
      
      xxxxxxxxxx
      export CUDA_DEVICE_ORDER=FASTEST_FIRST

    大多数情况下,你不需要关心这个环境变量。但是,假如你有一个旧且慢的 GPU 显卡、以及一个新且快的 GPU 显卡,并且不恰当的插入方式使得旧显卡看起来是第一位的,那么这个环境变量就非常有用。

    解决这个问题的方法之一是交换显卡的插入位置。或者设置 CUDA_DEVICE_ORDER=FASTEST_FIRST 将总是把较快的新卡放在第一位。不过这将会有些混乱,因为 nvidia-smi 仍然会按照 PCIe 顺序报告它们。

    交换顺序的另一个解决方案是使用:

    
    
    xxxxxxxxxx
    export CUDA_VISIBLE_DEVICES=1,0

e. Trainer 集成

  1. Trainer 已经被扩展到支持一些库,这些库可能会极大地改善你的训练时间并适应更大的模型。

    目前,它支持第三方解决方案,如 DeepSpeed, PyTorch FSDP, FairScale ,它们实现了论文 《ZeRO: Memory Optimizations Toward Training Trillion Parameter Models》 的一部分。

    截至本文写作时,这种提供的支持是新的和实验性的。虽然对 DeepSpeedPyTorch FSDP 的支持是活跃的,我们也欢迎围绕它们的问题,但我们不再支持 FairScale 的集成,因为 FairScale 已经集成到 PyTorch 主系统中。

  2. CUDA Extension 安装:截至目前,FairScaleDeepspeed 都需要编译 CUDA C++ 代码才能使用。

    虽然所有的安装问题都应该通过 FairScaleDeepspeed 的相应 GitHub issue 来处理,但在构建任何需要构建 CUDA ExtensionPyTorch extension 时,可能会遇到一些常见的问题。因此,如果你在执行如下指令时遇到了与 CUDA 相关的 build issue

    
    
    xxxxxxxxxx
    pip install fairscale pip install deepspeed

    那么请阅读以下说明。在这些说明中,我们举例说明了当 pytorch 是用 CUDA 10.2 构建的时候应该怎么做。如果你的情况不一样,请记得把版本号调整为你所需要的版本。

    • 可能的问题 1:虽然,Pytorch 带有自己的 CUDA toolkit ,但要构建这两个项目(即,fairscale, deepspeed),你必须在全系统安装相同版本的 CUDA

      例如,如果你在 Python 环境下安装了 pytorch ,并使用 cudatoolkit==10.2 ,你也需要在全系统安装CUDA 10.2

      具体位置可能因系统而异,但 /usr/local/cuda-10.2 是许多 Unix 系统上最常见的位置。当 CUDA 被正确设置并添加到PATH环境变量中时,可以通过以下操作找到安装位置:

      
      
      xxxxxxxxxx
      which nvcc

      如果你的系统中没有安装 CUDA,请先安装它。

    • 可能的问题 2:你可能在系统中安装了不止一个 CUDA toolkit ,如:

      
      
      xxxxxxxxxx
      /usr/local/cuda-10.2 /usr/local/cuda-11.0

      现在,在这种情况下,你需要确保你的 PATHLD_LIBRARY_PATH 环境变量包含所需 CUDA 版本的正确路径。通常情况下,软件包安装程序会将这些设置为包含最仅安装的任何版本。如果你遇到这样的问题,即尽管你已经在全系统安装了 CUDA ,但由于找不到正确的 CUDA 版本而导致 package 构建失败,这意味着你需要调整上述两个环境变量:

      
      
      xxxxxxxxxx
      export PATH=/usr/local/cuda-10.2/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATH
    • 可能的问题 3:一些旧的 CUDA 版本可能会拒绝使用较新的编译器进行编译。例如,你有 gcc-9 ,但它想要 gcc-7 。有多种方法可以解决这个问题:

      • 如果你能安装最新的CUDA toolkit,它通常应该支持较新的编译器。

      • 另外,你可以在你已经有的编译器之外再安装低版本的编译器;或者,你已经有了低版本的编译器但它不是默认的,所以构建系统看不到它。下面的方法可能会有帮助:

        
        
        xxxxxxxxxx
        sudo ln -s /usr/bin/gcc-7 /usr/local/cuda-10.2/bin/gcc sudo ln -s /usr/bin/g++-7 /usr/local/cuda-10.2/bin/g++

        这里,我们从 /usr/local/cuda-10.2/bin/gcc 建立了一个指向 gcc-7 的符号链接,由于 /usr/local/cuda-10.2/bin/ 应该在 PATH 环境变量中(见前面问题的解决方案),它应该找到 gcc-7(和 g++7 ),然后构建就会成功。

  3. PyTorch Fully Sharded Data Parallel: FSDP:为了在更大的 batch size 上加速训练巨大的模型,我们可以使用一个 fully sharded data parallel model 。这种类型的数据并行范式通过分片 optimizer states 、梯度、以及parameters,能够适应更多的数据和更大的模型。我们已经集成了最新 PyTorch’s Fully Sharded Data Parallel: FSDP 训练特性。你只需通过配置将其启用即可。

    注意,必须从 PyTorch 1.12.0 及其以后的版本才可以使用 FSDP 的能力。

    用法:

    • 确保你已经添加了distributed launcher

      
      
      xxxxxxxxxx
      python -m torch.distributed. launch --nproc_per_node=NUMBER_OF_GPUS_YOU_HAVE ...
    • 分片策略:

      • FULL_SHARD:将 optimizer states + gradients + model parameters 分片到 data parallel workers/GPUs 中。为此,在命令行参数中添加 -fsdp full_shard
      • SHARD_GRAD_OP:将 optimizer states + gradients 分片到 data parallel workers/GPUs 中。为此,在命令行参数中添加 -fsdp shard_grad_op
      • NO_SHARD:不分片。为此,在命令行参数中添加 -fsdp no_shard
    • 要将 parametersgradients 卸载到 CPU ,请在命令行参数中添加:

      
      
      xxxxxxxxxx
      --fsdp "full_shard offload" # or --fsdp "shard_grad_op offload"
    • 要使用 default_auto_wrap_policy 来采用 FSDP 自动递归地 wrap layers ,请在命令行参数中添加:

      
      
      xxxxxxxxxx
      --fsdp "full_shard auto_wrap" # or --fsdp "shard_grad_op auto_wrap"。
    • 要同时启用 CPU 卸载和 auto wrapping,请在命令行参数中添加:

      
      
      xxxxxxxxxx
      --fsdp "full_shard offload auto_wrap" # or --fsdp "shard_grad_op offload auto_wrap"
    • 如果启用了 auto wrapping,你可以使用 transformer based auto wrap policysize based auto wrap policy

      • 对于 transformer based auto wrap policy ,请在命令行参数中加入:

        
        
        xxxxxxxxxx
        --fsdp_transformer_layer_cls_to_wrap <value>

        这指定了要包装的 transformer layer class name(区分大小写),例如,BertLayer, GPTJBlock, T5Block,... 。这很重要,因为共享权重的子模块(例如,embedding layer)不应该最终出现在不同的 FSDP wrapped units 中。

        使用这个策略,每个包含 Multi-Head Attention followed by couple of MLP layersblock 都会发生包装。其余的层,包括 shared embeddings ,都方便地被包裹在同一个最外层的 FSDP unit 中。因此,对于 transformer based 的模型,可以使用这个策略。

      • 对于 size based auto wrap policy,请在命令行参数中加入:

        
        
        xxxxxxxxxx
        --fsdp_min_num_params <number>

        它指定了 FSDP auto wrapping 的最少的 parameters 数量。

    • 一些注意事项:

      • FSDP 目前不支持混合精度,因为我们在等待 PyTorch 修复对混合精度的支持。
      • FSDP 目前不支持multiple parameter groups

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文