PEFT documentation
OFT
OFT

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
< 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 = 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 derplus élevée entraîne des matrices de mise à jour plus creuses avec moins de paramètres entraînables. Vous ne pouvez spécifier querouoft_block_size, mais pas les deux simultanément, carr×oft_block_size= dimension de la couche. Pour simplifier, vous pouvez spécifier soitr, soitoft_block_size, et l’autre est déduit. La valeur par défaut estr = 0; il est conseillé à l’utilisateur de définiroft_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 deoft_block_sizeentraîne des matrices de mise à jour plus denses, avec davantage de paramètres entraînables. Choisissezoft_block_sizede 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 querouoft_block_size, mais pas les deux simultanément, carr×oft_block_size= dimension de la couche. Pour simplifier, vous pouvez spécifier soitr, soitoft_block_size, et l’autre valeur est déduite automatiquement. La valeur par défaut estoft_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
Truepour 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 (TrueetFalse) selon vos besoins. La valeur par défaut estFalse. - 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 silayers_to_transformest différent deNone. Il doit cibler lenn.ModuleListdu 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 sicoftest 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 estFalse.
Ceci est la classe de configuration destinée à stocker la configuration d'un OFTModel.
check_kwargs
< source >( **kwargs )
Vérifiez si les kwargs sont valides pour la configuration.
OFTModel
classe peft.OFTModel
< 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
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éfautFalse) — 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.