Skip to content

105.PEFT消费级设备训练模型 ​

来源:语雀原文 | 整理日期:2026-09-22

示例代码 ​

注:将ppt后缀名改为zip后解压

参数高效微调(PEFT)方法在微调过程中冻结预训练模型的参数,并在其顶部添加少量可训练参数(adapters)。adapters 被训练以学习特定任务的信息。这种方法已被证明非常节省内存,同时具有较低的计算使用量,同时产生与完全微调模型相当的结果。

使用 PEFT 训练的 adapters 通常比完整模型小一个数量级,使其方便共享、存储和加载。

与完整尺寸的模型权重(约为 700MB)相比,存储在 Hub 上的 OPTForCausalLM 模型的 adapter 权重仅为~ 6MB。

如果您对学习更多关于🤗 PEFT 库感兴趣,请查看文档。

安装 ​

在开始之前,您需要设置您的环境,安装适当的软件包,并配置 🤗 PEFT。🤗 PEFT 在 Python 3.9+ 版本上进行了测试。

🤗 PEFT 在 PyPI 和 GitHub 上均有提供

PyPI ​

要从 PyPI 安装 🤗 PEFT,请运行:

pip install peft

源代码 ​

尚未发布的新功能每天都会添加,这也意味着可能存在一些错误。要尝试这些新功能,请从 GitHub 仓库安装

pip install git+https://github.com/huggingface/peft

如果您正在为库做贡献,或者希望使用源代码并查看代码运行的实时结果,则可以从本地克隆的仓库版本安装可编辑版本

plain
git clone https://github.com/huggingface/peft
cd peft
pip install -e .[test]

快速入门 ​

PEFT 为微调大型预训练模型提供了参数高效的方法。传统的范式是为每个下游任务微调模型的所有参数,但这正变得极其昂贵且不切实际,因为如今模型中的参数数量庞大。相反,训练少量 prompt 参数或使用像低秩适配 (LoRA) 这样的重参数化方法来减少可训练参数更为有效。

本快速入门将向您展示 PEFT 的主要功能,以及如何在通常在消费级设备上无法访问的大型模型上进行训练或运行推理。

训练 ​

每种 PEFT 方法都由 PeftConfig 类定义,该类存储构建 PeftModel 的所有重要参数。例如,要使用 LoRA 进行训练,请加载并创建 LoraConfig 类,并指定以下参数:

  • task_type:要训练的任务类型(在本例中为序列到序列语言建模)条件生成任务,根据给定的输入(可能是文本、图片等)生成符合条件的输出。
SEQ_CLS ​

序列分类(Sequence Classification),对整个句子进行分类。如: 获取评论的情绪,检测电子邮件是否为垃圾邮件,确定句子在语法上是否正确或两个句子在逻辑上是否相关等

SEQ_2_SEQ_LM ​

条件生成任务,根据给定的输入(可能是文本、图片等)生成符合条件的输出。

与因果语言建模任务不同,条件生成不仅仅关注于给定上下文的连贯性,还关注于满足预定的任务要求。因果语言建模仅关注于根据给定的上下文生成文本序列。

条件生成的应用包括但不限于机器翻译、文本摘要、图像描述等。这些任务通常需要模型在输入和输出之间建立复杂的映射关系。

CAUSAL_LM ​

因果语言建模任务(CLM),在这种建模方法中,模型试图预测给定上下文中的下一个单词,该上下文通常包括在当前单词之前的所有单词。这种建模方法遵循因果原则,即当前单词只受到其前面单词的影响,而不受后面单词的影响。代表模型有 GPT2、Bloom、OPT、GPT-Neo、GPT-J、LLaMA、ChatGLM。

TOKEN_CLS ​

Token 分类任务(Token Classification),对句子中的每个词进行分类。如: 识别句子的语法成分(名词、动词、形容词)或命名实体(人、地点、组织)。

  • inference_mode:是否将模型用于推理
  • r:低秩矩阵的维度
  • lora_alpha:低秩矩阵的缩放因子
  • lora_dropout:LoRA 层的 dropout 概率
plain
from peft import LoraConfig, TaskType

peft_config = LoraConfig(task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1)

请参阅 LoraConfig 参考文档,了解有关您可以调整的其他参数的更多详细信息,例如要定位的模块或偏置类型。

设置好 LoraConfig 后,使用 get_peft_model() 函数创建一个 PeftModel。它接受一个基础模型(您可以从 Transformers 库加载)和包含如何配置模型以使用 LoRA 进行训练的参数的 LoraConfig。

加载您要微调的基础模型。

plain
from transformers import AutoModelForSeq2SeqLM

model = AutoModelForSeq2SeqLM.from_pretrained("bigscience/mt0-small")

使用 get_peft_model() 函数包装基础模型和 peft_config 以创建一个 PeftModel。要了解模型中可训练参数的数量,请使用 print_trainable_parameters 方法。

plain
from peft import get_peft_model

model = get_peft_model(model, peft_config)
model.print_trainable_parameters()
"output: trainable params: 2359296 || all params: 1231940608 || trainable%: 0.19151053100118282"

在 bigscience/mt0-large 的 12 亿参数中,您仅训练了其中的 0.19%!

就是这样 🎉!现在您可以使用 Transformers Trainer、Accelerate 或任何自定义 PyTorch 训练循环来训练模型。

plain
# 开始训练循环,共num_epochs轮
for epoch in range(num_epochs):
    # 设置模型为训练模式,启用dropout等
    model.train()
    # 初始化总损失
    total_loss = 0
    # 遍历训练数据加载器中的每个批次
    for step, batch in enumerate(tqdm(train_dataloader)):
        # 将批次数据移动到设备
        batch = {k: v.to(device) for k, v in batch.items()}
        # 前向传播,计算模型输出
        outputs = model(**batch)
        # 获取损失
        loss = outputs.loss
        # 累加损失
        total_loss += loss.detach().float()
        # 反向传播,计算梯度
        loss.backward()
        # 优化器更新参数
        optimizer.step()
        # 学习率调度器更新学习率
        lr_scheduler.step()
        # 清零梯度,准备下一批次
        optimizer.zero_grad()

将模型、训练参数、数据集、tokenizer 和任何其他必要组件传递给 Trainer,并调用 train 开始训练。

plain
# 获取处理后的训练集和验证集
train_dataset = processed_datasets["train"]
eval_dataset = processed_datasets["validation"]

# 创建训练数据加载器,设置随机打乱、批处理大小等
train_dataloader = DataLoader(
    train_dataset, shuffle=True, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True
)
# 创建验证数据加载器
eval_dataloader = DataLoader(eval_dataset, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True)

保存模型 ​

模型训练完成后,您可以使用 save_pretrained 函数将模型保存到目录中。

model.save_pretrained("output_dir")

您还可以使用 push_to_hub 函数将模型保存到 Hub(请先确保您已登录您的 Hugging Face 帐户)。

plain
# 保存模型
# 创建模型ID,包含基础模型名称、PEFT类型和任务类型
peft_model_id = f"{model_name_or_path}_{peft_config.peft_type}_{peft_config.task_type}"
# 保存模型到指定路径
model.save_pretrained(peft_model_id)


from huggingface_hub import notebook_login
notebook_login()
model.push_to_hub("your-name/bigscience/mt0-small-lora")

这两种方法都只保存训练的额外 PEFT 权重,这意味着存储、传输和加载都非常高效。例如,这个使用 LoRA 训练的 模型仅包含两个文件:adapter_config.json 和 adapter_model.safetensors。adapter_model.safetensors 文件仅有 1.3MB!

存储在 Hub 上的 模型的适配器权重仅约 1.3MB,而完整模型权重的大小可能约为1.1GB。

推理 ​

请查看 AutoPeftModel API 参考文档,获取可用 AutoPeftModel 类的完整列表。

使用 AutoPeftModel 类和 from_pretrained 方法,轻松加载任何 PEFT 训练的模型以进行推理

plain
# 加载保存的模型进行推理
# 导入PEFT模型和配置类
from peft import PeftModel, PeftConfig

# 创建模型ID,与保存时相同
peft_model_id = f"{model_name_or_path}_{peft_config.peft_type}_{peft_config.task_type}"

# 加载PEFT配置
config = PeftConfig.from_pretrained(peft_model_id)
# 加载基础模型
model = AutoModelForSeq2SeqLM.from_pretrained(config.base_model_name_or_path)
# 加载PEFT权重,应用到基础模型
model = PeftModel.from_pretrained(model, peft_model_id)

# 设置模型为评估模式
model.eval()
# 选择验证集中的第13个样本进行测试
i = 13
# 对输入文本进行分词处理
inputs = tokenizer(dataset["validation"][text_column][i], return_tensors="pt")
# 打印原始输入文本
print(dataset["validation"][text_column][i])
# 打印分词后的输入
print(inputs)

# 使用模型生成预测结果
with torch.no_grad():
    # 生成输出,限制最大新生成的token数为10
    outputs = model.generate(input_ids=inputs["input_ids"], max_new_tokens=10)
    # 打印原始输出token ID
    print(outputs)
    # 将输出token ID解码为文本并打印
    print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True))

对于其他 AutoModelFor 类未显式支持的任务(例如自动语音识别),您仍然可以使用基础 PeftConfig类来加载用于该任务的模型。

plain
# 加载PEFT配置
config = PeftConfig.from_pretrained(peft_model_id)
# 加载基础模型
model = AutoModelForSeq2SeqLM.from_pretrained(config.base_model_name_or_path)