PEFT documentation
LoHa
LoHa

低秩哈达玛积(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 积 ((逐元素乘积)代替矩阵乘法。 由四个较小的矩阵表示,而不是像 LoRA 那样由两个矩阵表示,并且这些低秩矩阵中的每一对都通过 Hadamard 积进行组合。因此, 可以拥有相同数量的可训练参数,但具有更高的秩和表达能力。
何时使用 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
< source >( 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
< source >( 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 toFalse) — 在 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 模型的配置。