当前位置:   article > 正文

huggingface笔记:使用accelerate加速_huggingface accelerate

huggingface accelerate

1 介绍

  • 随着模型规模的增大,并行处理已成为在有限硬件上训练大型模型和提高训练速度的重要策略。
  • Hugging Face 创建了Accelerate库,帮助用户在任何类型的分布式环境中轻松训练Transformers模型,无论是单机多GPU还是跨多机的多GPU

2 创建Accelerator对象

  1. from accelerate import Accelerator
  2. accelerator = Accelerator()

3 训练对象传递给prepare方法

  1. train_dataloader, eval_dataloader, model, optimizer = accelerator.prepare(
  2. train_dataloader,
  3. eval_dataloader,
  4. model,
  5. optimizer
  6. )

4 反向传播

唯一不同的是把loss.backward()替换成Accelerate的backward

5 总结

绿色的是加上的,红色的是去掉的

6  训练

运行以下命令创建并保存配置文件

accelerate config

然后启动训练:

accelerate launch train.py

7 保存和加载

  • 使用 save_state() 将所有内容保存到一个文件夹位置
  • 使用 load_state() 加载之前通过 save_state() 保存的所有内容

  • 通过使用 register_for_checkpointing(),可以注册自定义对象以便通过前两个函数自动存储或加载

7.1 unwrap_model

  • 解包模型,在保存模型之前,用于从 prepare() 可能添加的额外层中解包模型
    • 因为 prepare() 方法将模型包装成适合分布式训练的接口。
    • 如果不解包模型,保存模型状态字典时也会保存大模型中可能存在的额外层,之后就无法将权重加载回基础模型
  1. # 假设有两个GPU进程
  2. from torch.nn.parallel import DistributedDataParallel
  3. from accelerate import Accelerator
  4. accelerator = Accelerator()
  5. model = accelerator.prepare(MyModel())
  6. print(model.__class__.__name__)
  7. #DistributedDataParallel
  8. model = accelerator.unwrap_model(model)
  9. print(model.__class__.__name__)
  10. #MyModel
  11. torch.save(model.state_dict(), path)
  12. #解包之后,可以用torch的save函数

还可以使用使用 accelerate提供的save_model() 方法来解包并保存模型状态字典。

  1. accelerator.wait_for_everyone()
  2. accelerator.save_model(model, save_directory)

 7.1.1 使用save_pretrained 保存模型

这样可以后续用from_pretrained的方式再得到模型

  1. from transformers import AutoModel
  2. unwrapped_model = accelerator.unwrap_model(model)
  3. unwrapped_model.save_pretrained(
  4. "path/to/my_model_directory",
  5. is_main_process=accelerator.is_main_process,
  6. save_function=accelerator.save,
  7. )
  8. model = AutoModel.from_pretrained("path/to/my_model_directory")

8 分布式评估

8.1 gather_for_metrics

  • 在分布式系统中,每个设备只接收一部分评估数据,这意味着你应该使用 gather_for_metrics() 方法将你的预测结果组合在一起。
  • 此方法会收集 input_data 并可能在最后一个批次中删除重复项。
  • 可应用于收集用于指标计算的输入和目标。
  • 此方法要求每个进程上的所有张量大小相同,因此如果张量在每个进程上的大小不同(例如在批处理中动态填充到最大长度时),应该使用 pad_across_processes() 方法将你的张量填充到跨进程的最大大小
  1. for inputs, targets in validation_dataloader:
  2. predictions = model(inputs)
  3. # Gather all predictions and targets
  4. all_predictions, all_targets = accelerator.gather_for_metrics((predictions, targets))
  5. # Example of use with a *Datasets.Metric*
  6. metric.add_batch(all_predictions, all_targets)

8.2  pad_across_processes

( tensordim = 0,pad_index = 0,pad_first = False ) → torch.Tensor,

递归地填充来自所有设备的嵌套列表/元组/字典中的张量,以便它们可以安全地被聚合。

tensor要聚合的数据
dim填充的维度
pad_index用于填充的值
pad_first是否在开始或结束时进行填充

  1. # 假设有两个进程,第一个进程有一个大小为1的张量,第二个进程的张量大小为2
  2. import torch
  3. from accelerate import Accelerator
  4. accelerator = Accelerator()
  5. process_tensor = torch.arange(accelerator.process_index + 1).to(accelerator.device)
  6. '''
  7. accelerator.process_index:这是当前进程的索引。
  8. 在两个进程的设置中,第一个进程的索引为 0,第二个进程的索引为 1。
  9. '''
  10. padded_tensor = accelerator.pad_across_processes(process_tensor)
  11. '''
  12. 它确保所有进程中的张量都被填充到相同的大小,这样它们就可以安全地聚合或进行其他并行操作
  13. '''
  14. padded_tensor.shape
  15. #torch.Size([2])

9 accelerate原理

  • 在内部,Accelerate 首先分析启动脚本的环境,以确定使用的分布式设置类型、有多少个不同的进程以及当前脚本位于哪个进程中
  • 然后,调用 prepare() 时,库会:

    • 将模型封装在适用于分布式设置的容器中,

    • 将优化器封装在 AcceleratedOptimizer 中,

    • 将调度器封装在 AcceleratedScheduler 中,

    • 在 DataLoaderShard 或 DataLoaderDispatcher 中创建数据加载器的新版本。

      • 创建的原因是, PyTorch 不允许用户在数据加载器创建后更改其批处理采样器

      • DataLoaderShard 继承自 DataLoader,添加了以下功能:

        • 它在每次新迭代时同步所有进程的适当随机数生成器,以确保任何随机化(如洗牌)都以完全相同的方式跨进程完成。
        • 它在产生批次之前将批次放置在适当的设备上(除非选择了 device_placement=True)。
           
      • DataLoaderDispatcher 与 DataLoaderShard 的不同之处在于,在迭代 DataLoader 时,数据都是从进程 0 开始的,然后分割并发送到每个进程,而不是在数据集级别进行
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/771935
推荐阅读
相关标签
  

闽ICP备14008679号