重要
您正在查看 NeMo 2.0 文档。此版本对 API 和新的库 NeMo Run 进行了重大更改。我们目前正在将 NeMo 1.0 中的所有功能移植到 2.0。有关先前版本或 2.0 中尚不可用的功能的文档,请参阅 NeMo 24.07 文档。
NeMo 2.0 中的 PEFT#
模型定制#
定制模型使您能够将通用的预训练 LLM 适配到特定的用例或领域。此过程产生一个微调模型,该模型受益于广泛的预训练数据,同时为特定的下游任务产生更准确的输出。模型定制通过监督微调实现,并分为两个流行的类别
全参数微调,在 NeMo 中称为监督微调 (SFT)
参数高效微调 (PEFT)
在 SFT 中,所有模型参数都会更新,以产生适应任务的输出。
另一方面,PEFT 调整的参数数量要少得多,这些参数被插入到基础模型中的策略位置。当使用 PEFT 进行微调时,基础模型权重保持冻结,并且仅训练适配器模块。因此,可训练参数的数量显着减少,通常少于 1%。
虽然 SFT 通常产生最佳结果,但 PEFT 方法通常可以达到几乎相同的精度,同时显着降低计算成本。随着语言模型尺寸的持续增长,PEFT 因其对训练硬件的轻量级要求而越来越受欢迎。
NeMo 2.0 支持 SFT 和两种 PEFT 方法,这些方法可以与各种基于 Transformer 的模型一起使用。
SFT |
LoRA |
DoRA |
|
---|---|---|---|
Baichuan 2 7B |
✅ |
✅ |
✅ |
ChatGLM 3 6B |
✅ |
✅ |
✅ |
Gemma 2B/7B |
✅ |
✅ |
✅ |
Gemma 2 9B/27B |
✅ |
✅ |
✅ |
Llama 3 8B/70B |
✅ |
✅ |
✅ |
Llama 3.1 8B/70B/405B |
✅ |
✅ |
✅ |
Mistral 7B |
✅ |
✅ |
✅ |
Mixtral 8x7B/8x22B |
✅ |
✅ |
✅ |
Nemotron 3 4B/8B |
✅ |
✅ |
✅ |
Nemotron 4 15B/22B/340B |
✅ |
✅ |
✅ |
Qwen 2 0.5B/1.5B/7B/72B |
✅ |
✅ |
✅ |
Starcoder 15B |
✅ |
✅ |
✅ |
Starcoder 2 3B/7B/15B |
✅ |
✅ |
✅ |
在此处阅读有关支持的 PEFT 方法的更多信息
在 NeMo 2.0 中运行 PEFT 训练#
以下是使用 NeMo 2.0 运行 Llama 3.2 1B 模型的简单 PEFT 训练循环的三个示例。这些示例展示了 NeMo 框架提供的不同抽象级别。一旦您按照 安装 NeMo 框架 中的说明设置好环境,您就可以运行简单的 PEFT 调整脚本。
运行 PEFT 训练的最简单方法是使用配方文件。您可以在 此处 找到支持的模型列表及其预定义的配方。
注意
先决条件:在继续之前,请按照 NeMo-Run 快速入门 中的示例,首先熟悉 NeMo-Run。
from nemo.collections import llm
import nemo_run as run
nodes = 1
gpus_per_node = 1
recipe = llm.llama32_1b.finetune_recipe(
dir="/checkpoints/llama3.2_1b", # Path to store checkpoints
name="llama3_lora",
num_nodes=nodes,
num_gpus_per_node=gpus_per_node,
peft_scheme="lora",
)
# Note: "lora" is the default peft_scheme.
# Supported values are "lora", "dora", "none"/None (full fine-tuning)
# Override your PEFT configuration here, if needed. For example:
recipe.peft.target_modules = ["linear_qkv", "linear_proj", "linear_fc1", "linear_fc2"]
recipe.peft.dim = 16
recipe.peft.alpha = 32
# Add other overrides here
...
run.run(recipe)
您可以通过 NeMo Run CLI 使用 PEFT 配方(有关更多详细信息,请参见 此处)。LoRA 和 DoRA 注册为工厂类,因此您可以在终端中直接指定 peft=<lora/dora/none>
。当您不需要覆盖默认配方中的任何配置时,这提供了一种快速简便的启动训练作业的方法。
nemo llm finetune -f llama32_1b peft=lora # acceptable values are lora/dora/none
此示例使用 NeMo 框架 LLM 集合中的 finetune API。这是一个较低级别的 API,允许您以 Pythonic 方式布置各种配置。这使您可以最大程度地控制每个配置。
import torch
from nemo import lightning as nl
from nemo.collections import llm
from megatron.core.optimizer import OptimizerConfig
if __name__ == "__main__":
seq_length = 2048
global_batch_size = 16
## setup a finetuning dataset
data = llm.DollyDataModule(
seq_length=seq_length,
global_batch_size=global_batch_size
)
## initialize a small Llama model
llama_config = llm.Llama32Config1B()
model = llm.LlamaModel(llama_config, tokenizer=data.tokenizer)
## initialize the strategy
strategy = nl.MegatronStrategy(
tensor_model_parallel_size=1,
pipeline_model_parallel_size=1,
pipeline_dtype=torch.bfloat16,
)
## setup the optimizer
opt_config = OptimizerConfig(
optimizer='adam',
lr=1e-4,
bf16=True,
)
opt = nl.MegatronOptimizerModule(config=opt_config)
trainer = nl.Trainer(
devices=1, ## you can change the number of devices to suit your setup
max_steps=50,
accelerator="gpu",
strategy=strategy,
plugins=nl.MegatronMixedPrecision(precision="bf16-mixed"),
)
nemo_logger = nl.NeMoLogger(
log_dir="test_logdir", ## logs and checkpoints will be written here
)
peft = llm.peft.LoRA(dim=8, alpha=16)
resume = nl.AutoResume(
restore_config=nl.RestoreConfig(path="nemo://meta-llama/Llama-3.2-1B"),
)
# only need to import the first time script is run
llm.import_ckpt(model, "hf://meta-llama/Llama-3.2-1B")
llm.finetune(
model=model,
data=data,
trainer=trainer,
peft=peft,
log=nemo_logger,
optim=opt,
resume=resume,
)
在 NeMo 2.0 中运行 PEFT 推理#
llm.generate
API 原生支持使用适配器进行推理。只需将完整模型的路径替换为 PEFT 检查点的路径即可。NeMo 将从检查点推断运行推理所需的所有信息,包括模型类型、适配器类型、基础模型检查点路径等。有关更多详细信息,请参见 llm.generate API。
以下是一个示例脚本
from megatron.core.inference.common_inference_params import CommonInferenceParams
import nemo.lightning as nl
from nemo.collections.llm import api
strategy = nl.MegatronStrategy(
tensor_model_parallel_size=1,
pipeline_model_parallel_size=1,
context_parallel_size=1,
sequence_parallel=False,
setup_optimizers=False,
)
trainer = nl.Trainer(
accelerator="gpu",
devices=1,
num_nodes=1,
strategy=strategy,
plugins=nl.MegatronMixedPrecision(
precision="bf16-mixed",
params_dtype=torch.bfloat16,
pipeline_dtype=torch.bfloat16,
),
)
prompts = [
"Hello, how are you?",
"How many r's are in the word 'strawberry'?",
"Which number is bigger? 10.119 or 10.19?",
]
if __name__ == "__main__":
adapter_checkpoint = "/path/to/nemo_ckpt" # a folder that contains "weights" and "context" subfolders
results = api.generate(
path=adapter_checkpoint,
prompts=prompts,
trainer=trainer,
inference_params=CommonInferenceParams(temperature=0.1, top_k=10, num_tokens_to_generate=512),
text_only=True,
)
提示
适配器检查点仅包含适配器权重,而不包含基础模型权重。那么为什么我们不需要提供基础模型的路径呢?
这是因为适配器检查点还包含对其训练所用基础模型路径的引用。每个适配器检查点都必须与其训练所用的精确基础模型配对,因此对其的引用与适配器权重一起存储在 weights/adapter_metadata.json
中。
因此,如果您在不同的文件系统上与某人共享适配器检查点,则必须确保接收者将 weights/adapter_metadata.json
更新为其文件系统上的有效路径。
提示
根据模型的大小,您可能需要调整 tensor_model_parallel_size
、pipeline_model_parallel_size
、num_devices
和 num_nodes
。如果您不确定要设置什么并行配置,则该模型的 PEFT 训练配方将提供一个良好的上限。请参见 此处 以获取配方列表。
将 LoRA 权重与基础模型合并#
当您想要在不更改模型架构的情况下运行 PEFT 推理时,我们也支持将训练后的 LoRA 权重合并回基础模型。llm.peft.merge_lora
API 支持此功能。
from nemo.collections import llm
if __name__ == '__main__':
llm.peft.merge_lora(
lora_checkpoint_path="path/to/lora_checkpoint",
output_path="path/to/merged_checkpoint",
)
将 LoRA 权重导出到 Hugging Face#
llm.export_ckpt
API 支持导出 LoRA 检查点,前提是为模型实现了 PEFT 导出器 (hf-peft
)。要为自己的模型类实现 PEFT 导出器,请按照 Llama 中的示例进行操作。
from nemo.collections import llm
if __name__ == '__main__':
llm.export_ckpt(
path=Path("path/to/lora_checkpoint"),
target="hf-peft",
output_path=Path("path/to/output_HF_checkpoint"),
)
请注意,Hugging Face 实现等效于 NeMo 的 CanonicalLoRA
,而不是 LoRA
。但是两者都可以转换为 Hugging Face 实现。在此处阅读有关差异的更多信息
探索 NeMo 2.0 中的 PEFT 设计#
如果您正在为 NeMo PEFT 开发,我们邀请您在此处阅读有关 NeMo 2.0 中 PEFT 设计的更多信息: 此处。