PEFT 的工作流程

社区文章 发布于 2024 年 8 月 14 日

image/png

我是参数高效微调(PEFT)方法和库(peft)的新手。PEFT 是一种旨在通过关注参数子集来提高大型模型微调效率的方法。peft 是一个有助于各种 PEFT 方法的库。

PEFT 中流行的一种技术是 低秩适应(Low-Rank Adaptation) (LoRA),我将通过 peft 库来演示它。

阅读了 peft 快速入门后,我掌握了该库的基本工作流程。在这篇短文中,我将探讨如何创建基础模型并使用它来构建 LoRA 模型。此外,我将简要了解 peft 库的内部机制,以便更好地理解其工作原理。

为什么要使用 PEFT 和 LoRA?

PEFT 方法,如 LoRA,旨在通过关注模型的特定部分来减少微调期间的计算负载。这使得您能够以显著减少的可训练参数实现高性能,使其成为资源有限场景的理想选择。

创建基础模型

import torch
from torch import nn
from peft import LoraConfig, get_peft_model, PeftType

# create a base model
class BaseModel(nn.Module):
    def __init__(self, dim_in, dim_out):
        super().__init__()
        self.linear = nn.Linear(dim_in, dim_out)
    
    def forward(self, x):
        return self.linear(x)

base_model = BaseModel(dim_in=2, dim_out=4)

print("### BASE MODEL")
for name, param in base_model.named_parameters():
    print(name, param)

BaseModel 由一个 Linear 层组成。当我们打印模型的名称和参数时,我们观察到参数具有 requires_grad=True,表明它们是可训练的。

### BASE MODEL
linear.weight Parameter containing:
tensor([[-0.4009, -0.6960],
        [-0.1067, -0.3404],
        [-0.1151, -0.5108],
        [ 0.3779, -0.3602]], requires_grad=True)
linear.bias Parameter containing:
tensor([-0.2076, -0.0166, -0.1409,  0.3477], requires_grad=True)

创建 PEFT 配置

每种 PEFT 方法都需要一个**配置**来确定如何应用微调。下面是 LoRA 的配置

# you always start with a configuration
config = LoraConfig(
    inference_mode=False,
    r=1,
    lora_alpha=4,
    lora_dropout=0.1,
    target_modules=["linear"],
    peft_type=PeftType.LORA,
)

创建 PEFT 模型

使用基础模型和配置,我们通过 get_peft_model 方法实例化 PEFT 模型。

lora_model = get_peft_model(model=base_model, peft_config=config)
print("\n\n### LORA MODEL")
for name, param in lora_model.named_parameters():
    print(name, param)
### LORA MODEL
base_model.model.linear.base_layer.weight Parameter containing:
tensor([[-0.4009, -0.6960],
        [-0.1067, -0.3404],
        [-0.1151, -0.5108],
        [ 0.3779, -0.3602]])
base_model.model.linear.base_layer.bias Parameter containing:
tensor([-0.2076, -0.0166, -0.1409,  0.3477])
base_model.model.linear.lora_A.default.weight Parameter containing:
tensor([[-0.5649,  0.3173]], requires_grad=True)
base_model.model.linear.lora_B.default.weight Parameter containing:
tensor([[0.],
        [0.],
        [0.],
        [0.]], requires_grad=True)

在这里,基础模型的线性层不再具有 requires_grad=True,这意味着 lora_model 将只训练 LoRA 特定的层,只优化 LoRA 引入的额外参数。

PEFT 幕后揭秘

为了更好地理解工作流程,我们来探讨一下调用 get_peft_model 方法时会发生什么。

  • get_peft_model 函数位于 src/peft/mapping.py 文件中,它会预处理配置并创建一个 PeftModel。
  • PeftModel 类位于 src/peft/peft_model.py 中,它是各种 PEFT 方法(包括 LoRA)的基础模型。它选择合适的 PEFT 模块并创建一个实例,例如本例中的 LoraModel。
  • 每个 PEFT 调谐器都在 src/peft/tuners/ 文件夹中实现。例如,LoraModel 类在 src/peft/tuners/lora/model.py 中定义。这个类继承自 BaseTuner 类,该类为所有 PEFT 调谐器提供了通用方法和属性。

要进行更详细的探索,您可以查看 LoRA 论文并浏览 GitHub 上的 PEFT 代码

结论

我希望这篇帖子能让您对执行 get_peft_model 方法时发生的事情以及如何在模型中实现 LoRA 等 PEFT 方法有一个概览。如果您想深入了解,请随时联系我。

我要感谢 Benjamin Bossan,他是 Hugging Face PEFT 的核心贡献者,他审阅了这篇帖子并提供了宝贵的建议。

社区

注册登录 以评论