fsdp_qlora

fsdp_qlora

量化技术实现大型语言模型的高效训练

fsdp_qlora项目结合FSDP与量化LoRA,实现了在有限显存GPU上高效训练大型语言模型。支持HQQ和bitsandbytes的4位量化、LoRA、DoRA等多种策略,大幅降低内存占用。项目提供详细文档,便于快速上手使用。该方法使在消费级GPU上训练70B参数模型成为可能,为大模型研究提供了实用工具。

FSDPQLoRALLM微调量化Github开源项目

fsdp_qlora

使用量化LoRA + FSDP训练大语言模型。

阅读我们的公告博客文章

你应该将此脚本视为alpha/预览版本。如果你不熟悉测试和调试模型,我们建议再等几个月,让社区更充分地测试这种方法。

集成

FSDP+QLoRA已集成到:

安装

以下步骤应该可以正常工作(在Cuda 11.7、11.8和12.1上测试通过):

  • 克隆 https://github.com/AnswerDotAI/fsdp_qlora
  • pip install llama-recipes fastcore "transformers!=4.38.*,!=4.39.*" --extra-index-url https://download.pytorch.org/whl/test/cu118 作为获取大多数依赖项的简单方法(将118替换为你所需的Cuda版本)
  • 安装bitsandbytes pip install bitsandbytes>=0.43.0
  • 运行 huggingface-cli login (访问Llama 2)
  • 可选库:
    • HQQ量化: 按照HQQ安装说明进行操作。我们的训练脚本使用 HQQBackend.ATEN_BACKPROP,所以还要确保构建自定义内核 cd hqq/kernels && python setup_cuda.py install
    • Weights and Biases日志记录: pip install wandb
  • 推荐使用Pytorch >= 2.2以利用原生flash-attention 2内核。

在双24GB GPU上微调Llama-2 70B

安装完成后,运行 cd fsdp_qlora,然后运行以下命令,开始在最大序列长度为512个token的Alpaca数据集上微调Llama-2 70B。

python train.py \ --model_name meta-llama/Llama-2-70b-hf \ --batch_size 2 \ --context_length 512 \ --precision bf16 \ --train_type qlora \ --use_gradient_checkpointing true \ --use_cpu_offload true \ --dataset alpaca \ --reentrant_checkpointing true

这个示例命令目前使用略超过128GB的CPU RAM。如果你只有128GB可用,我们建议创建一个10-20GB的交换文件以适应初始的使用峰值。

训练选项

对于量化,我们支持HQQ和bitsandbytes。我们目前正在进行基准测试,以帮助你决定使用哪一个。如果你使用bitsandbytes,请确保传递 --reentrant_checkpointing True 以避免触发bitsandbytes中导致高内存使用的bug(修复正在进行中)。

--train_type full

全参数微调。

export CUDA_VISIBLE_DEVICES=4,5 # 可选设置设备 python train.py \ --world_size 2 \ # 可选,在单机上会自动设置 --master_port 12356 \ # 可选,默认为12355 --model_name meta-llama/Llama-2-7b-hf \ --gradient_accumulation_steps 4 \ --batch_size 8 \ --context_length 512 \ --precision bf16 \ --train_type full \ --use_gradient_checkpointing true \ --use_cpu_offload false \ --use_activation_cpu_offload false \ --log_to wandb \ --dataset alpaca

--train_type lora

使用HF PEFT库进行LoRA微调。

- --train_type full \ + --train_type lora \

--train_type custom_lora

使用自定义LoRA模块进行LoRA微调。

- --train_type full \ + --train_type custom_lora \

--train_type qlora

使用bitsanbytes Linear4bit层(NF4量化)和HF PEFT库进行4位量化LoRA微调。

- --train_type full \ + --train_type qlora \ + --reentrant_checkpointing true \

--train_type custom_qlora

使用bitsanbytes Linear4bit层(NF4量化)和自定义LoRA模块进行4位量化LoRA微调。

- --train_type full \ + --train_type custom_qlora \ + --reentrant_checkpointing true \

--train_type hqq_lora

使用HQQ库和自定义LoRA模块进行4位量化LoRA微调。

- --train_type full \ + --train_type hqq_lora \

--train_type bnb_dora

使用bitsanbytes Linear4bit层(NF4量化)和自定义DoRA模块进行4位量化DoRA微调。

- --train_type full \ + --train_type bnb_dora \

--train_type hqq_dora

使用HQQ库和自定义DoRA模块进行4位量化DoRA微调。

- --train_type full \ + --train_type hqq_dora \

--train_type bnb_llama_pro

使用bitsanbytes Linear4bit层(NF4量化)进行4位量化Llama-Pro微调。

要创建llama-pro权重,运行以下命令:

python scripts/block_expansion.py \ --model_name meta-llama/Llama-2-7b-hf \ --output_dir /path/to/llama_pro_weights_directory \ --expansion_rate 0.1
- --train_type full \ + --train_type bnb_llama_pro \ + --llama_pro_path /path/to/llama_pro_weights_directory \

--train_type hqq_llama_pro

使用HQQ库进行4位量化Llama-Pro微调。

要创建llama-pro权重,运行以下命令:

python scripts/block_expansion.py \ --model_name meta-llama/Llama-2-7b-hf \ --output_dir /path/to/llama_pro_weights_directory \ --expansion_rate 0.1
- --train_type full \ + --train_type hqq_llama_pro \ + --llama_pro_path /path/to/llama_pro_weights_directory \

低内存加载

在量化LoRA训练期间,我们使用自定义量化和加载代码,以避免在将整个模型分片到多个GPU之前将其完全加载到GPU内存中。当使用以下任何训练选项 "qlora", "custom_qlora", "hqq_lora" 时,这是我们训练脚本的默认行为。其他训练选项已经在最大程度上针对低内存加载进行了优化。

我们迭代加载权重,在GPU上对其进行量化,并根据其等级将其放回CPU或meta设备,同时每次处理几个层。我们在所有GPU上执行此操作以初始化量化参数(如零点和缩放因子),同时在FSDP初始化期间使用 sync_module_states=True 来同步所有GPU上的模型参数和缓冲区。

混合精度训练

--precision bf16 (纯bfloat16)

这将在训练前将所有模型参数转换为 torch.bfloat16,并且不会使用FSDP混合精度。因此,分片和未分片的参数将以bf16存储,前向和后向传递将以bf16进行,梯度归约和更新也将以bf16进行。

--precision fp32 (纯float32)

这将在训练前将所有模型参数转换为 torch.float32,并且不会使用FSDP混合精度。因此,分片和未分片的参数将以fp32存储,前向和后向传递将以fp32进行,梯度归约和更新也将以fp32进行。

--precision mp_fp16_autocast (带自动转换的混合float16)

这将在训练前将所有模型参数转换为 torch.float32,并使用FSDP混合精度,配置如下:

mp_policy = MixedPrecision(param_dtype=torch.float32, reduce_dtype=torch.float32, buffer_dtype=torch.float32)

因此,分片和未分片的参数将以fp32存储。它将使用 autocast(torch.float16) 进行前向和后向传递,以及梯度归约和更新。

--precision mp_bf16_autocast (带自动转换的混合bfloat16)

这将在训练前将所有模型参数转换为 torch.float32,并使用FSDP混合精度,配置如下:

mp_policy = MixedPrecision(param_dtype=torch.float32, reduce_dtype=torch.float32, buffer_dtype=torch.float32)

因此,分片和未分片的参数将以fp32存储。它将使用 autocast(torch.bfloat16) 进行前向和后向传递,以及梯度归约和更新。

--precision mp_bf16_buffers_autocast (bfloat16参数和float32缓冲区,带自动转换)

这将在训练前将所有模型参数转换为 torch.bfloat16,但将缓冲区保持在 torch.float32,并使用FSDP混合精度,配置如下:

mp_policy = MixedPrecision(param_dtype=torch.bfloat16, reduce_dtype=torch.bfloat16, buffer_dtype=torch.float32)

因此,分片和未分片的参数将以bf16存储。它将使用 autocast(torch.bfloat16) 进行前向和后向传递,以及梯度归约和更新。缓冲区和自动转换中的符合条件的操作将以bf16执行。

这个选项对RoPE层很重要,因为当转换为较低精度时,特别是在较长的上下文长度下,RoPE层会给出不正确的结果。

与现有训练器的比较

Screenshot 2024-02-01 083222 hf_train.py使用TRL的SFTTrainer进行对比运行。为了与我们的脚本匹配,修改数据加载代码以训练所有内容(不仅仅是完成部分),然后运行train.py --train_type qlora --dataset guanaco --batch_size 8 --lr_scheduler cosine --log_to wandb --save_model True --output_dir guanaco_7B --gradient_accumulation_steps 2 --lr 2e-4。SFTTrainer版本必须以较低的批量大小运行(4而不是8),所以我们只进行2个梯度累积步骤,而QLoRA+FSDP版本是4个。

转换保存的模型

如果指定--save_model True,适配器层将被保存为状态字典。要转换为常规的Hugging Face格式并上传到hub,请参见:Converting the State Dict.ipynb

如果使用"custom_qlora", "hqq_lora"训练选项,则只会保存可训练的LoRA参数。在推理之前,你需要再次加载和量化基础模型,并单独加载保存的LoRA参数。

你也可以尝试将基础模型权重与训练后的LoRA权重合并后再量化,看看是否与训练期间分开保存参数的效果相似。要在HQQ中使用torch.compile,请参见https://github.com/mobiusml/hqq/issues/18。

限制

虽然QLoRA微调与FSDP兼容,但这个alpha版本和我们的示例脚本还存在一些不完善之处。

首先,当前版本的Transformer AutoModel.from_pretrained不能用于将模型加载到量化权重中,因为它不支持新的quant_storage或quantization标志。加载预训练模型需要编写或使用自定义的模型加载代码。我们在演示脚本中提供了如何加载和量化QLoRA模型以进行微调的示例。

我们正在与Hugging Face积极合作,以在未来的Transformers和PEFT版本中解决这个不兼容问题。

其次,虽然FSDP的混合精度与QLoRA兼容,但实践者需要小心设置MixedPrecision.param_type以匹配Linear4Bit.quant_storage的dtype。否则,FSDP的混合精度可能会将量化权重转换为不同的精度,实际上将它们变成随机权重。我们的示例脚本展示了如何避免这个潜在的陷阱,我们也很乐意协助模型训练库在使用QLoRA训练时正确地向用户公开FSDP的混合精度选项。

示例:Llama 70B 4-A100 40GB训练

# BnB QLoRA export CUDA_VISIBLE_DEVICES=4,5,6,7 python train.py \ --world_size 4 \ --master_port 12356 \ --model_name meta-llama/Llama-2-70b-hf \ --gradient_accumulation_steps 4 \ --batch_size 2 \ --context_length 512 \ --precision bf16_buffers_autocast \ --train_type custom_qlora \ --use_gradient_checkpointing true \ --reentrant_checkpointing true --use_cpu_offload false \ --log_to stdout \ --dataset alpaca # HQQ QLoRA export CUDA_VISIBLE_DEVICES=4,5,6,7 python train.py \ --world_size 4 \ --master_port 12356 \ --model_name meta-llama/Llama-2-70b-hf \ --gradient_accumulation_steps 4 \ --batch_size 2 \ --context_length 512 \ --precision bf16_buffers_autocast \ --train_type hqq_lora \ --use_gradient_checkpointing true \ --use_cpu_offload false \ --log_to stdout \ --dataset alpaca

**注意:**对于大批量或长上下文训练,HQQ LoRA比使用重入检查点的BnB LoRA略微更节省内存。因此,如果遇到OOM问题,可以尝试使用HQQ LoRA。

SLURM训练

查看fsdp_multi_node.sh以获取使用SLURM进行多节点训练的示例训练脚本。

添加对新模型的支持

首先,从Transformers导入新模型的transformer、attention和MLP层:

from transformers.models.mistral.modeling_mistral import MistralDecoderLayer, MISTRAL_ATTENTION_CLASSES, MistralMLP

然后在get_wrapping_policy函数中,将attention、MLP和transformer层添加到self_attn_policy_fnmlp_policy_fntransformer_wrap_policy包装策略方法中:

def get_wrapping_policy(custom_policy:bool=False): def self_attn_policy_fn(module): return isinstance(module, tuple(*LLAMA_ATTENTION_CLASSES.values(), *MISTRAL_ATTENTION_CLASSES.values())) def mlp_policy_fn(module): return isinstance(module, (LlamaMLP, MistralMLP)) transformer_wrap_policy = functools.partial( transformer_auto_wrap_policy, transformer_layer_cls=(LlamaDecoderLayer, MistralDecoderLayer), )

最后,通过将transformer层添加到check_fn中来添加梯度检查点支持:

if args["use_gradient_checkpointing"]: check_fn = lambda submodule: isinstance(submodule, (LlamaDecoderLayer, MistralDecoderLayer))

编辑推荐精选

扣子-AI办公

扣子-AI办公

职场AI,就用扣子

AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!

堆友

堆友

多风格AI绘画神器

堆友平台由阿里巴巴设计团队创建,作为一款AI驱动的设计工具,专为设计师提供一站式增长服务。功能覆盖海量3D素材、AI绘画、实时渲染以及专业抠图,显著提升设计品质和效率。平台不仅提供工具,还是一个促进创意交流和个人发展的空间,界面友好,适合所有级别的设计师和创意工作者。

图像生成AI工具AI反应堆AI工具箱AI绘画GOAI艺术字堆友相机AI图像热门
码上飞

码上飞

零代码AI应用开发平台

零代码AI应用开发平台,用户只需一句话简单描述需求,AI能自动生成小程序、APP或H5网页应用,无需编写代码。

Vora

Vora

免费创建高清无水印Sora视频

Vora是一个免费创建高清无水印Sora视频的AI工具

Refly.AI

Refly.AI

最适合小白的AI自动化工作流平台

无需编码,轻松生成可复用、可变现的AI自动化工作流

酷表ChatExcel

酷表ChatExcel

大模型驱动的Excel数据处理工具

基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。

AI工具酷表ChatExcelAI智能客服AI营销产品使用教程
TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
AIWritePaper论文写作

AIWritePaper论文写作

AI论文写作指导平台

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

AI辅助写作AI工具AI论文工具论文写作智能生成大纲数据安全AI助手热门
博思AIPPT

博思AIPPT

AI一键生成PPT,就用博思AIPPT!

博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。

AI办公办公工具AI工具博思AIPPTAI生成PPT智能排版海量精品模板AI创作热门
潮际好麦

潮际好麦

AI赋能电商视觉革命,一站式智能商拍平台

潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。

下拉加载更多