PEFT documentation

LoHa

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.21.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

LoHa

Navigating Text-To-Image Customization: From LyCORIS Fine-Tuning to Model Evaluation

低秩哈达玛积(LoHa)与 LoRA 类似,但它使用更多低秩矩阵来近似大型权重矩阵,并通过哈达玛积将它们组合起来。该方法比 LoRA 具有更高的参数效率,并能实现相当的性能。LoHa 最初是为联邦学习(FedPara)提出的,但作为一种通用的 PEFT 方法表现良好,尤其常用于微调 Stable Diffusion 等图像生成模型。

注意:LoHa 是 LyCORIS 适配器家族的一部分。其近亲 LoKr 使用 Kronecker 积而非 Hadamard 积。

该论文的摘要如下:

在本工作中,我们提出了一种通信高效的参数化方法 FedPara,用于联邦学习(FL),以克服频繁上传和下载模型所带来的负担。我们的方法使用低秩权重,随后进行 Hadamard 积,对层的权重参数进行重参数化。与传统的低秩参数化相比,我们的 FedPara 方法不受低秩约束的限制,因此具有远大的容量。这一特性使其能够在通信成本比原始层模型低 3 到 10 倍的情况下实现可比的性能,而这是传统低秩方法无法实现的。通过将我们的方法与其他高效的 FL 优化器结合,可以进一步提高其效率。此外,我们将该方法扩展到个性化联邦学习应用 pFedPara,该方法将参数分为全局参数和局部参数。我们证明,pFedPara 在参数数量减少三倍以上的前提下,性能优于其他竞争性个性化联邦学习方法。

低秩分解可能会影响性能,因为权重更新被限制在低秩空间内,这可能会限制模型的表达能力。然而,你并不一定希望使用更大的秩,因为这会增加可训练参数的数量。为了解决这个问题,LoHa 被应用于扩散模型,因为在这些模型中,生成多样化图像的能力是一个重要的考量因素。LoHa 也应该适用于通用模型类型,但 PEFT 目前尚未实现对嵌入层的支持。

LoHa 使用 Hadamard 积 ((逐元素乘积)代替矩阵乘法。 ΔW\Delta W 由四个较小的矩阵表示,而不是像 LoRA 那样由两个矩阵表示,并且这些低秩矩阵中的每一对都通过 Hadamard 积进行组合。因此, ΔW\Delta W 可以拥有相同数量的可训练参数,但具有更高的秩和表达能力。

何时使用 LoHa

LoHa 在以下情况下是一个不错的选择:

  • 您正在微调图像生成模型(Stable Diffusion UNet 或文本编码器),这是其最广泛的应用场景。
  • 与 LoRA 相比,在相同数量的可训练参数下,你希望获得更高的有效秩,因为两个低秩矩阵的哈达玛积所张成的子空间比单个低秩乘积更大。
  • 您希望在推理时使用 PeftMixedModel 组合不同的 PEFT 方法,例如将 LoHa 与 LoKr 一起使用。

LoHa 支持线性层和 Conv2d 层。对于还需要适配嵌入层的任务,请考虑使用 LoRA。

用法

from diffusers import StableDiffusionPipeline
from peft import LoHaConfig, get_peft_model

config_unet = LoHaConfig(
    r=8,
    alpha=8,
    target_modules=[
        "to_k",
        "to_q",
        "to_v",
        "to_out.0",
        "proj_in",
        "proj_out",
    ],
    rank_dropout=0.0,
    module_dropout=0.0,
    use_effective_conv2d=True,
)

pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
pipeline.unet = get_peft_model(pipeline.unet, config_unet)
pipeline.unet.print_healthcheck()

基准测试概览

API

LoHaConfig

类 peft.LoHaConfig

< >

( task_type: Optional[Union[str, TaskType]] = Nonepeft_type: Optional[Union[str, PeftType]] = Noneauto_mapping: Optional[dict] = Nonepeft_version: Optional[str] = Nonebase_model_name_or_path: Optional[str] = Nonerevision: Optional[str] = Noneinference_mode: bool = Falserank_pattern: Optional[dict] = <factory>alpha_pattern: Optional[dict] = <factory>r: int = 8alpha: int = 8rank_dropout: float = 0.0module_dropout: float = 0.0use_effective_conv2d: bool = Falsetarget_modules: Optional[Union[list[str], str]] = Noneexclude_modules: Optional[Union[list[str], str]] = Noneinit_weights: bool = Truelayers_to_transform: Optional[Union[list[int], int]] = Nonelayers_pattern: Optional[Union[list[str], str]] = Nonemodules_to_save: Optional[list[str]] = None )

参数

  • r (int) — LoHa 秩。
  • alpha (int) — LoHa 缩放的 alpha 参数。
  • rank_dropout (float) — 训练期间秩维度的 dropout 概率。
  • module_dropout (float) — 训练期间禁用 LoHa 模块的 dropout 概率。
  • use_effective_conv2d (bool) — 对 ksize > 1 的 Conv2d(以及 Conv1d)使用参数有效分解(FedPara 论文中的“Proposition 3”)。
  • target_modules (Optional[Union[List[str], str]]) — 要应用适配器(adapter)的模块名称。如果指定了此参数,则只有名称匹配的模块会被替换。传入字符串时,将执行正则表达式匹配。传入字符串列表时,将执行精确匹配,或检查模块名称是否以列表中的任一字符串结尾。如果指定为 ‘all-linear’,则选择所有 linear/Conv1D 模块,但不包括输出层。如果未指定,将根据模型架构选择模块。如果架构未知,则会引发错误——在这种情况下,应手动指定目标模块。
  • exclude_modules (Optional[Union[List[str], str]]) — 不应用适配器的模块名称。传入字符串时,将执行正则表达式匹配。传入字符串列表时,将执行精确匹配,或检查模块名称是否以传入的任一字符串结尾。
  • init_weights (bool) — 是否执行适配器权重的初始化。默认值为 True,不建议传入 False。
  • layers_to_transform (Union[List[int], int]) — 要转换的层索引。如果传入一个整数列表,则会将适配器应用于该列表中指定的层索引。如果传入单个整数,则会对该索引处的层应用转换。
  • layers_pattern (Optional[Union[List[str], str]]) — 层模式名称,仅在 layers_to_transform 不同于 None 时使用。它应指向模型的 nn.ModuleList,该列表通常命名为 'layers' 或 'h'。
  • rank_pattern (dict) — 从层名称或正则表达式到与 r 指定的默认 rank 不同的 rank 的映射。例如,{'^model.decoder.layers.0.encoder_attn.k_proj': 16}。
  • alpha_pattern (dict) — 从层名称或正则表达式到与alpha指定的默认 alpha 不同的 alpha 值的映射。例如,{'^model.decoder.layers.0.encoder_attn.k_proj': 16}。
  • modules_to_save (Optional[List[str]]) — 除适配器层外,需要设置为可训练并在最终检查点中保存的模块列表。

这是用于存储 LoHaModel 配置的类。

LoHaModel

类 peft.LoHaModel

< >

( modelpeft_config: Union[PeftConfig, dict[str, PeftConfig]]adapter_name: strlow_cpu_mem_usage: bool = Falsestate_dict: Optional[dict[str, torch.Tensor]] = None ) → torch.nn.Module

参数

  • model (torch.nn.Module) — 将附加适配器调优层的模型。
  • config (LoHaConfig) — LoHa 模型的配置。
  • adapter_name (str) — 适配器的名称,默认为 "default"。
  • low_cpu_mem_usage (bool, optional, defaults to False) — 在 meta 设备上创建空的适配器权重。有助于加快加载过程。

返回值

torch.nn.Module

LoHa 模型。

从预训练模型创建低秩哈达玛积(Low-Rank Hadamard Product)模型。该方法在 https://huggingface.co/papers/2108.06098 中有所描述。当前实现大量借鉴自 https://github.com/KohakuBlueleaf/LyCORIS/blob/eb460098187f752a5d66406d3affade6f0a07ece/lycoris/modules/loha.py

示例:

>>> from diffusers import StableDiffusionPipeline
>>> from peft import LoHaModel, LoHaConfig

>>> config_te = LoHaConfig(
...     r=8,
...     lora_alpha=32,
...     target_modules=["k_proj", "q_proj", "v_proj", "out_proj", "fc1", "fc2"],
...     rank_dropout=0.0,
...     module_dropout=0.0,
...     init_weights=True,
... )
>>> config_unet = LoHaConfig(
...     r=8,
...     lora_alpha=32,
...     target_modules=[
...         "proj_in",
...         "proj_out",
...         "to_k",
...         "to_q",
...         "to_v",
...         "to_out.0",
...         "ff.net.0.proj",
...         "ff.net.2",
...     ],
...     rank_dropout=0.0,
...     module_dropout=0.0,
...     init_weights=True,
...     use_effective_conv2d=True,
... )

>>> model = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
>>> model.text_encoder = LoHaModel(model.text_encoder, config_te, "default")
>>> model.unet = LoHaModel(model.unet, config_unet, "default")

属性:

  • model (~torch.nn.Module) — 要适配的模型。
  • peft_config (LoHaConfig): LoHa 模型的配置。
Update on GitHub