PEFT documentation
Lily : Adaptation interconnectée de faible rang à travers les couches
Lily : Adaptation interconnectée de faible rang à travers les couches
Lily est une technique de fine-tuning efficace en termes de paramètres qui introduit le partage de poids inter-couches pour les matrices d'adaptateurs. Plutôt que d'apprendre une paire AB indépendante par couche comme dans LoRA, Lily utilise des adaptateurs A partagés localement (chaque A est partagé sur un bloc de stride_A couches consécutives) et des experts B partagés globalement (un petit pool de num_B adaptateurs B est partagé entre toutes les couches). À chaque passe avant, un routeur léger dépendant des données calcule une combinaison pondérée par softmax des experts B pour produire le B effectif pour cette couche et cette entrée.
Ce partage peut réduire le nombre total de matrices d’adaptateurs de 2N (LoRA standard) à N / stride_A + num_B, libérant ainsi le budget de paramètres pour utiliser un rang r beaucoup plus élevé — typiquement 2×–4× celui utilisé en LoRA. Un rang plus élevé et une meilleure interconnectivité augmentent le rang effectif de la mise à jour des poids ΔW = A × combined_B, ce qui améliore les performances d’adaptation.
La combinaison B est dépendante des données (les poids du routeur dépendent des activations d’entrée à l’exécution), merge et unmerge ne sont donc pas pris en charge. Si la fusion des poids est requise pour votre déploiement, envisagez d’autres méthodes telles que LoRA.
Lily a actuellement les contraintes supplémentaires suivantes :
- Seules les couches
nn.Linearsont prises en charge. - Les couches quantifiées ne sont pas prises en charge.
Si ces contraintes ne conviennent pas à votre cas d’usage, envisagez plutôt d’autres méthodes.
L'abstract de l'article est :
L’adaptation de faible rang (LoRA) est une méthode de fine-tuning efficace en paramètres (PEFT) largement utilisée, qui apprend des mises à jour de poids ΔW = AB pour les poids pré-entraînés W à l’aide d’adaptateurs de faible rang A et B. Bien que LoRA garantisse une efficacité matérielle, ses mises à jour de poids de faible rang limitent les performances d’adaptation. Dans cet article, nous proposons l’adaptation interconnectée de faible rang entre les couches (Lily), une nouvelle méthode PEFT qui introduit un cadre interconnecté avec des experts A partagés localement et des experts B partagés globalement. Cette structure élimine les paires AB redondantes par couche, permettant un ΔW de rang supérieur avec un nombre égal ou inférieur de paramètres. Pour améliorer l’expressivité, nous utilisons des routeurs dépendants des données pour déterminer les interconnexions A-B, empêchant les experts B de converger vers le même comportement et améliorant la puissance de représentation à travers les domaines. Des expériences à travers différentes modalités, architectures et tailles de modèles démontrent les performances supérieures et l’efficacité de Lily.
Aperçu des benchmarks
API
LilyConfig
classe peft.LilyConfig
< 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 = 32stride_A: int = 1num_B: int = 2scaling: float = 1.0target_modules: Optional[Union[list[str], str]] = Noneexclude_modules: Optional[Union[list[str], str]] = Nonemodules_to_save: Optional[list[str]] = Nonelayers_to_transform: Optional[Union[list[int], int]] = Nonelayers_pattern: Optional[Union[list[str], str]] = Noneinit_weights: bool = True )
Paramètres
- r (
int) — Rang de Lily. Détermine la dimension cachée interne de chaque adaptateur et le rang de la mise à jour des poidsA @ B. Dans Lily, le nombre d’adaptateurs étant généralement plus faible que dans LoRA, chaque adaptateur doit porter plus de capacité ; il est donc recommandé d’utiliser unrplus élevé que dans LoRA — typiquement2x,3xou4xle rang LoRA que vous utiliseriez normalement. Le nombre total de paramètres entraîlables évolue avecr * (total_layers / stride_A + num_B), il est donc recommandé d’augmenterrtout en maintenantstride_Aélevé etnum_Bfaible. - stride_A (
int) — Le nombre de couches consécutives qui partagent un adaptateur A. Par exemple, sistride_A=4, toutes les 4 couches adjacentes partagent le même adaptateur A, ce qui donnetotal_layers / stride_Aadaptateurs A distincts au total. L'adaptateur A compresse l'entrée en une représentation de rang faible de tailler.stride_Ane doit pas être inférieur à- Valeurs suggérées :
2,3ou4(c’est-à-dire partager toutes les 2, 3 ou 4 couches). Garderstride_Aélevé (moins d’adaptateurs A distincts) et augmenterrà la place conduit à de meilleures performances que le compromis inverse (petitstride_A, petitr). Définirstride_A=1signifie que chaque couche possède son propre adaptateur A. NOTE : le partage des A se fait au sein de chaque cible (couches ayant le même suffixe de cible). Par exemple, si vos target_modules sont['q_proj', 'v_proj']et que vous définissezstride_A=2, alors toutes les 2 couches q_proj adjacentes partageront un adaptateur A, et toutes les 2 couches v_proj adjacentes partageront un autre adaptateur A, mais les couches q_proj et v_proj ne partageront pas d’adaptateurs A entre elles car elles ont des suffixes différents.
- Valeurs suggérées :
- num_B (
int) — Le nombre d'adaptateurs B partagés. Contrairement aux adaptateurs A (qui sont groupés par couche), tous les adaptateurs B sont partagés globalement sur toutes les couches. Pour chaque passe avant, un routeur calcule une combinaison pondérée de tous lesnum_Badaptateurs B (en utilisant des poids normalisés par softmax) pour produire un unique adaptateur B combiné, qui projette ensuite la représentation de faible rang vers la dimension d'origine. Il est recommandé de définirnum_Bà un ordre de grandeur similaire àtotal_layers / stride_A. Valeurs suggérées :total_layers / 2,total_layers / 3outotal_layers / 4. De manière similaire àstride_A, préférez unnum_Bplus petit avec unrplus grand plutôt qu'unnum_Bplus grand avec unrplus petit. REMARQUE : pour entraîner le routeur, vous avez besoin d'au moins 2 adaptateurs B (c'est-à-direnum_B >= 2), car le routeur apprend à calculer une combinaison pondérée des adaptateurs B. REMARQUE : le partage des B se fait au sein de chaque cible (couches ayant le même suffixe de cible). Par exemple, si vos target_modules sont['q_proj', 'v_proj']et que vous définisseznum_B=4, il y aura 4 adaptateurs B partagés entre toutes les couches q_proj, et 4 autres adaptateurs B partagés entre toutes les couches v_proj, mais les couches q_proj et v_proj ne partageront pas d'adaptateurs B entre elles car elles ont des suffixes différents. - target_modules (
Union[List[str], str], facultatif) — Les noms des modules auxquels appliquer Lily. Peut être une liste de chaînes de caractères de noms de modules (par ex.['q_proj', 'v_proj']) ou un motif regex (par ex.'.*decoder.*(SelfAttention|EncDecAttention).*(q|v)$'). Si non spécifié, Lily sera appliqué à toutes les couches linéaires prises en charge. - scaling (
float) — Un multiplicateur scalaire appliqué à la sortie combinée de l’adaptateur (scaling * A @ combined_B) avant de l’ajouter au passage avant du poids figé. Contrairement à LoRA, Lily n’utilise pas de formulationalpha / r; à la place,scalingest un multiplicateur direct. Cette conception permet de balayer facilement des valeurs sur une échelle logarithmique (par ex.0.01,0.1,1.0,10.0). La valeur optimale dépend de la tâche et doit être traitée comme un hyperparamètre. Nous recommandons de commencer avec1.0. - modules_to_save (
List[str], facultatif) — Liste des modules, à l'exception des couches Lily, à définir comme entraînables et à enregistrer dans le point de contrôle final. Par exemple, dans les tâches de classification de séquences ou de classification de jetons, la couche finaleclassifier/scoreest initialisée aléatoirement et doit donc être entraînable et enregistrée. - exclude_modules (
Union[List[str], str], facultatif) — 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. - layers_to_transform (
Union[list[int], int], facultatif) — Les index des couches à transformer. Si cet argument est spécifié, PEFT ne transformera que les index de couches indiqués dans cette liste. Si un entier unique est transmis, PEFT ne transformera que la couche située à cet index. - layers_pattern (
Optional[Union[List[str], str]], facultatif) — Le nom du motif de couche, utilisé uniquement silayers_to_transformest différent de None et si le motif de couche ne figure pas dans les motifs de couches courants. Il doit cibler lenn.ModuleListdu modèle, souvent appelé'layers'ou'h'. - init_weights (
bool) — Indique s'il faut initialiser les poids de l'adaptateur Lily en utilisant le schéma d'initialisation par défaut : les matrices A sont initialisées avec Kaiming uniform, et les matrices B sont initialisées à zéro, ce qui garantit que la sortie de l'adaptateur est nulle au début de l'entraînement et ne perturbe pas le modèle pré-entraîné. Il est fortement recommandé de conserver cette valeur àTruesauf si vous avez une raison spécifique de la modifier.
Ceci est la classe de configuration destinée à stocker la configuration d'un LilyModel.
LilyModel
classe peft.LilyModel
< 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 à adapter. - config (LilyConfig) — La configuration du modèle Lily.
- adapter_name (
str) — Le nom de l'adaptateur, par défaut"default".
Retourne
torch.nn.Module
Le modèle PEFT de Lily.
Crée un modèle Low-Rank Interconnected Adaptation Across Layers (Lily) à partir d'un modèle transformers pré-entraîné.
La méthode est décrite en détail dans https://arxiv.org/abs/2407.09946.
Attributs :
- model (PreTrainedModel) — Le modèle à adapter.
- peft_config (LilyConfig) : La configuration du modèle Lily.