PEFT documentation

Контекстно-зависимая настройка промптов: развитие обучения в контексте с помощью противоречивых методов

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

Контекстно-зависимая настройка промптов: развитие обучения в контексте с помощью противоречивых методов

CPT optimizing only specific token embeddings while keeping the rest of the model frozen (image source).

Context-Aware Prompt Tuning (CPT) предназначен для улучшения классификации в режиме few-shot за счёт оптимизации только контекстных эмбеддингов. Этот подход объединяет идеи из In-Context Learning (ICL), Prompt Tuning (PT) и противоречивой оптимизации, фокусируясь на том, чтобы сделать адаптацию модели одновременно параметрически эффективной и результативной. В CPT оптимизируются только эмбеддинги определённых контекстных токенов, тогда как остальные части модели остаются замороженными. Чтобы предотвратить переобучение и сохранить стабильность, CPT использует контролируемые возмущения, ограничивая допустимые изменения контекстных эмбеддингов в заданном диапазоне. Кроме того, для борьбы с явлением recency bias — когда примеры, расположенные ближе к концу контекста, получают приоритет над более ранними, — CPT применяет коэффициент затухания потерь.

Аннотация из статьи:

Большие языковые модели (LLMs) способны выполнять обучение с малым количеством примеров (few-shot learning), используя либо методы на основе оптимизации, либо обучение в контексте (In-Context Learning, ICL). Методы на основе оптимизации часто страдают от переобучения, поскольку требуют обновления большого числа параметров при ограниченных данных. В отличие от них, ICL избегает переобучения, но, как правило, уступает по эффективности методам на основе оптимизации и крайне чувствителен к выбору, порядку и формату демонстрационных примеров. Чтобы преодолеть эти трудности, мы предлагаем метод контекстно-зависимой настройки промптов (Context-aware Prompt Tuning, CPT), вдохновленный ICL, настройкой промптов (Prompt Tuning, PT) и атаками на основе антагонистических примеров. CPT строится на стратегии ICL, заключающейся в конкатенации примеров перед входными данными, и расширяет ее, включая обучение в стиле PT для уточнения контекстного эмбеддинга посредством итеративной оптимизации, что позволяет извлекать более глубокие сведения из обучающих примеров. Наш подход тщательно модифицирует определенные токены контекста, учитывая уникальную структуру примеров внутри контекста. Помимо обновления контекста с помощью оптимизации в стиле PT, CPT черпает вдохновение в атаках на основе антагонистических примеров, корректируя входные данные на основе меток, присутствующих в контексте, при этом сохраняя внутреннюю ценность данных, предоставленных пользователем. Для обеспечения робастности и стабильности в процессе оптимизации мы применяем алгоритм проекционного градиентного спуска, ограничивая эмбеддинги токенов так, чтобы они оставались близкими к своим исходным значениям, что защищает качество контекста. Наш метод продемонстрировал более высокую точность на нескольких задачах классификации с использованием различных моделей LLM, превзойдя существующие базовые методы и эффективно решив проблему переобучения при обучении с малым количеством примеров.

Ознакомьтесь с примером, где пошагово описано, как обучить модель с помощью CPT.

Принцип работы

Context-aware Prompt Tuning похож на Prompt Tuning тем, что вы можете использовать текстовый промпт на ваш выбор, но сделать обучаемыми токены именно этого промпта (и только его) за счёт наличия второй матрицы эмбеддингов токенов, применяемой исключительно к токенам промпта. При запросе к модели CPT ваш «мягкий» промпт добавляется в начало эмбеддинга вашего обычного входного текста. Отличие CPT от Prompt Tuning состоит в том, что теперь ваш мягкий промпт может быть контекстуализирован путём пометки конкретных частей как необучаемых. Специфичная для CPT матрица эмбеддингов токенов состоит из статического эмбеддинга, инициализированного из матрицы эмбеддингов базовой модели, и обучаемых дельта-значений, специфичных для каждого токена.

CPT полезен, когда у вас есть промпт с инструкциями, примерами и эталонными данными/метками. Инструкции могут быть неоптимальными и, следовательно, выигрывают от оптимизации в процессе обучения (как при prompt tuning), но примеры/метки, которые вы включили в промпт, не должны изменяться. Это можно обеспечить, явно определив, где заканчивается промпт и начинаются примеры. CPT также добавляет потерю токенов к стандартной потере предсказания следующего токена вашей модели для примеров в промпте, чтобы максимально эффективно использовать предоставленные примеры.

CPT использует пять различных идентификаторов типов для разметки разных разделов в промпте:

  • 0: separator: полностью игнорируется, полезно для токенов начала/конца предложения
  • 1: маркер входа: токены, описывающие подсказку, которая обозначает весь шаблон входной стороны, включая дополнительную информацию
  • 2: входной запрос: токены, описывающие пользовательский ввод примера
  • 3: маркер вывода: токены, описывающие начало ожидаемого вывода примера
  • 4: label: токены, относящиеся к метке примера

Это довольно абстрактно, поэтому ниже приведён пример промпта CPT и соответствующие идентификаторы типов. Для простоты предположим, что каждое слово = 1 токен:

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,  4

token_ids — это ваш промпт, закодированный токенизатором базовой модели, и он соответствует ~CPTConfig.cpt_token_ids. type_ids — это идентификаторы типов токенов промпта, определяющие различные разделы промпта, и они соответствуют ~CPTConfig.cpt_tokens_type_mask.

Каждый из идентификаторов оказывает различное влияние на процесс обучения:

  • 0: полностью игнорируется, не вносит вклад в функцию потерь, и эти токены не обучаются; полезно для токенов, которые присутствуют исключительно по техническим причинам и в противном случае бесполезно расширяли бы пространство параметров (например, токены EOS)
  • 1 и 3: эти токены учитываются при форматировании, а максимальная норма их дельта-эмбеддингов контролируется функцией opt_projection_format_epsilon(). Норма определяет максимальную величину, в пределах которой обученные дельта-эмбеддинги этого типа могут быть направлены. Чем выше норма, тем выше потенциальное изменение смысла.
  • 2: эти токены учитываются при вводе примера, а максимальная норма их дельта-эмбеддингов контролируется функцией opt_projection_epsilon(). Норма определяет максимальную величину, в пределах которой обученные дельта-эмбеддинги данного типа могут быть направлены. Чем выше норма, тем выше потенциальное изменение смысла.
  • 4: Токены метки из промпта добавляются в качестве дополнительных целей предсказания следующего токена к стандартной функции потерь на данных обучения; все остальные токены мягкого промпта маскируются в функции потерь. Дельта-эмбеддинги токенов метки никогда не изменяются, чтобы сохранить семантику меток.

Вы могли заметить, что числа в type_ids для второго примера сдвинуты на 4. CPT использует экспоненциальное взвешивание для потерь примеров, которые вы предоставляете в промпте: последний пример имеет наименьшее затухание, а потеря первого примера затухает сильнее всего. Это придаёт больший вес примерам, расположенным ближе к фактическому входному запросу, и управляется параметром opt_loss_decay_factor(), когда opt_weighted_loss_type() установлено в "decay". Сдвигая примеры на 4, мы можем пронумеровать различные примеры так, чтобы функция потерь могла назначать каждому из них различные веса затухания.

Обратите внимание, что cpt_tokens_type_mask описывает только сам soft prompt. Во время обучения дополнительно передавайте тензор input_type_mask вместе с каждой партией, назначая идентификаторы типов токенам вашего фактического входа (используя идентификаторы 0–4, как описано выше, при этом токены padding или end-of-sentence помечаются как 0). CPT автоматически сдвигает эти идентификаторы на количество примеров в вашем prompt, поэтому вам не нужно выполнять сдвиг самостоятельно. Это эквивалентно добавлению входа в конец списка примеров в prompt. Помните, что идентификаторы интерпретируются по модулю 4: сдвиг на кратное 4 безвреден, но любое другое смещение незаметно меняет набор токенов, участвующих в вычислении loss. Если input_type_mask не передан, CPT вычисляет loss по всей последовательности входа, то есть предполагая тип 4 для всех входных токенов.

Обзор бенчмарков

Пока для этого метода нет бенчмарка. Вы можете внести свой вклад, предоставив конфигурацию эксперимента, но сначала создайте задачу здесь.

API

CPTConfig

класс peft.CPTConfig

< >

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

Класс конфигурации CPT, расширяющий PeftConfig для контекстно-зависимой настройки промптов (CPT).

Этот класс вводит дополнительные параметры, необходимые для CPT, такие как:

  • Маски типов токенов
  • Инициализация prompt tuning
  • Взвешивание потерь
  • Настройки проекции

Подробнее в статье: https://huggingface.co/papers/2410.17222

CPTEmbedding

класс peft.CPTEmbedding

< >

( configword_embeddings )

CPTEmbedding — это собственный слой эмбеддингов, разработанный для Context-aware Prompt Tuning (CPT) в PEFT. Он инициализирует эмбеддинги, применяет проекции, специфичные для промпта, и вычисляет потерю с использованием масок меток.

calculate_loss

< >

( base_model_outputlabelscpt_type_maskconfig ) → ModelOutput

Параметры

  • base_model_output (ModelOutput) — Вывод базовой модели, содержащий логиты.
  • labels (torch.Tensor) — Эталонные метки для входных токенов.
  • cpt_type_mask (torch.Tensor) — Маска типов токенов, используемая для фильтрации валидных членов функции потерь.
  • config (Namespace) — Объект конфигурации, содержащий гиперпараметры, связанные с функцией потерь.

Возвращает

ModelOutput

Выход базовой модели с вычисленной потерей.

Вычисляет потерю для моделей CPT с необязательным экспоненциальным затуханием.

forward

< >

( indices ) → torch.Tensor

Параметры

  • indices (torch.Tensor) — Индексы токенов, подлежащих встраиванию.

Возвращает

torch.Tensor

Сумма эмбеддингов промпта и дельта-эмбеддингов.

Вычисляет эмбеддинги промпта и применяет дельта-корректировки.

get_projection

< >

( )

Применяет проекцию на основе эпсилона к дельта-эмбеддингам для контроля их нормы.

set_updated_tokens

< >

( )

Устанавливает обратный хук для выборочного обновления градиентов токенов на основе маски типа токенов CPT.

Update on GitHub