Prompt Tuning
プロンプトチューニングは、入力に追加する少数のソフトプロンプトベクトルを学習し、重みを固定したモデルを特定のタスクに適応させます。これにより、1つのモデルで多くのタスクに対応できます。
プロンプトチューニングでは、事前学習済みの基盤モデルに新しいタスクを適応させるため、ソフトプロンプトと呼ばれる少数のベクトルを学習します。すべてのモデルの重みを固定したまま、ソフトプロンプトを入力の前に配置します。ソフトプロンプトはモデルのトークン埋め込みと同じ空間にありますが、ベクトルは誤差逆伝播によって学習され、実在する単語に対応する必要はありません。GoogleのBrian Lester、Rami Al-Rfou、Noah Constantは、EMNLP 2021で発表したThe Power of Scale for Parameter-Efficient Prompt Tuningでこの手法を紹介しました。彼らは、110億パラメーターのT5-XXLモデルに5トークンのプロンプトを使う場合、タスクごとに必要なパラメーターはわずか20,480個だと指摘しました。また、モデルの規模が数十億パラメーターを超えると、プロンプトチューニングはモデル全体をチューニングする場合と同等の精度を実現することを示しました。
プロンプトチューニングの仕組み#
大規模言語モデル(LLM)は、各入力tokenを埋め込みベクトルに変換してから、Transformer層に渡します。プロンプトチューニングでは、このシーケンスの先頭にk個のベクトルを追加します。Lesterらは長さ1~150を検証し、デフォルトで100を使用しました。学習中は、タスクの損失関数を固定されたネットワーク全体に逆伝播し、オプティマイザーはプロンプトベクトルのみを更新します。その結果、タスクごとに小さなテンソルが得られます。モデル自体は変更されないため、プロンプトを削除すれば破滅的忘却のリスクなしに元の動作へ戻せます。また、1つのデプロイ済みコピーで複数のタスクを同時に処理できます。バッチ内の各リクエストが独自のソフトプロンプトを持つこの方式を、Lesterらは混合タスク推論と呼んでいます。
次のPyTorchの例では、Hugging Face Transformersの固定されたGPT-2に対し、学習レビュー4件と評価用レビュー8件を使って、感情分析用の8ベクトルのソフトプロンプトをチューニングします。
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が出力されます。4つの例に対するAdamの30ステップの学習で変更されたのは6,144個の数値だけで、モデル全体の0.005%に相当します。固定されたGPT-2は、未見のレビューをさらに2件正しく分類しました。
Prefix TuningとVisual Prompt Tuning#
プロンプトチューニングは、パラメーター効率の高いファインチューニング(PEFT)に属する連続プロンプト手法の一種です。Xiang Lisa LiとPercy LiangのPrefix Tuningでは、Transformerの各層の先頭に追加するベクトルを学習します。GPT-2またはBARTのパラメーターの約0.1%を使い、テーブルからテキストへの生成と要約で、完全なファインチューニングと同等の性能を実現しました。プロンプトチューニングでは、入力層だけでベクトルを学習することで、この方法を簡略化しています。
この考え方はビジョンにも応用できます。Menglin JiaらのVisual Prompt Tuning(VPT)では、固定されたVision Transformer(ViT)のパッチトークンの前に学習可能なトークンを追加し、パラメーターの1%未満を学習します。多くの画像分類設定で、完全なファインチューニングを上回りました。ビジョン言語モデルでは、Kaiyang ZhouらのContext Optimization(CoOp)が、「a photo of a」などのCLIPプロンプトにおける手書きの単語を、学習したベクトルに置き換えます。11個のデータセットで、クラスごとにラベル付き例が1~2件の場合、CoOpは手作業で作成したプロンプトを上回りました。クラスごとに16例を使うと、平均で約15%改善しました。
オープンボキャブラリー検出器も関連する方法で適応します。Ultralytics YOLOEはクラス名をテキストプロンプトの埋め込みに変換します。カスタムデータセット向けの線形プロービング手法では、データセットのクラス名の埋め込みを各分類ブランチの最終畳み込み層に統合し、その層だけを学習します。バックボーン、ネック、ヘッドの残りの部分は固定されたままです。
プロンプトチューニングと関連手法#
- プロンプトエンジニアリング: 人がハードプロンプトとも呼ばれるテキスト形式のプロンプトを作成し、学習は行いません。プロンプトチューニングではラベル付きデータからプロンプトを学習するため、モデルの勾配へのアクセスが必要であり、オープンウェイトモデルに適用されます。
- 完全なファインチューニング: すべての重みを更新し、タスクごとにモデル全体のコピーを作成するため、以前の能力を破滅的忘却するリスクがあります。Lesterらは、プロンプトチューニング済みモデルのほうが、完全にチューニングしたモデルよりもドメインシフトに強いことも示しました。
- LoRA: モデルの重み層に学習可能な低ランク行列を追加します。プロンプトチューニングでは層に手を加えず、入力だけを変更します。
- プロンプト内のFew-shot学習: ラベル付きの例をテキストとして、リクエストごとにコンテキストウィンドウへ入れます。チューニング済みのソフトプロンプトでは、例から得た情報を少数のベクトルに保存でき、追加される入力位置はk個だけです。










