Transformers 4.37 中文文档(十九)(6)https://developer.aliyun.com/article/1564927
调度器
DeepSpeed 支持 LRRangeTest
、OneCycle
、WarmupLR
和 WarmupDecayLR
学习率调度器。完整文档在这里。
这是🤗 Transformers 和 DeepSpeed 之间调度器重叠的地方:
- 通过
--lr_scheduler_type constant_with_warmup
实现的WarmupLR
- 通过
--lr_scheduler_type linear
配置WarmupDecayLR
。这也是--lr_scheduler_type
的默认值,因此,如果您没有配置调度程序,则默认将配置此调度程序。
如果您没有在配置文件中配置scheduler
条目,Trainer 将使用--lr_scheduler_type
、--learning_rate
和--warmup_steps
或--warmup_ratio
的值来配置其🤗 Transformers 版本。
以下是WarmupLR
的自动配置scheduler
条目示例:
{ "scheduler": { "type": "WarmupLR", "params": { "warmup_min_lr": "auto", "warmup_max_lr": "auto", "warmup_num_steps": "auto" } } }
由于使用了*“auto”*,Trainer 参数将在配置文件中设置正确的值。这样一来,数值就有了一个明确的来源,避免了例如学习率在不同地方设置为不同值时难以找到的错误。命令行规则。设置的值包括:
warmup_min_lr
,其值为0
。warmup_max_lr
,其值为--learning_rate
。- 如果提供了
--warmup_steps
,则warmup_num_steps
的值为--warmup_steps
。否则,将使用--warmup_ratio
乘以训练步数并四舍五入。 total_num_steps
,其值为--max_steps
或者如果未提供,则在运行时根据环境和数据集大小以及其他命令行参数自动推导(对于WarmupDecayLR
是必需的)。
当然,您可以接管任何或所有配置值,并自行设置:
{ "scheduler": { "type": "WarmupLR", "params": { "warmup_min_lr": 0, "warmup_max_lr": 0.001, "warmup_num_steps": 1000 } } }
但是,您需要自行同步 Trainer 命令行参数和 DeepSpeed 配置。
例如,对于WarmupDecayLR
,您可以使用以下条目:
{ "scheduler": { "type": "WarmupDecayLR", "params": { "last_batch_iteration": -1, "total_num_steps": "auto", "warmup_min_lr": "auto", "warmup_max_lr": "auto", "warmup_num_steps": "auto" } } }
total_num_steps
、warmup_max_lr
、warmup_num_steps
和total_num_steps
将在加载时设置。
fp32 精度
Deepspeed 支持完整的 fp32 和 fp16 混合精度。
由于使用 fp16 混合精度可以大大减少内存需求并提高速度,唯一不使用它的情况是当您使用的模型在这种训练模式下表现不佳时。通常情况下,这种情况发生在模型没有在 fp16 混合精度下进行预训练时(例如,bf16 预训练模型经常出现这种情况)。这样的模型可能会溢出或下溢,导致NaN
损失。如果您遇到这种情况,那么您需要使用完整的 fp32 模式,通过显式禁用默认的 fp16 混合精度模式:
{ "fp16": { "enabled": false, } }
如果您使用基于 Ampere 架构的 GPU,pytorch 版本 1.7 及更高版本将自动切换到使用更高效的 tf32 格式进行某些操作,但结果仍将是 fp32。有关详细信息和基准,请参阅TensorFloat-32(TF32) on Ampere devices。该文档包括如何在某种情况下禁用此自动转换的说明。
使用🤗 Trainer,您可以使用--tf32
来启用它,或者使用--tf32 0
或--no_tf32
来禁用它。默认情况下使用 PyTorch 默认值。
自动混合精度
您可以使用类似于 pytorch 的 AMP 方式或类似于 apex 的方式进行自动混合精度:
fp16
要配置带有 fp16(float16)的 pytorch AMP 模式,请设置:
{ "fp16": { "enabled": "auto", "loss_scale": 0, "loss_scale_window": 1000, "initial_scale_power": 16, "hysteresis": 2, "min_loss_scale": 1 } }
Trainer 将根据args.fp16_backend
的值自动启用或禁用它。其余的配置值由您决定。
当传递--fp16 --fp16_backend amp
或--fp16_full_eval
命令行参数时,此模式将被启用。
您还可以显式启用/禁用此模式:
{ "fp16": { "enabled": true, "loss_scale": 0, "loss_scale_window": 1000, "initial_scale_power": 16, "hysteresis": 2, "min_loss_scale": 1 } }
但是,您需要自行同步 Trainer 命令行参数和 DeepSpeed 配置。
这是文档。
bf16
如果希望使用 bf16(bfloat16)而不是 fp16,则应使用以下配置部分:
{ "bf16": { "enabled": "auto" } }
bf16 具有与 fp32 相同的动态范围,因此不需要损失缩放。
当传递--bf16
或--bf16_full_eval
命令行参数时,将启用此模式。
您也可以显式启用/禁用此模式:
{ "bf16": { "enabled": true } }
截至deepspeed==0.6.0
,bf16 支持是新的实验性功能。
如果您在启用 bf16 的情况下使用梯度累积,您需要注意它将在 bf16 中累积梯度,这可能不是您想要的,因为这种格式的低精度可能导致损失的累积。
正在进行修复工作,并提供使用更高精度dtype
(fp16 或 fp32)的选项。
NCCL 集合
这是训练制度的dtype
,还有一个用于通信集合的dtype
。
所有收集/散布操作都以相同的dtype
执行,因此如果您使用 bf16 训练制度,则会以 bf16 进行收集-收集是一个非损失操作。
各种减少操作可能会导致很大的损失,例如当梯度在多个 GPU 上平均时,如果通信使用 fp16 或 bf16,则结果可能会有损失-因为在低精度下相加多个数字时结果并不精确。bf16 的精度比 fp16 低,因此更容易出现这种情况。通常情况下,fp16 足够好,因为在平均梯度时损失很小。因此,默认情况下,对于半精度训练,减少操作的默认值是使用 fp16。但是您可以完全控制此功能,如果选择,可以增加一些开销,并确保减少操作将使用 fp32 作为累积 dtype,仅当结果准备就绪时才会将其降级为您正在训练的半精度dtype
。
要覆盖默认设置,只需添加一个新的配置条目:
{ "communication_data_type": "fp32" }
截至目前,有效值为“fp16”,“bfp16”,“fp32”。
注意:stage zero 3 存在关于 bf16 comm dtype 的错误,已在deepspeed==0.8.1
中修复。
apex
要配置 apex AMP 类似模式,请设置:
"amp": { "enabled": "auto", "opt_level": "auto" }
训练器将根据args.fp16_backend
和args.fp16_opt_level
的值自动配置。
当传递--fp16 --fp16_backend apex --fp16_opt_level 01
命令行参数时,将启用此模式。
您也可以显式配置此模式:
{ "amp": { "enabled": true, "opt_level": "O1" } }
但是,您需要自行同步 Trainer 命令行参数和 DeepSpeed 配置。
这是文档。
批量大小
要配置批量大小,请使用:
{ "train_batch_size": "auto", "train_micro_batch_size_per_gpu": "auto" }
训练器将自动将train_micro_batch_size_per_gpu
设置为args.per_device_train_batch_size
的值,将train_batch_size
设置为args.world_size * args.per_device_train_batch_size * args.gradient_accumulation_steps
的值。
您也可以显式设置这些值:
{ "train_batch_size": 12, "train_micro_batch_size_per_gpu": 4 }
但是,您需要自行同步 Trainer 命令行参数和 DeepSpeed 配置。
梯度累积
要配置梯度累积,请设置:
{ "gradient_accumulation_steps": "auto" }
训练器将自动将其设置为args.gradient_accumulation_steps
的值。
您也可以显式设置值:
{ "gradient_accumulation_steps": 3 }
但是,您需要自行同步 Trainer 命令行参数和 DeepSpeed 配置。
梯度裁剪
配置梯度裁剪设置:
{ "gradient_clipping": "auto" }
Trainer 将自动将其设置为args.max_grad_norm
的值。
您还可以显式设置该值:
{ "gradient_clipping": 1.0 }
但是,您需要自行同步 Trainer 命令行参数和 DeepSpeed 配置。
获取模型权重
只要您继续使用 DeepSpeed 进行训练和恢复,您就不必担心任何事情。DeepSpeed 将 fp32 主权重存储在其自定义检查点优化器文件中,这些文件是global_step*/*optim_states.pt
(这是通配符),并保存在正常检查点下。
FP16 权重:
当模型保存在 ZeRO-2 下时,您最终会得到带有模型权重的正常pytorch_model.bin
文件,但它们只是权重的 fp16 版本。
在 ZeRO-3 下,情况要复杂得多,因为模型权重被分区到多个 GPU 上,因此需要"stage3_gather_16bit_weights_on_model_save": true
来让Trainer
保存权重的 fp16 版本。如果此设置为False
,将不会创建pytorch_model.bin
。这是因为默认情况下 DeepSpeed 的state_dict
包含一个占位符而不是真正的权重。如果我们保存这个state_dict
,将无法加载回来。
{ "zero_optimization": { "stage3_gather_16bit_weights_on_model_save": true } }
FP32 权重:
虽然 fp16 权重适用于恢复训练,但如果您完成了微调模型并希望将其上传到models hub或传递给其他人,您很可能希望获取 fp32 权重。最好不要在训练过程中执行此操作,因为这是一个需要大量内存的过程,因此最好在训练完成后离线执行。但如果需要并且您有足够的空闲 CPU 内存,可以在相同的训练脚本中执行。以下部分将讨论这两种方法。
在线 FP32 权重恢复:
如果您的模型很大且剩余的 CPU 内存很少,这种方法可能不起作用。
如果您至少保存了一个检查点,并且想要使用最新的检查点,可以执行以下操作:
from transformers.trainer_utils import get_last_checkpoint from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint checkpoint_dir = get_last_checkpoint(trainer.args.output_dir) fp32_model = load_state_dict_from_zero_checkpoint(trainer.model, checkpoint_dir)
如果您正在使用--load_best_model_at_end
类:~transformers.TrainingArguments参数(用于跟踪最佳检查点),那么您可以通过首先显式保存最终模型,然后执行与上述相同的操作来完成训练:
from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint checkpoint_dir = os.path.join(trainer.args.output_dir, "checkpoint-final") trainer.deepspeed.save_checkpoint(checkpoint_dir) fp32_model = load_state_dict_from_zero_checkpoint(trainer.model, checkpoint_dir)
请注意,一旦运行了load_state_dict_from_zero_checkpoint
,model
将不再在相同应用程序的 DeepSpeed 上下文中可用。即您需要重新初始化 deepspeed 引擎,因为model.load_state_dict(state_dict)
将从中删除所有 DeepSpeed 的魔法。因此,只在训练的最后阶段执行此操作。
当然,您不必使用类:~transformers.Trainer,您可以根据自己的训练器调整上面的示例。
如果出于某种原因您想要更多的细化,您还可以提取权重的 fp32state_dict
并按照以下示例自行应用:
from deepspeed.utils.zero_to_fp32 import get_fp32_state_dict_from_zero_checkpoint state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir) # already on cpu model = model.cpu() model.load_state_dict(state_dict)
离线 FP32 权重恢复:
DeepSpeed 创建了一个特殊的转换脚本zero_to_fp32.py
,并将其放在检查点文件夹的顶层。使用此脚本,您可以在任何时候提取权重。该脚本是独立的,您不再需要配置文件或Trainer
来执行提取。
假设您的检查点文件夹如下所示:
$ ls -l output_dir/checkpoint-1/ -rw-rw-r-- 1 stas stas 1.4K Mar 27 20:42 config.json drwxrwxr-x 2 stas stas 4.0K Mar 25 19:52 global_step1/ -rw-rw-r-- 1 stas stas 12 Mar 27 13:16 latest -rw-rw-r-- 1 stas stas 827K Mar 27 20:42 optimizer.pt -rw-rw-r-- 1 stas stas 231M Mar 27 20:42 pytorch_model.bin -rw-rw-r-- 1 stas stas 623 Mar 27 20:42 scheduler.pt -rw-rw-r-- 1 stas stas 1.8K Mar 27 20:42 special_tokens_map.json -rw-rw-r-- 1 stas stas 774K Mar 27 20:42 spiece.model -rw-rw-r-- 1 stas stas 1.9K Mar 27 20:42 tokenizer_config.json -rw-rw-r-- 1 stas stas 339 Mar 27 20:42 trainer_state.json -rw-rw-r-- 1 stas stas 2.3K Mar 27 20:42 training_args.bin -rwxrw-r-- 1 stas stas 5.5K Mar 27 13:16 zero_to_fp32.py*
在这个例子中只有一个 DeepSpeed 检查点子文件夹global_step1。因此,要重建 fp32 权重,只需运行:
python zero_to_fp32.py . pytorch_model.bin
就是这样。pytorch_model.bin
现在将包含从多个 GPU 中整合的完整 fp32 模型权重。
脚本将自动处理 ZeRO-2 或 ZeRO-3 检查点。
python zero_to_fp32.py -h
将为您提供使用详细信息。
脚本将使用文件latest
的内容自动发现 deepspeed 子文件夹,当前示例中将包含global_step1
。
注意:当前脚本需要最终 fp32 模型权重的 2 倍通用 RAM。
Transformers 4.37 中文文档(十九)(8)https://developer.aliyun.com/article/1564929