Prompt Tuning
Настройка промпта адаптирует замороженную модель к задаче, обучая несколько мягких векторов промпта, добавляемых к входным данным, чтобы одна модель могла решать множество задач.
Настройка промпта адаптирует предварительно обученную базовую модель к новой задаче, обучая небольшой набор векторов, называемый мягким промптом и размещаемый перед входными данными, в то время как все веса модели остаются замороженными. Мягкий промпт существует в том же пространстве, что и эмбеддинги токенов модели, но его векторы обучаются с помощью обратного распространения ошибки и не обязаны соответствовать реальным словам. Brian Lester, Rami Al-Rfou и Noah Constant из Google представили этот метод в работе The Power of Scale for Parameter-Efficient Prompt Tuning, опубликованной на EMNLP 2021. Они отметили, что для настройки модели T5-XXL с 11 миллиардами параметров достаточно промпта из пяти токенов, которому требуется всего 20 480 параметров на задачу, и показали: по мере роста моделей до миллиардов параметров и выше точность настройки промпта сравнивается с точностью настройки всей модели.
Как работает настройка промптов#
Большая языковая модель (LLM) преобразует каждый входной токен в вектор-эмбеддинг, прежде чем тот попадёт в слои трансформера. Настройка промпта добавляет к последовательности k дополнительных векторов; Lester и коллеги проверяли длину от 1 до 150 и по умолчанию использовали 100. Во время обучения функция потерь задачи передаётся обратным распространением через замороженную сеть вплоть до входа, а оптимизатор обновляет только векторы промпта. В результате для каждой задачи получается небольшой тензор. Поскольку сама модель не меняется, удаление промпта восстанавливает исходное поведение без риска катастрофического забывания, а одна развёрнутая копия может одновременно обслуживать множество задач: каждый запрос в пакете получает собственный мягкий промпт. Lester и коллеги называют это инференсом со смешанными задачами.
В следующем примере на PyTorch настраивается мягкий промпт из 8 векторов для анализа тональности на замороженной GPT-2 из Transformers от Hugging Face: используются четыре обучающих отзыва и восемь отложенных отзывов.
import torch
from torch.nn.functional import cross_entropy
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2").requires_grad_(False) # freeze all 124M weights
embed = model.get_input_embeddings()
# Soft prompt: 8 trainable vectors in GPT-2's embedding space, initialized from the word " review"
soft_prompt = torch.nn.Parameter(embed.weight[tokenizer.encode(" review")].repeat(8, 1).clone())
optimizer = torch.optim.Adam([soft_prompt], lr=0.01)
labels = tokenizer.encode(" positive negative") # token ids for label 0 and label 1
# Reviews alternate between positive (label 0) and negative (label 1)
train = ["Loved every minute.", "A waste of time.", "Great story and acting.", "Boring and slow."]
test = ["What a wonderful film.", "I fell asleep halfway.", "A fantastic ending.", "Terrible dialogue."]
test += ["A joy to watch.", "Dull and predictable.", "Superb from start to end.", "I want my money back."]
def label_scores(text):
"""Score both label tokens after the soft prompt and the review."""
ids = tokenizer.encode(f"{text} Sentiment:", return_tensors="pt")
return model(inputs_embeds=torch.cat([soft_prompt[None], embed(ids)], dim=1)).logits[0, -1, labels]
def correct():
"""Count held-out reviews whose higher-scoring label is right."""
with torch.no_grad():
return sum(int(label_scores(text).argmax()) == i % 2 for i, text in enumerate(test))
print(f"Held-out reviews correct before tuning: {correct()}/8")
for step in range(30):
loss = sum(cross_entropy(label_scores(text), torch.tensor(i % 2)) for i, text in enumerate(train))
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"After tuning: {correct()}/8, training {soft_prompt.numel():,} of {model.num_parameters():,} parameters")Вывод: Held-out reviews correct before tuning: 5/8, затем After tuning: 7/8, training 6,144 of 124,439,808 parameters. Тридцать шагов Adam на четырёх примерах изменили только 6 144 числа — 0,005% параметров модели; кроме того, замороженная GPT-2 правильно классифицировала ещё два ранее не встречавшихся отзыва.
Настройка префикса и визуальная настройка промпта#
Настройка промпта относится к семейству методов с непрерывными промптами в рамках параметрически эффективного дообучения (PEFT). Метод настройки префикса, разработанный Xiang Lisa Li и Percy Liang, обучает векторы, добавляемые перед каждым слоем трансформера; они составляют около 0,1% параметров GPT-2 или BART и обеспечивают результаты на уровне полного дообучения для генерации текста по таблицам и суммаризации. Настройка промпта упрощает этот подход, обучая векторы только на входном слое.
Эту идею можно применить и к компьютерному зрению. Метод визуальной настройки промпта (VPT), разработанный Menglin Jia и коллегами, добавляет обучаемые токены к токенам патчей замороженного визуального трансформера (ViT), обучая менее 1% параметров, и превосходит полное дообучение во многих сценариях классификации изображений. Для визуально-языковых моделей метод оптимизации контекста (CoOp), разработанный Kaiyang Zhou и коллегами, заменяет написанные вручную слова в промпте CLIP, например «фотография», обучаемыми векторами. На 11 наборах данных CoOp превзошёл промпты, созданные вручную, при наличии одного или двух размеченных примеров на класс, а при 16 примерах на класс улучшил результат в среднем примерно на 15%.
Детекторы с открытым словарём адаптируются похожим образом. Ultralytics YOLOE преобразует названия классов в эмбеддинги текстовых промптов, а в рецепте линейного зондирования для пользовательских наборов данных эмбеддинги названий классов объединяются с последним свёрточным слоем каждой ветви классификации, после чего обучаются только эти слои, а основная сеть, шея и остальные части головы остаются замороженными.
Настройка промптов и связанные методы#
- Промпт-инжиниринг: Человек составляет промпт в виде текста, иногда называемого жёстким промптом; обучение не проводится. При настройке промптов промпт обучается на размеченных данных, для чего нужен доступ к градиентам модели, поэтому метод применим к моделям с открытыми весами.
- Полное дообучение: Обновляет все веса, создавая отдельную полную копию модели для каждой задачи и рискуя вызвать катастрофическое забывание ранее приобретённых навыков. Lester и коллеги также обнаружили, что модели с настройкой промптов лучше справлялись со сдвигом домена, чем полностью дообученные модели.
- LoRA: Добавляет обучаемые матрицы низкого ранга в слои весов модели. Настройка промптов не меняет слои, а изменяет только входные данные.
- Обучение на нескольких примерах в промпте: При каждом запросе помещает размеченные примеры в контекстное окно в виде текста. Настроенный мягкий промпт хранит то, чему обучают примеры, в нескольких векторах и занимает всего k дополнительных позиций во входной последовательности.










