DeepSpeed 数据效率:一个可组合的库,可以更好地利用数据、提高训练效率并改善模型质量
什么是 DeepSpeed 数据效率:DeepSpeed 数据效率是一个专门构建的库,用于更好地利用数据,提高训练效率并改善模型质量。
为什么要使用 DeepSpeed 数据效率:DeepSpeed 数据效率提供新颖的数据效率技术,以实现更好的训练效率和/或更好的模型质量。DeepSpeed 数据效率考虑了可扩展性、灵活性和可组合性,这使得更容易自定义技术、将技术应用于各种训练任务以及组合多种技术。我们强烈建议您也阅读我们的博客,以了解更多关于(在高级别)我们构建 DeepSpeed 数据效率的原因以及它为用户带来的好处。其他技术细节可以在我们的论文中找到,“Random-LTD:随机分层标记丢弃为大型 Transformer 带来了高效训练”描述了 random-LTD 技术,以及“DeepSpeed 数据效率:通过高效数据采样和路由提高深度学习模型质量和训练效率”描述了课程学习技术和整体 DeepSpeed 数据效率框架。
如何使用 DeepSpeed 数据效率:在以下教程中,前两节将描述库支持的数据效率技术。第三节将描述如何组合这两种技术以实现更好的训练效率/模型质量。
1. 课程学习
1.1 什么是课程学习
课程学习(由Yoshua Bengio 等人提出)旨在通过在训练早期呈现相对更容易或更简单的示例来提高训练收敛速度。构建课程学习解决方案通常需要两个组件:难度指标(即如何量化每个数据样本的难度)和节奏函数(即如何决定采样下一个训练数据批次时的课程难度范围)。
1.2 何时使用课程学习
课程学习已成功应用于各种训练任务(例如,参见这篇综述论文中的详细信息),去年我们还发布了一种针对 GPT 风格模型预训练的特定课程学习技术(序列长度预热)(参见我们发表在 NeurIPS 2022 上的论文“稳定性-效率困境:调查 GPT 模型训练的序列长度预热”以及此传统课程学习功能的教程中的技术细节)。DeepSpeed 数据效率中的这个新的通用课程学习库使用户能够以最大可扩展性将其应用于自己的模型:用户可以根据各种可自定义的策略轻松分析、索引和采样其训练数据。使用此库,我们能够探索 GPT-3 和 BERT 预训练的不同 CL 策略,并确定提供高达1.5 倍数据节省同时仍保持相似模型质量的最佳解决方案。
1.3 如何使用课程学习
1.3.1 GPT-3 和 BERT 预训练
我们Megatron-DeepSpeed 存储库中的examples_deepspeed/data_efficiency
目录包含我们如何将课程学习应用于 GPT-3 和 BERT 预训练的示例。包括三个步骤:数据分析、预训练和评估/微调。
数据分析:课程学习需要在预训练之前进行数据分析,以计算每个数据样本的难度(基于用户提供的指标),并构建一个将难度值映射到相应数据样本的索引。(有一些例外:例如,基于截断的序列长度指标可以通过数据后处理实现,无需数据分析。)我们提供了一个数据分析器来执行离线的仅 CPU 数据分析。
examples_deepspeed/data_efficiency/gpt/ds_analyze_*.sh
和examples_deepspeed/data_efficiency/bert/ds_analyze_*.sh
是 GPT-3 和 BERT 数据分析的示例脚本。我们的数据分析器采用简单的 Map-Reduce 方案。首先,在 Map 阶段,ds_analyze_*_data_map.sh
用于分割数据集并计算每个数据样本的难度值。用户需要提供一个计算指标的函数(我们在examples_deepspeed/data_efficiency/analyze_data.py
中实现了我们的函数)、原始训练数据集以及其他配置,例如 CPU 节点数和每个节点的线程数。然后,数据分析器将根据工作程序数量自动分割数据集,以批处理方式计算难度值,并将结果写入两个索引:一个索引将每个数据样本映射到其难度值,另一个索引将每个不同的难度值映射到相应的样本。其次,在 Reduce 阶段,ds_analyze_*_data_reduce.sh
用于合并所有工作程序生成的索引文件。需要注意的是,为了通过分布式实现加速,但仍然能够合并所有输出,Map 阶段可能会生成大量输出文件,这与 CPU 节点数、每个节点的线程数以及可能的指标值数量成正比。因此,为了避免生成过多的输出文件,我们建议从较少的节点/线程开始(在输出日志中,我们提供了用户判断是否要增加工作程序数量的所需时间估计),并且我们建议在设计难度指标时限制可能的难度值的数量(我们的经验表明,几千个不同的值已经足以享受课程学习的好处)。
预训练examples_deepspeed/data_efficiency/gpt/pretrain
和examples_deepspeed/data_efficiency/bert/pretrain
包含具有课程学习功能的示例预训练脚本。要启用预训练期间的课程学习,需要进行一些更改:(1)用户需要提供一个 DeepSpeed json 配置文件,其中包含课程学习的配置(有关详细信息,请参见配置列表)。我们在examples_deepspeed/data_efficiency/gpt/pretrain/ds_pretrain_gpt_1.3B_dense_run.sh
和examples_deepspeed/data_efficiency/bert/pretrain/ds_pretrain_bert_336M_run.sh
中提供了经过测试的示例配置。(2)当通过deepspeed.initialize
初始化 DeepSpeed 引擎时,用户需要提供训练数据集并使用初始化返回的数据加载器(此数据加载器包括课程学习功能)。我们在megatron/training.py
函数setup_model_and_optimizer
中提供了此更改的示例实现。(3)如果课程学习指标需要数据后处理(例如基于截断的序列长度),用户需要使用 DeepSpeed 引擎的set_data_post_process_func
API 提供后处理函数。我们在megatron/training.py
、pretrain_bert.py
和pretrain_gpt.py
中提供了此更改的示例实现。(4)如果课程学习指标需要自定义调度策略(节奏函数),用户需要使用 DeepSpeed 引擎的set_custom_curriculum_learning_schedule
API 提供用于更新训练期间最大接受难度的函数。DeepSpeed 引擎将向此回调函数提供全局训练步骤输入。
评估/微调examples_deepspeed/data_efficiency/gpt/eval/
和examples_deepspeed/data_efficiency/bert/finetune
包含 GPT-3 模型的零样本/少样本评估和 BERT 模型的微调的示例脚本。如果您按照我们的示例脚本执行预训练/评估/微调,我们的论文包含参考评估/微调结果。
1.3.2 GPT-2 微调
我们 DeepSpeedExamples 仓库 中的 data_efficiency/gpt_finetuning
目录包含了我们如何将课程学习应用于 GPT-2 微调的示例。 data_efficiency/gpt_finetuning/finetune/ds_finetune_gpt2_run.sh
是示例微调脚本。对于需要数据分析的 CL 指标(例如,词汇稀有度指标),您需要首先使用 data_efficiency/gpt_finetuning/finetune/ds_analyze_gpt_data_*
分析并索引数据集,类似于上面 1.3.1 中描述的 GPT-3 预训练案例。
2. 随机分层标记丢弃 (random-LTD)
2.1 什么是 random-LTD
Random-LTD 是一种应用于每一层的有效 token 丢弃方法,并进行随机分配。准确地说,对于每一层,与基线相比,random-LTD 会随机选择一部分 token 并将其馈送到 Transformer 层。之后,我们将 Transformer 层的输出与丢弃的 token 相结合,以恢复完整的序列长度。因此,下一层仍然接收完整的序列,并且可以重复此过程。有关更多技术细节,请阅读 我们的 random-LTD 论文。
2.2 何时使用 random-LTD
当您想要预训练/微调基于 Transformer 的模型时,尝试使用 random-LTD 始终是一个好主意,因为它可以在相同计算成本下实现比标准基线训练更好的性能。如果您资源有限,random-LTD 可以用最多 33.3% 的理论成本节省和最多 25.6% 的实际运行时间节省来达到与原始基线方法类似的准确率。特别是,如果您需要训练一个更大的模型(具有 >=24 层和 >=2048 序列长度),我们的方法将比基线方法效率更高。
2.3 如何使用 random-LTD
2.3.1 GPT-3 和 BERT 预训练
我们 Megatron-DeepSpeed 仓库 中的 examples_deepspeed/data_efficiency
目录包含了我们如何将 random-LTD 应用于 GPT-3 和 BERT 预训练的示例。
examples_deepspeed/data_efficiency/gpt/pretrain
和 examples_deepspeed/data_efficiency/bert/pretrain
包含了带有 random-LTD 功能的示例预训练脚本。启用预训练期间的 random-LTD 需要进行一些更改:(1) 用户需要提供一个包含 random-LTD 配置的 DeepSpeed json 配置文件(有关详细信息,请参阅 配置列表)。我们在 examples_deepspeed/data_efficiency/gpt/pretrain/ds_pretrain_gpt_1.3B_dense_run.sh
和 examples_deepspeed/data_efficiency/bert/pretrain/ds_pretrain_bert_336M_run.sh
中提供了经过测试的示例配置。(2) 通过 deepspeed.initialize
初始化 DeepSpeed 引擎后,用户需要使用 convert_to_random_ltd
API 转换和包装模型层以启用 random-LTD 功能。我们在 megatron/training.py
函数 setup_model_and_optimizer
中提供了此更改的示例实现。(3) 为了让 random-LTD 理解前向函数的输入参数映射,用户需要将所有输入参数(除了 hidden_states 输入)更改为关键字/命名参数。例如,在 megatron/model/transformer.py
中,我们将前向函数从 def forward(self, hidden_states, attention_mask, encoder_output=None, enc_dec_attn_mask=None, layer_past=None, get_key_value=False):
更改为 def forward(self, hidden_states, attention_mask=None, encoder_output=None, enc_dec_attn_mask=None, layer_past=None, get_key_value=False):
。(4) 保存模型检查点时(特别是如果状态字典具有非传统结构),用户需要使用 remove_random_ltd_state_dict
API 将 random-LTD 包装的层转换回原始模型层。我们在 megatron/model/language_model.py
中提供了此更改的示例实现。
有关预训练模型的评估/微调,请参阅 上一节,了解如何使用我们的示例脚本。
2.3.2 GPT-2 和 ViT 微调
我们 DeepSpeedExamples 仓库 中的 data_efficiency
目录包含了我们如何将 random-LTD 应用于 GPT-2 和 ViT 微调的示例。
就像预训练案例一样,启用微调的 random-LTD 也需要类似的更改:(1) DeepSpeed json 配置文件。(2) 使用 convert_to_random_ltd
API 转换和包装模型层。(3) 保存模型检查点时,使用 remove_random_ltd_state_dict
API 将 random-LTD 包装的层转换回原始模型层。
您可以通过以下方式运行我们的 GPT 微调示例:
DeepSpeedExamples/data_efficiency/gpt_finetuning$ pip install -r requirement.txt
DeepSpeedExamples/data_efficiency/gpt_finetuning$ bash ./bash_script/run_base_random_ltd.sh
DeepSpeedExamples/data_efficiency/gpt_finetuning$ bash ./bash_script/run_medium_random_ltd.sh
参考最终结果为:
For run_base_random_ltd.sh:
End of training epoch 3 step 1344 consumed_token 2148032 best perplexity 22.552324221233757 time 0.17486039188173083 hr
For run_medium_random_ltd.sh:
End of training epoch 3 step 1373 consumed_token 2147024 best perplexity 17.332243199130996 time 0.4661190489927928 hr
您可以通过以下方式运行我们的 ViT 微调示例:
DeepSpeedExamples/data_efficiency/vit_finetuning$ pip install -r requirement.txt
DeepSpeedExamples/data_efficiency/vit_finetuning$ bash ./bash_script/run_cifar.sh
DeepSpeedExamples/data_efficiency/vit_finetuning$ bash ./bash_script/run_imagenet.sh
参考最终结果为:
For run_cifar.sh:
13 epoch at time 480.6546013355255s | reserved_length 197
iter 5474 | LR [0.0001]| val_acc 97.97000122070312 | layer_token 305784192
3. 组合课程学习和 random-LTD 以实现更多
3.1 GPT-3 和 BERT 预训练
我们 Megatron-DeepSpeed 仓库 中的 examples_deepspeed/data_efficiency
目录包含了我们如何组合课程学习和 random-LTD,并将它们都应用于 GPT-3 和 BERT 预训练的示例。
所需的更改与前面两节中描述的相同,因为 DeepSpeed 数据效率已经处理了组合这两种技术的复杂性。但是,需要注意的是,由于 random-LTD 和一些课程学习指标都会改变序列长度,因此可能需要一些额外的代码来计算每一步的有效序列长度。我们在 megatron/training.py
函数 train
中提供了此更改的示例实现,我们在这里计算了 actual_seq_length
。
3.2 GPT-2 微调
我们 DeepSpeedExamples 仓库 中的 data_efficiency/gpt_finetuning
目录包含了我们如何组合课程学习和 random-LTD 以用于 GPT-2 微调的示例。 data_efficiency/gpt_finetuning/finetune/ds_finetune_gpt2_run.sh
是示例微调脚本。