【diffusers 进阶之 PEFT 入门(三)】BaseTunerLayer 与 set_adapter

系列文章目录



    def set_adapter(self, adapter_names: str | list[str]) -> None:
        """Set the active adapter(s).

        Additionally, this function will set the specified adapters to trainable (i.e., requires_grad=True). If this is
        not desired, use the following code.

        ```py
        >>> for name, param in model_peft.named_parameters():
        ...     if ...:  # some check on name (ex. if 'lora' in name)
        ...         param.requires_grad = False
        ```

        Args:
            adapter_name (`str` or `List[str]`): Name of the adapter(s) to be activated.
        """
        if isinstance(adapter_names, str):
            adapter_names = [adapter_names]

        # Deactivate grads on the inactive adapter and activate grads on the active adapter
        for layer_name in self.adapter_layer_names:
            module_dict = getattr(self, layer_name)
            for key, layer in module_dict.items():
                if key in adapter_names:
                    # Note: It is possible that not a single layer is called with requires_grad_(True) here. This may
                    # happen if a completely different adapter layer is being activated.
                    layer.requires_grad_(True)
                else:
                    layer.requires_grad_(False)

        self._active_adapter = adapter_names

getattrself 在 PEFT 中的详细解析

getattr 函数

getattr 是 Python 内置函数,用于获取对象的属性。

基本语法

getattr(object, name[, default])
  • object: 要获取属性的对象
  • name: 属性名称(字符串)
  • default: 可选参数,如果属性不存在则返回此值

在 PEFT 中的应用

module_dict = getattr(self, layer_name)

这行代码的作用是:

  1. self 对象(即当前类实例)中
  2. 获取名为 layer_name 的属性
  3. 将获取到的属性赋值给 module_dict 变量

在 PEFT 的上下文中,这些属性是存储适配器层的字典。

self 在 PEFT 中的含义

self 是 Python 类方法中的第一个参数,表示类的实例本身。

在 PEFT 中的 self

set_adapter 方法中,self 指的是 BaseTunerLayer 的实例,它包含:

  1. 适配器层字典

    • 每个 layer_name 对应一个字典属性
    • 这些字典存储了不同名称的适配器层
  2. 适配器层名称列表

    • self.adapter_layer_names 存储了所有适配器层的属性名称
    • 例如,对于 LoRA,可能包含 ['lora_A', 'lora_B']
  3. 活跃适配器记录

    • self._active_adapter 记录当前活跃的适配器名称

完整流程解析

让我们详细分析这段代码的执行流程:

for layer_name in self.adapter_layer_names:
    module_dict = getattr(self, layer_name)
    for key, layer in module_dict.items():
        if key in adapter_names:
            layer.requires_grad_(True)
        else:
            layer.requires_grad_(False)
  1. 遍历适配器层类型

    • self.adapter_layer_names 包含所有适配器层类型的名称
    • 对于 LoRA,这通常是 ['lora_A', 'lora_B']
    • 对于其他适配器类型,可能有不同的名称
  2. 获取每种类型的适配器字典

    • module_dict = getattr(self, layer_name) 获取特定类型的适配器字典
    • 例如,getattr(self, 'lora_A') 返回所有 A 矩阵的字典
  3. 遍历适配器实例

    • for key, layer in module_dict.items() 遍历字典中的所有适配器
    • key 是适配器名称(如 “default”, “adapter1” 等)
    • layer 是实际的适配器层(如 LoRA 的 A 或 B 矩阵)
  4. 设置梯度状态

    • 如果适配器名称在要激活的列表中,设置 requires_grad=True
    • 否则设置 requires_grad=False

具体示例

假设我们有一个 LoRA 模型,其结构如下:

BaseTunerLayer
├── adapter_layer_names = ('lora_A', 'lora_B', 'lora_embedding_A', 'lora_embedding_B')
├── lora_A = {
│   ├── 'default': LinearLayer(...),
│   └── 'adapter1': LinearLayer(...)
│   }
└── lora_B = {
    ├── 'default': LinearLayer(...),
    └── 'adapter1': LinearLayer(...)
    }
 ...

当调用 set_adapter('adapter1') 时:

  1. adapter_names 被设置为 ['adapter1']
  2. 遍历 adapter_layer_names(即 ['lora_A', 'lora_B']
  3. 对于 'lora_A'
    • 获取 self.lora_A 字典
    • 'default' 对应的层设为不可训练
    • 'adapter1' 对应的层设为可训练
  4. 对于 'lora_B'
    • 获取 self.lora_B 字典
    • 'default' 对应的层设为不可训练
    • 'adapter1' 对应的层设为可训练
  5. 设置 self._active_adapter = ['adapter1']

这种设计使得 PEFT 可以在同一个模型中管理多个适配器,并轻松切换它们的活跃状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值