PEFT documentation
コンテキスト認識プロンプトチューニング: 敵対的手法によるインコンテキストラーニングの推進
コンテキスト認識プロンプトチューニング: 敵対的手法によるインコンテキストラーニングの推進

Context-Aware Prompt Tuning (CPT)は、コンテキスト埋め込みのみを洗練させることで、少ショット分類を強化するために設計されています。 このアプローチは、In-Context Learning (ICL)、Prompt Tuning (PT)、および敵対的最適化のアイデアを組み合わせ、モデルの適応をパラメータ効率が高くかつ効果的なものにすることを重視しています。 CPTでは、特定のコンテキストトークンの埋め込みのみが最適化され、モデルの残りは凍結されたままです。 過学習を防ぎ、安定性を維持するために、CPTは制御された摂動を用いて、コンテキスト埋め込みの許容される変更を定義された範囲内に制限します。 さらに、コンテキストの末尾に近い例が先行する例よりも優先される傾向があるという近接性バイアスの現象に対処するため、CPTは減衰損失係数を適用します。
論文の抄録は以下の通りです:
大規模言語モデル(LLM)は、最適化ベースのアプローチまたはインコンテキストラーニング(ICL)を用いて、フェューショットラーニングを実行できます。最適化ベースの手法は、限られたデータで多数のパラメータを更新する必要があるため、過学習に苦しむ傾向があります。一方、ICLは過学習を回避できますが、最適化ベースの手法と比較して通常は性能が劣り、デモ用サンプルの選択、順序、および形式に対して非常に敏感です。これらの課題を克服するために、ICL、プロンプトチューニング(PT)、および敵対的攻撃に着想を得た手法である、コンテキスト認識プロンプトチューニング(CPT)を導入します。CPTは、入力の前にサンプルを連結するICL戦略を基盤とし、反復的な最適化を通じてコンテキスト埋め込みを洗練させるPT類似の学習を取り入れることで拡張し、トレーニングサンプルからより深い洞察を引き出します。私たちのアプローチは、コンテキスト内のサンプルの固有の構造を考慮し、特定のコンテキストトークンを慎重に修正します。PT類似の最適化によるコンテキストの更新に加えて、CPTは敵対的攻撃から着想を得て、コンテキストに存在するラベルに基づいて入力を調整しながら、ユーザーが提供したデータの本来の価値を保持します。最適化中の堅牢性と安定性を確保するために、トークン埋め込みが元の値の近くに留まるよう制約を課す投影勾配降下法を採用し、コンテキストの品質を保護します。私たちの手法は、さまざまなLLMモデルを用いた複数の分類タスクにおいて、既存のベースラインを上回る優れた精度を示し、フェューショットラーニングにおける過学習の課題を効果的に解決しました。
CPTでモデルをトレーニングする方法を段階的に説明したExampleをご覧ください。
動作原理
Context-aware Prompt Tuning は、Prompt Tuning と同様に、任意のテキストプロンプトを選択できますが、プロンプトのトークンにのみ第二のトークン埋め込みを適用することで、このプロンプトのトークンだけが学習可能になります。CPT モデルをクエリするたびに、「ソフト」プロンプトが通常の入力の埋め込みに前置されます。CPT は、特定の部分を学習しないようにマークすることで、ソフトプロンプトを文脈化できる点で Prompt Tuning と異なります。CPT 固有のトークン埋め込み行列は、ベースモデルの埋め込み行列から初期化される静的な埋め込みと、学習可能なトークン固有のデルタ値で構成されています。
CPTは、指示と例および正解ラベル(ground-truth/labels)を含むプロンプトがある場合に有用です。指示は最適でない可能性があるため、学習中に最適化されることで恩恵を受ける場合があります(プロンプトチューニングと同様)。ただし、プロンプトに含めた例やラベルは変更されるべきではありません。これは、プロンプトの終了位置と例の開始位置を明示的に定義することで強制できます。CPTは、プロンプト内の例に対して、モデルの標準的な次のトークン予測損失にトークン損失を追加することで、与えられた例を最適に活用します。
CPTは、プロンプト内の異なるセクションをマークするために5つの異なるタイプIDを使用します:
- 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, 4token_ids は、ベースモデルのトークナイザーによってエンコードされたプロンプトであり、~CPTConfig.cpt_token_ids に対応します。type_ids はプロンプトのトークンタイプ ID であり、プロンプトの異なるセクションを定義し、~CPTConfig.cpt_tokens_type_mask に対応します。
個々のIDは、学習プロセスに対して異なる影響を与えます:
- 0: は完全に無視され、損失に寄与せず、これらのトークンは学習されません。技術的な理由で存在するだけで、それ以外の場合はパラメータ空間を無意味に拡大させるトークン(例: EOS トークン)に有用です。
- 1 と 3: これらのトークンはフォーマットのために考慮され、それらの埋め込みデルタの最大ノルムは
opt_projection_format_epsilon()によって制御されます。ノルムは、このタイプの学習済みデルタ埋め込みが指し示し得る最大の変化量を制御します。ノルムが大きいほど、意味が変化する可能性が高くなります。 - 2: これらのトークンは、例の入力として考慮され、それらの埋め込みデルタの最大ノルムは
opt_projection_epsilon()によって制御されます。ノルムは、このタイプの学習済みデルタ埋め込みが指し示し得る最大の変化量を制御します。ノルムが大きいほど、意味が変化する可能性が高くなります。 - 4: プロンプトのラベルトークンは、学習データに対する標準的なロスに、追加の次のトークン予測ターゲットとして加算されます。その他のソフトプロンプトトークンはすべて、ロスからマスクされます。ラベルの意味を維持するために、ラベルトークンのデルタ埋め込みは変更されません。
2番目の例のtype_idsの数値が4ずれていることに気づかれたかもしれません。CPTでは、プロンプトに提供した例の損失に対して指数関数的な重み付けを行います。最後の例が最も減衰しておらず、最初の例の損失が最も減衰します。これにより、実際の入力クエリに近い例に大きな重みが付けられ、opt_weighted_loss_type()が"decay"に設定されている場合、opt_loss_decay_factor()によって制御されます。例を4ずらすことで、異なる例を列挙し、損失が各例に対して異なる減衰重み付けを適用できるようにします。
cpt_tokens_type_mask はソフトプロンプト自体のみを記述している点にご注意ください。学習時には、各バッチとともに input_type_mask テンソルを渡す必要があります。このテンソルでは、実際の入力トークンにタイプ ID を割り当てます(上記と同様に ID 0-4 を使用し、パディングトークンや文の終了トークンは 0 とします)。CPT はこれらの ID をプロンプト内の例の数だけ自動的にシフトするため、ご自身でシフトする必要はありません。これにより、プロンプトの例のリストの末尾にその入力を追加したのと同じ状態になります。ID は 4 を法として解釈される点にご注意ください。4 の倍数だけシフトしても問題はありませんが、それ以外のオフセットを適用すると、損失計算に寄与するトークンが静かに変更されてしまいます。input_type_mask が渡されない場合、CPT は入力シーケンス全体で損失を計算する処理にフォールバックします。つまり、すべての入力トークンをタイプ 4 と仮定します。
ベンチマーク概要
この手法のベンチマークはまだありません。実験設定の貢献は歓迎しますが、まずこちらでイシューを作成してください。
API
CPTConfig
クラス 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 )
Context-aware Prompt Tuning (CPT) 用の PeftConfig を拡張する CPT 設定クラス。
このクラスは、CPTに必要な追加のパラメータ、例えば以下のようなものを導入します:
- トークンタイプマスク
- プロンプトチューニングの初期化
- 損失の重み付け
- Projection設定
詳細については、論文を参照してください: https://huggingface.co/papers/2410.17222
CPTEmbedding
CPTEmbedding は、PEFT における Context-aware Prompt Tuning (CPT) 用に設計されたカスタムな埋め込みレイヤーです。埋め込みを初期化し、プロンプト固有の射影を適用し、ラベルマスクを使用して損失を計算します。
calculate_loss
< source >( base_model_outputlabelscpt_type_maskconfig ) → ModelOutput
オプションの指数減衰付きで、CPTモデルの損失を計算します。
forward
< source >( indices ) → torch.Tensor
プロンプトの埋め込みを計算し、デルタ調整を適用します。
epsilonベースの射影をdelta埋め込みに適用し、そのノルムを制御します。
CPTトークンタイプマスクに基づいて、トークン勾配を選択的に更新するためのバックワードフックを設定します。