| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import re |
| | from typing import Dict, Type, Union |
| |
|
| | import torch |
| | from torch import nn |
| |
|
| | from peft.tuners.lycoris_utils import LycorisConfig, LycorisTuner |
| |
|
| | from .layer import Conv2d, Linear, OFTLayer |
| |
|
| |
|
| | class OFTModel(LycorisTuner): |
| | """ |
| | Creates Orthogonal Finetuning model from a pretrained model. The method is described in |
| | https://arxiv.org/abs/2306.07280 |
| | |
| | Args: |
| | model (`torch.nn.Module`): The model to which the adapter tuner layers will be attached. |
| | config ([`OFTConfig`]): The configuration of the OFT model. |
| | adapter_name (`str`): The name of the adapter, defaults to `"default"`. |
| | |
| | Returns: |
| | `torch.nn.Module`: The OFT model. |
| | |
| | Example: |
| | ```py |
| | >>> from diffusers import StableDiffusionPipeline |
| | >>> from peft import OFTModel, OFTConfig |
| | |
| | >>> config_te = OFTConfig( |
| | ... r=8, |
| | ... target_modules=["k_proj", "q_proj", "v_proj", "out_proj", "fc1", "fc2"], |
| | ... module_dropout=0.0, |
| | ... init_weights=True, |
| | ... ) |
| | >>> config_unet = OFTConfig( |
| | ... r=8, |
| | ... target_modules=[ |
| | ... "proj_in", |
| | ... "proj_out", |
| | ... "to_k", |
| | ... "to_q", |
| | ... "to_v", |
| | ... "to_out.0", |
| | ... "ff.net.0.proj", |
| | ... "ff.net.2", |
| | ... ], |
| | ... module_dropout=0.0, |
| | ... init_weights=True, |
| | ... ) |
| | |
| | >>> model = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5") |
| | >>> model.text_encoder = OFTModel(model.text_encoder, config_te, "default") |
| | >>> model.unet = OFTModel(model.unet, config_unet, "default") |
| | ``` |
| | |
| | **Attributes**: |
| | - **model** ([`~torch.nn.Module`]) -- The model to be adapted. |
| | - **peft_config** ([`OFTConfig`]): The configuration of the OFT model. |
| | """ |
| |
|
| | prefix: str = "oft_" |
| | layers_mapping: Dict[Type[torch.nn.Module], Type[OFTLayer]] = { |
| | torch.nn.Conv2d: Conv2d, |
| | torch.nn.Linear: Linear, |
| | } |
| |
|
| | def _create_and_replace( |
| | self, |
| | config: LycorisConfig, |
| | adapter_name: str, |
| | target: Union[OFTLayer, nn.Module], |
| | target_name: str, |
| | parent: nn.Module, |
| | current_key: str, |
| | ) -> None: |
| | """ |
| | A private method to create and replace the target module with the adapter module. |
| | """ |
| |
|
| | |
| | pattern_keys = list(config.rank_pattern.keys()) |
| | target_name_key = next(filter(lambda key: re.match(rf"(.*\.)?{key}$", current_key), pattern_keys), target_name) |
| |
|
| | kwargs = config.to_dict() |
| | kwargs["r"] = config.rank_pattern.get(target_name_key, config.r) |
| |
|
| | if isinstance(target, OFTLayer): |
| | target.update_layer(adapter_name, **kwargs) |
| | else: |
| | new_module = self._create_new_module(config, adapter_name, target, **kwargs) |
| | self._replace_module(parent, target_name, new_module, target) |
| |
|