PEFT documentation
Prompt Tuning contextuel : faire progresser l'apprentissage en contexte avec des méthodes adversariales
Prompt Tuning contextuel : faire progresser l'apprentissage en contexte avec des méthodes adversariales

Context-Aware Prompt Tuning (CPT) est conçu pour améliorer la classification en peu d'exemples en ne raffinant que les embeddings de contexte. Cette approche combine des idées issues de l'In-Context Learning (ICL), du Prompt Tuning (PT) et de l'optimisation adversariale, en se concentrant sur une adaptation du modèle à la fois efficace en termes de paramètres et performante. Dans CPT, seuls les embeddings de jetons de contexte spécifiques sont optimisés, tandis que le reste du modèle reste figé. Pour éviter le surapprentissage et maintenir la stabilité, CPT utilise des perturbations contrôlées pour limiter les modifications autorisées des embeddings de contexte à une plage définie. De plus, pour traiter le phénomène de biais de récence — où les exemples proches de la fin du contexte ont tendance à être privilégiés par rapport aux précédents — CPT applique un facteur de perte de décroissance.
L'abstract de l'article est :
Les grands modèles de langage (LLMs) peuvent effectuer de l'apprentissage par quelques exemples (few-shot learning) en utilisant soit des approches basées sur l'optimisation, soit l'apprentissage en contexte (In-Context Learning, ICL). Les méthodes basées sur l'optimisation souffrent souvent du surapprentissage, car elles nécessitent la mise à jour d'un grand nombre de paramètres avec des données limitées. En revanche, l'ICL évite le surapprentissage, mais offre généralement des performances inférieures à celles des méthodes basées sur l'optimisation et est très sensible à la sélection, à l'ordre et au format des exemples de démonstration. Pour surmonter ces défis, nous introduisons le Context-aware Prompt Tuning (CPT), une méthode inspirée de l'ICL, du Prompt Tuning (PT) et des attaques adverses. Le CPT s'appuie sur la stratégie ICL qui consiste à concaténer les exemples avant l'entrée, en l'étendant par l'intégration d'un apprentissage de type PT pour affiner l'incorporation (embedding) du contexte par optimisation itérative, extrayant ainsi des informations plus approfondies des exemples d'entraînement. Notre approche modifie soigneusement des jetons (tokens) de contexte spécifiques, en tenant compte de la structure unique des exemples au sein du contexte. En plus de la mise à jour du contexte par une optimisation de type PT, le CPT s'inspire des attaques adverses en ajustant l'entrée en fonction des étiquettes présentes dans le contexte, tout en préservant la valeur inhérente des données fournies par l'utilisateur. Pour garantir la robustesse et la stabilité pendant l'optimisation, nous utilisons un algorithme de descente de gradient projeté, contraignant les incorporations de jetons à rester proches de leurs valeurs d'origine et protégeant ainsi la qualité du contexte. Notre méthode a démontré une précision supérieure sur plusieurs tâches de classification en utilisant divers modèles LLM, surpassant les lignes de base existantes et traitant efficacement le défi du surapprentissage dans l'apprentissage par quelques exemples.
Consultez Example pour un guide étape par étape sur la façon d’entraîner un modèle avec CPT.
Principe de fonctionnement
Le Prompt Tuning contextuel (Context-aware Prompt Tuning) est similaire au Prompt Tuning en ce sens que vous pouvez choisir un prompt texte de votre choix, mais rendre les jetons de ce prompt, et uniquement ceux-ci, entraînables grâce à une seconde matrice d’incorporation de jetons appliquée uniquement aux jetons du prompt. Chaque fois que vous interrogez un modèle CPT, votre prompt « soft » est préfixé à l’incorporation de votre entrée normale. Le CPT diffère du Prompt Tuning en ce que votre prompt soft peut désormais être contextualisé en marquant des parties spécifiques comme non entraînables. La matrice d’incorporation de jetons spécifique au CPT est composée d’une incorporation statique initialisée à partir de la matrice d’incorporation du modèle de base et de valeurs delta spécifiques aux jetons, entraînables.
CPT est utile lorsque vous disposez d’un prompt contenant des instructions accompagnées d’exemples et de valeurs de référence/étiquettes. Les instructions peuvent être sous-optimales et bénéficier donc d’une optimisation pendant l’entraînement (comme avec le prompt tuning), mais les exemples/étiquettes inclus dans le prompt ne doivent pas changer. Cela peut être imposé en définissant explicitement où le prompting se termine et où les exemples commencent. CPT ajoute également une perte de jeton à la perte de prédiction du jeton suivant standard de votre modèle pour les exemples du prompt afin de tirer le meilleur parti des exemples fournis.
CPT utilise cinq identifiants de type différents pour marquer les différentes sections du prompt :
- 0 : séparateur : sera complètement ignoré, utile pour les jetons de début/fin de phrase
- 1: marqueur d'entrée : jetons décrivant l'invite qui marque le modèle complet du côté de l'entrée, y compris les informations supplémentaires
- 2: requête d'entrée : jetons décrivant l'entrée utilisateur d'un exemple
- 3 : marqueur de sortie : jetons décrivant le début de la sortie attendue d'un exemple
- 4: label: jetons appartenant à l'étiquette de l'exemple
Cela reste très abstrait, voici donc un exemple de prompt CPT et les identifiants de type correspondants. Nous supposons que chaque mot = 1 jeton pour simplifier :
prompt_text = "Example 1: Input: 1+1 Answer: 2 Example 2: 1+3 Answer: 4"
token_ids = [15, 2, 11, 9, 1, 9, 11, 3, 11, 8, 9, 4, 2, 4, 9, 11, 3, 6, 8, 9, 10]
# BOS, Example 1 : Input : 1 + 1 Answer : 2 Example 2 : 1 + 3 Answer : 4
type_ids = [0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8]
# 1, 1, 1, 2, 2, 2, 3, 3, 4Les token_ids sont votre invite encodée par le tokenizer du modèle de base et correspondent à ~CPTConfig.cpt_token_ids. Les type_ids sont les identifiants de type de jeton de l’invite, définissant les différentes sections de l’invite et correspondant à ~CPTConfig.cpt_tokens_type_mask.
Les identifiants individuels ont des effets différents sur le processus d'entraînement :
- 0 : sera complètement ignoré, ne contribue pas à la perte et ces jetons ne sont pas entraînés, utile pour les jetons qui sont simplement présents pour des raisons techniques et qui, autrement, élargiraient inutilement l’espace des paramètres (par exemple, les jetons EOS)
- 1 et 3 : ces jetons sont pris en compte pour le formatage et la norme maximale de leur delta d’incorporation est contrôlée par
opt_projection_format_epsilon(). La norme contrôle l’amplitude maximale dans laquelle les deltas d’incorporation appris pour ce type peuvent pointer. Des normes plus élevées impliquent un potentiel de changement de sens plus important. - 2 : ces jetons sont pris en compte pour l’entrée d’un exemple et la norme maximale de leur delta d’incorporation est contrôlée par
opt_projection_epsilon(). La norme contrôle l’amplitude maximale dans laquelle les deltas d’incorporation appris pour ce type peuvent pointer. Des normes plus élevées impliquent un potentiel de changement de sens plus important. - 4 : Les jetons d’étiquette du prompt sont ajoutés comme cibles supplémentaires de prédiction du jeton suivant à la perte standard sur vos données d’entraînement ; tous les autres jetons de prompt doux sont masqués dans la perte. Les plongements de différence des jetons d’étiquette ne sont jamais modifiés afin de préserver la sémantique des étiquettes.
Vous avez peut-être remarqué que les nombres dans type_ids pour le deuxième exemple sont décalés de 4. CPT applique un pondération exponentielle à la perte des exemples fournis dans le prompt, l’exemple le plus récent étant le moins atténué et la perte de l’exemple le plus ancien étant la plus atténuée. Cela accorde un poids plus important aux exemples proches de la requête d’entrée réelle et est contrôlé par opt_loss_decay_factor() lorsque opt_weighted_loss_type() est défini sur "decay". En décalant les exemples de 4, nous pouvons énumérer les différents exemples afin que la perte puisse attribuer des pondérations d’atténuation distinctes à chaque exemple.
Notez que cpt_tokens_type_mask ne décrit que le soft prompt lui-même. Lors de l’entraînement, passez également un tenseur input_type_mask avec chaque lot, en attribuant des identifiants de type aux jetons de votre entrée réelle (en utilisant les identifiants 0-4 comme ci-dessus, avec les jetons de bourrage ou de fin de phrase marqués comme 0). CPT décale automatiquement ces identifiants du nombre d’exemples dans votre prompt, vous n’avez donc pas besoin de les décaler vous-même. Cela équivaut alors à ajouter l’entrée à la fin de votre liste d’exemples dans le prompt. Gardez à l’esprit que les identifiants sont interprétés modulo 4 : les décaler d’un multiple de 4 est sans effet, mais tout autre décalage modifie silencieusement les jetons qui contribuent à la perte. Si aucun input_type_mask n’est passé, CPT se rabat sur le calcul de la perte sur toute la séquence d’entrée, c’est-à-dire en supposant le type 4 pour tous les jetons d’entrée.
Aperçu des benchmarks
Aucun benchmark n'existe encore pour cette méthode. N'hésitez pas à contribuer une configuration d'expérience, mais assurez-vous d'abord de créer un ticket ici.
API
CPTConfig
classe peft.CPTConfig
< 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 = Falsenum_virtual_tokens: int = Nonetoken_dim: int = Nonenum_transformer_submodules: Optional[int] = Nonenum_attention_heads: Optional[int] = Nonenum_layers: Optional[int] = Nonemodules_to_save: Optional[list[str]] = Nonecpt_token_ids: list[int] | None = Nonecpt_mask: list[int] | None = Nonecpt_tokens_type_mask: list[int] | None = Noneopt_weighted_loss_type: typing.Literal['none', 'decay'] | None = 'none'opt_loss_decay_factor: float | None = 1.0opt_projection_epsilon: float | None = 0.1opt_projection_format_epsilon: float | None = 0.1tokenizer_name_or_path: str | None = None )
Classe de configuration CPT héritant de PeftConfig pour le Context-aware Prompt Tuning (CPT).
Cette classe introduit des paramètres supplémentaires requis pour le CPT, tels que :
- Masques de types de jetons
- Initialisation du prompt tuning
- Pondération de la perte
- Paramètres de projection
Pour plus de détails, consultez l’article : https://huggingface.co/papers/2410.17222
CPTEmbedding
CPTEmbedding est une couche d’embedding personnalisée conçue pour le Context-aware Prompt Tuning (CPT) dans PEFT. Elle initialise les embeddings, applique des projections spécifiques aux prompts et calcule la perte à l’aide de masques d’étiquettes.
calculate_loss
< source >( base_model_outputlabelscpt_type_maskconfig ) → ModelOutput
Paramètres
- base_model_output (ModelOutput) — Sortie du modèle de base contenant les logits.
- labels (torch.Tensor) — Étiquettes de référence pour les jetons d'entrée.
- cpt_type_mask (torch.Tensor) — Masque de type de jeton utilisé pour filtrer les termes de perte valides.
- config (Namespace) — Configuration object containing loss-related hyperparameters.
Retourne
ModelOutput
La sortie du modèle de base avec la perte calculée.
Calcule la perte pour les modèles CPT avec un décodage exponentiel facultatif.
forward
< source >( indices ) → torch.Tensor
Calcule les embeddings du prompt et applique les ajustements delta.
Applique une projection basée sur epsilon aux embeddings delta pour contrôler leur norme.
Configure un hook de rétropropagation pour mettre à jour sélectivement les gradients des jetons en fonction du masque de type de jeton CPT.