24年3月来自北航和北大的论文“LLAMA-FACTORY: Unified Efficient Fine-Tuning of 100+ Language Models”。
高效的微调对于将大语言模型 (LLM) 适应下游任务至关重要。然而,在不同模型上实施这些方法需要付出不小的努力。LLAMA-FACTORY是一个集成一套高效训练方法的统一框架。它允许用户通过内置的 Web UI LLAMA-BOARD 灵活地自定义 100 多个 LLM 的微调,无需编码。经验验证该框架在语言建模和文本生成任务上的效率和有效性。
开源发布在
GitHub - hiyouga/LLaMA-Factory: Unify Efficient Fine-Tuning of 100+ LLMs
LLAMA-FACTORY是一个使 LLM 微调民主化的框架。它通过可扩展的模块统一了各种高效的微调方法,从而能够以最少的资源和高吞吐量对数百个 LLM 进行微调。此外,它还简化了常用的训练方法,包括生成式预训练(Radford,2018)、监督微调 (SFT)(Wei,2022)、人类反馈中强化学习 (RLHF)(Ouyang,2022)和直接偏好优化 (DPO)(Rafailov,2023)。用户可以利用命令行或 Web 界面以最少或无需编码工作量来定制和微调LLM。
下表是其和现存LLM调优工具的特征比较:
LLAMA-FACTORY 由三个主要模块组成:
模型加载器、数据工作器和训练器。
尽量减少这些模块对特定模型和数据集的依赖,使框架能够灵活地扩展到数百个模型和数据集。
具体来说,首先建立一个模型注册表,模型加载器可以通过识别精确的层将适配器精确地连接到预训练模型。
然后,开发一个数据描述规范,允许数据工作器通过对齐相应的列来收集数据集。
此外,提供高效微调方法的即插即用实现,使训练器能够通过替换默认方法激活。
允许这些模块在不同的训练方法中重复使用,从而显著降低新方法的集成成本。
下表是支持的LLM清单:
LLAMA-FACTORY 是用 PyTorch(Paszke,2019)实现的,并且从开源库中获益良多,例如 Transformers(Wolf,2020)、PEFT(Mangrulkar,2022)和 TRL(von Werra,2020)。
在此基础上,提供一个具有更高抽象级的开箱即用框架。
此外,用 Gradio(Abid,2019)构建 LLAMA-BOARD,无需编码即可微调 LLM。
高效的 LLM 微调技术可分为两大类:专注于优化和面向计算。高效优化技术的主要目标是调整 LLM 参数,同时将成本保持在最低水平。另一方面,高效的计算方法则力求减少 LLM 中所需计算的时间或空间。LLAMA-FACTORY 中包含的方法列于下表中。
冻结调整方法 (Houlsby,2019) 涉及冻结大多数参数,同时在一小部分解码器层中微调剩余参数。
另一种称为梯度低秩投影 (GaLoRA) (Zhao,2024) 的方法将梯度投影到低维空间,以节省内存的方式促进全参数学习。
相反,低秩自适应 (LoRA) (Hu,2022) 方法冻结所有预训练权重,并将一对可训练的低秩矩阵引入指定层。
当与量化结合时,这种方法称为 QLoRA (Dettmers,2023),这进一步减少了内存使用量。
权重分解低秩自适应 (DoRA) (Liu et al., 2024) 方法将预训练权重分解为绝对值和方向分量,将 LoRA 单独应用于方向分量以增强 LLM 的微调。
LoRA+ (Hayou et al., 2024) 提出来是为了克服 LoRA 的次优性。
在 LLAMA-FACTORY 中,集成了一系列高效的计算技术。常用的技术包括混合精度训练(Micikevicius,2018)和激活检查点(Chen,2016)。从检查注意层的输入输出 (IO) 开销中汲取见解,flash attention(Dao,2022 年)引入一种硬件友好的方法来增强注意计算。S^2 attention(Chen,2024b)解决了在块稀疏注意中扩展上下文的挑战,从而减少了微调长上下文 LLM 中的内存使用量。
各种量化策略(Dettmers,2022a;Frantar,2023;Lin,2023;Egiazarian,2024)用较低精度的权重表示来降低大语言模型 (LLM) 中的内存需求。尽管如此,量化模型的微调仅限于基于适配器的技术,例如 LoRA(Hu,2022)。Unsloth(Han & Han,2023)结合 Triton(Tillet,2019)来实现 LoRA 的后向传播,从而减少梯度下降过程中的浮点运算 (FLOPS) 并加快 LoRA 训练。
LLAMA-FACTORY 有效地将这些技术组合成一个凝聚的结构,大大提高 LLM 微调的效率。这使得内存占用从混合精度训练期间的18 字节/参数(Micikevicius,2018)或 Bfloat16 训练期间的 8 字节/参数(Le Scao,2022)减少到 0.6 字节/参数。
在LLAMA-FACTORY 中, 模型加载器准备了各种用于微调的架构,支持 100 多个 LLM。数据工作器通过精心设计的流水线处理来自不同任务的数据,支持 50 多个数据集。训练器统一了有效的微调方法,使这些模型适应不同的任务和数据集,提供四种训练方法。LLAMA-BOARD 为上述模块提供了友好的可视化界面,使用户能够以无代码的方式配置和启动单个 LLM 微调过程,并实时监控训练状态。如图说明 LLAMA-FACTORY 的整体架构。
模型加载器
有四个组件:模型初始化、模型补丁、模型量化和适配器连接。
模型初始化
。用 HF Transformers 的 AutoModel API(Wolf,2020)来加载模型和初始化参数。为了使框架与不同的模型架构兼容,建立了一个模型注册表来存储每个层的类型,从而更直接地促进高效微调技术的使用。如果token化器的词汇表大小超出了嵌入层的容量,会调整层的大小并使用噪声均值初始方法来初始化新参数。为了确定 RoPE 的缩放因子(Chen,2023),将其取做最大输入序列长度与模型的上下文长度之比。
模型补丁
。为了启用 flash attention 和 S^2 attention,用 monkey patch 来代替模型的前向计算。不过,由于自 HF Transformers 4.34.0 以来就支持 flash attention,用 API 来启用 flash attention。为了防止动态模块过度分区,在 DeepSpeed ZeRO-3 (Rasley et al., 2020) 优化时将混合专家 (MoE) 块设置为叶(Leaf)模块。
模型量化
。可以通过 bits-and-bytes 库 (Dettmers, 2021) 用 LLM.int8 (Dettmers et al., 2022a) 将模型动态量化为 8 位或 4 位。对于 4 位量化,用双量化和 4 位普通浮点作为 QLoRA (Dettmers et al., 2023)。还支持训练后量化 (PTQ) 方法量化的模型微调,包括 GPTQ (Frantar,2023)、AWQ (Lin,2023) 和 AQLM (Egiazarian,2024)。请注意,无法直接微调量化权重;因此,量化模型仅与基于适配器的方法兼容。
适配器附加
。用模型注册表自动识别适当的层来附加适配器。适配器默认附加到一个层的子集以节省内存,但将它们附加到所有线性层可能会产生更好的性能 (Dettmers,2023)。
PEFT
(Mangrulkar et al., 2022) 库提供了一种非常方便的方式来连接适配器,例如 LoRA (Hu et al., 2022)、rsLoRA (Kalajdzievski, 2023) 和 DoRA (Liu et al., 2024)。替换后向计算为Unsloth (Han & Han, 2023) 的版本加速 LoRA。为了执行人类反馈中强化学习 (RLHF) ,在模型上添加了一个V头,这是一个将每个 token 的表示映射到标量的线性层。
精度适应
。根据设备的功能处理预训练模型的浮点精度。对于 NVIDIA GPU,如果计算能力为 8.0 或更高,使用 bfloat16 精度。否则,采用 float16。对 Ascend NPU 和 AMD GPU 使用 float16,对非 CUDA 设备使用 float32。请注意,用 float16 精度加载 bfloat16 模型可能会导致溢出问题。在混合精度训练中,将所有可训练参数设置为 float32。尽管如此,在 bfloat16 训练中将可训练参数保留为 bfloat16。
一个数据处理流水线包括数据集加载、数据集对齐、数据集合并和数据集预处理。它将不同任务的数据集标准化为统一的格式,能够在各种格式的数据集上微调模型。
数据集加载
。用数据集(Lhoest,2021)库来加载数据,这使用户可以从 Hugging Face Hub 加载远程数据集或通过脚本或文件读取本地数据集。数据集库显着减少数据处理过程中的内存开销,并加速了用 Arrow(Apache,2016)的样本查询。默认情况下,整个数据集会下载到本地磁盘。但是,如果数据集太大而无法存储,框架提供数据集流动对其进行迭代,而无需下载。
数据集对齐
。为了统一数据集格式,设计了一个数据描述规范来表征数据集的结构。例如,Alpaca数据集有三列:指令、输入和输出(Taori,2023)。根据数据描述规范将数据集转换为与各种任务兼容的标准结构。
下表显示了一些数据集结构示例。
数据集合并
。
统一的数据集结构为合并多个数据集提供了一种有效的方法。
对于非流动模式下的数据集,只需在训练期间数据集混洗之前先连接起来。
然而,在流动模式下,简单地连接数据集会阻碍数据混洗。
因此,提供交替读取不同数据集数据的方法。
数据集预处理
。LLAMA-FACTORY 专为微调文本生成模型而设计,主要用于聊天完成。聊天模板是这些模型中的关键组成部分,因为它与这些模型的指令遵循能力高度相关。因此,提供数十种聊天模板,可以根据模型类型自动选择。用token化器在应用聊天模板后对句子进行编码。默认情况下,仅计算完成的损失,而忽略提示(Taori,2023)。或者,利用序列打包(Krell,2021)来减少训练时间,这在执行生成式预训练时会自动启用。
设计了一个 Formatter 类,以便将文本输入稳健地转换为其嵌入 ID。具体来说,提供 EmptyFormatter、StringFormatter、FunctionFormatter 和 ToolFormatter。此外,LLAMA-FACTORY 支持微调模型以获得函数调用能力。虽然 ReAct 提示(Yao,2023)是工具使用的流行选择,但它对于嵌套工具参数来说是不够的。优化的工具调用提示如表所示。
高效训练
。
将最先进的高效微调方法,包括 LoRA+(Hayou,2024)和 GaLore(Zhao,2024),集成到训练器中,替换默认组件。
这些训练方法独立于训练器,因此可以轻松应用于各种任务。
利用 Transformers(Wolf,2020)的训练器进行预训练和 SFT,同时采用 TRL(von Werra,2020)的训练器进行 RLHF 和 DPO。
利用定制的数据整理器来区分各种训练方法的训练器。
为了匹配训练器偏好数据的输入格式,在一个批次中构建 2n 个样本,其中前 n 个样本是选定的示例,后 n 个样本是拒绝的示例。