PEFT documentation

OFT

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

OFT

Controlling Text-to-Image Diffusion by Orthogonal Finetuning

Orthogonal Finetuning (OFT) et OFTv2 sont des méthodes développées pour adapter les modèles de diffusion texte-image. Elles fonctionnent en reparamétrisant les matrices de poids préentraînées avec une matrice orthogonale afin de préserver les informations du modèle préentraîné. Pour réduire le nombre de paramètres, OFT introduit une structure en blocs diagonaux dans la matrice orthogonale. La méthode se concentre principalement sur la préservation des performances génératives du modèle préentraîné dans le modèle affiné. Elle tente de maintenir la même similarité cosinus (hyperspherical energy) entre toutes les paires de neurones d'une couche, car cela capture mieux l'information sémantique entre les neurones. Cela signifie qu'OFT est plus capable de préserver le sujet et qu'il est plus adapté à la génération contrôlable (similaire à ControlNet).

L'abstract de l'article est :

Les grands modèles de diffusion texte-image possèdent des capacités impressionnantes pour générer des images photoréalistes à partir de prompts texte. La manière de guider ou de contrôler efficacement ces modèles puissants afin de les faire exécuter différentes tâches en aval constitue un problème ouvert important. Pour relever ce défi, nous introduisons une méthode de fine-tuning rigoureuse — Orthogonal Finetuning (OFT) — pour adapter les modèles de diffusion texte-image à des tâches en aval. Contrairement aux méthodes existantes, OFT peut prouver qu'il préserve l'énergie hypersphérique, qui caractérise la relation par paires entre les neurones sur l'hypersphère unitaire. Nous constatons que cette propriété est cruciale pour préserver la capacité de génération sémantique des modèles de diffusion texte-image. Pour améliorer la stabilité du fine-tuning, nous proposons en outre Constrained Orthogonal Finetuning (COFT), qui impose une contrainte de rayon supplémentaire à l'hypersphère. Plus précisément, nous considérons deux tâches de fine-tuning texte-image importantes : la génération pilotée par le sujet, dont l'objectif est de générer des images spécifiques à un sujet à partir de quelques images de ce sujet et d'un prompt texte, et la génération contrôlable, dont l'objectif est de permettre au modèle d'accepter des signaux de contrôle supplémentaires. Nous montrons empiriquement que notre cadre OFT surpasse les méthodes existantes en termes de qualité de génération et de vitesse de convergence.

OFT préserve l'énergie hypersphérique en apprenant une transformation orthogonale pour les neurones afin de maintenir la similarité cosinus entre eux inchangée, ce qui peut entraîner un moindre oubli des connaissances acquises précédemment. En pratique, cela consiste à effectuer le produit matriciel d'une matrice orthogonale avec la matrice de poids pré-entraînée. Toutefois, pour être efficace en termes de paramètres, la matrice orthogonale est représentée comme une matrice bloc-diagonale avec des blocs de rang r. Alors que LoRA réduit le nombre de paramètres entraînables grâce à des structures de faible rang, OFT réduit le nombre de paramètres entraînables grâce à une structure de matrice bloc-diagonale creuse.

Aperçu des benchmarks

Fusionner les poids OFT dans le modèle de base

De manière similaire à LoRA, les poids appris par OFT peuvent être intégrés aux matrices de poids préentraînées à l'aide de la fonction [~OFTModel.merge_and_unload(). Cette fonction fusionne les poids de l'adaptateur avec le modèle de base, ce qui vous permet d'utiliser efficacement le modèle nouvellement fusionné comme un modèle autonome.

Exemple d'utilisation de OFT

Pour utiliser OFT pour l’ajustement fin quantisé avec TRL pour SFT, PPO ou DPO, suivez le plan suivant :

from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from trl import SFTTrainer
from peft import OFTConfig

if use_quantization:
    bnb_config = BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_quant_type="nf4",
        bnb_4bit_compute_dtype=torch.bfloat16,
        bnb_4bit_use_double_quant=True,
        bnb_4bit_quant_storage=torch.bfloat16,
    )

model = AutoModelForCausalLM.from_pretrained(
    "model_name",
    quantization_config=bnb_config
)
tokenizer = AutoTokenizer.from_pretrained("model_name")

# Configure OFT
peft_config = OFTConfig(
    oft_block_size=32,
    use_cayley_neumann=True,
    target_modules="all-linear",
    bias="none",
    task_type="CAUSAL_LM"
)

trainer = SFTTrainer(
    model=model,
    train_dataset=ds['train'],
    peft_config=peft_config,
    processing_class=tokenizer,
    args=training_arguments,
    data_collator=collator,
)

trainer.train()

API

OFTConfig

classe peft.OFTConfig

< >

( 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 = Falser: int = 0oft_block_size: int = 32module_dropout: float = 0.0target_modules: Optional[Union[list[str], str]] = Nonefan_in_fan_out: bool = Falsebias: Literal['none', 'all', 'oft_only'] = 'none'exclude_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]] = Nonecoft: bool = Falseeps: float = 6e-05block_share: bool = Falseuse_cayley_neumann: bool = Truenum_cayley_neumann_terms: int = 5 )

Paramètres

  • r (int) — Rang OFT, nombre de blocs OFT par couche injectée. Une valeur de r plus élevée entraîne des matrices de mise à jour plus creuses avec moins de paramètres entraînables. Vous ne pouvez spécifier que r ou oft_block_size, mais pas les deux simultanément, car r × oft_block_size = dimension de la couche. Pour simplifier, vous pouvez spécifier soit r, soit oft_block_size, et l’autre est déduit. La valeur par défaut est r = 0 ; il est conseillé à l’utilisateur de définir oft_block_size à la place pour plus de clarté.
  • oft_block_size (int) — Taille des blocs OFT à travers les différentes couches. Une valeur plus élevée de oft_block_size entraîne des matrices de mise à jour plus denses, avec davantage de paramètres entraînables. Choisissez oft_block_size de manière à ce qu’il soit divisible par la dimension d’entrée de la couche (in_features), par exemple 4, 8, 16. Vous ne pouvez spécifier que r ou oft_block_size, mais pas les deux simultanément, car r × oft_block_size = dimension de la couche. Pour simplifier, vous pouvez spécifier soit r, soit oft_block_size, et l’autre valeur est déduite automatiquement. La valeur par défaut est oft_block_size = 32.
  • use_cayley_neumann (bool) — Indique s'il faut utiliser la paramétrisation de Cayley-Neumann (efficace mais approximative) ou la paramétrisation de Cayley classique (exacte mais coûteuse en calcul en raison de l'inverse de matrice). Nous recommandons de la définir sur True pour une meilleure efficacité, mais les performances peuvent être légèrement inférieures en raison de l'erreur d'approximation. Veuillez tester les deux réglages (True et False) selon vos besoins. La valeur par défaut est False.
  • module_dropout (float) — Probabilité de dropout multiplicatif, qui consiste à définir les blocs OFT comme l'identité pendant l'entraînement, de manière similaire à la couche de dropout dans LoRA.
  • target_modules (Optional[Union[list[str], str]]) — Les noms des modules auxquels appliquer l’adaptateur. Si ce paramètre est spécifié, seuls les modules portant les noms indiqués seront remplacés. En cas de chaîne de caractères, une correspondance par expression régulière est effectuée. En cas de liste de chaînes de caractères, une correspondance exacte est réalisée ou il est vérifié si le nom du module se termine par l’une des chaînes fournies. Si ce paramètre est spécifié comme ‘all-linear’, tous les modules linéaires sont sélectionnés, à l’exception de la couche de sortie. S’il n’est pas spécifié, les modules sont choisis en fonction de l’architecture du modèle. Si l’architecture est inconnue, une erreur est levée — dans ce cas, vous devez spécifier manuellement les modules cibles.
  • fan_in_fan_out (bool) — Définissez cette valeur sur True si la couche à remplacer stocke les poids sous la forme (fan_in, fan_out).
  • bias (str) — Type de biais pour OFT. Peut être ‘none’, ‘all’ ou ‘oft_only’. Si ‘all’ ou ‘oft_only’, les biais correspondants seront mis à jour pendant l’entraînement. Notez que cela signifie que, même en désactivant les adaptateurs, le modèle ne produira pas la même sortie que le modèle de base sans adaptation.
  • exclude_modules (Optional[Union[List[str], str]]) — Les noms des modules auxquels l’adaptateur ne doit pas être appliqué. Si une chaîne de caractères est transmise, une correspondance par expression régulière est effectuée. Si une liste de chaînes de caractères est transmise, une correspondance exacte est effectuée ou il est vérifié si le nom du module se termine par l’une des chaînes transmises.
  • init_weights (bool) — Indique s'il faut effectuer l'initialisation des poids OFT.
  • layers_to_transform (Union[List[int], int]) — Les indices de couches à transformer. Si une liste d'entiers est transmise, l'adaptateur sera appliqué aux indices de couches spécifiés dans cette liste. Si un seul entier est transmis, les transformations seront appliquées à la couche située à cet index.
  • layers_pattern (Optional[Union[List[str], str]]) — Le nom du motif de couche, utilisé uniquement si layers_to_transform est différent de None. Il doit cibler le nn.ModuleList du modèle, souvent appelé 'layers' ou 'h'.
  • modules_to_save (List[str]) — Liste des modules, en dehors des couches d’adaptateur, à définir comme entraînables et à enregistrer dans le point de contrôle final.
  • coft (bool) — Indique s'il faut utiliser la variante contrainte de OFT ou non. Désactivé par défaut.
  • eps (float) — La force de contrôle de COFT. La liberté de rotation. N'a un effet que si coft est défini sur True.
  • block_share (bool) — Indique s'il faut partager les paramètres OFT entre les blocs ou non. La valeur par défaut est False.

Ceci est la classe de configuration destinée à stocker la configuration d'un OFTModel.

check_kwargs

< >

( **kwargs )

Paramètres

  • kwargs (arguments supplémentaires par mot-clé, facultatif) — Arguments supplémentaires par mot-clé transmis à l'initialisation de la classe enfant.

Vérifiez si les kwargs sont valides pour la configuration.

OFTModel

classe peft.OFTModel

< >

( 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

Paramètres

  • model (torch.nn.Module) — Le modèle auquel les couches d’adaptation du tuner seront attachées.
  • config (OFTConfig) — La configuration du modèle OFT.
  • adapter_name (str) — Le nom de l'adaptateur, par défaut "default".
  • low_cpu_mem_usage (bool, optional, par défaut False) — Crée des poids d'adaptateurs vides sur l'appareil méta. Utile pour accélérer le processus de chargement.

Retourne

torch.nn.Module

Le modèle OFT.

Crée un modèle Orthogonal Finetuning à partir d'un modèle pré-entraîné. La méthode est décrite dans https://huggingface.co/papers/2306.07280

Exemple :

>>> 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")

Attributs :

  • model (~torch.nn.Module) — Le modèle à adapter.
  • peft_config (OFTConfig) : La configuration du modèle OFT.
Update on GitHub