PEFT documentation
ShadowPEFT
ShadowPEFT
ShadowPEFT は、凍結されたベースのデコーダー専用モデルに、バックボーンと並列で動作する軽量で事前学習可能なシャドウネットワークを追加します。小さなシャドウバックボーンが初期のシャドウ状態s^(0)を生成し、これがベースモデルのデコーダーループに沿って進みます。対象とされた各ブロックにおいて、ベースの隠れ状態とシャドウ状態の間の差分がブロック入力に注入されます(低ランク補正)。その後、ブロック出力から計算されるゲート付き残差更新によって、シャドウ状態が更新されます。学習されるのはシャドウコンポーネントのみであり、ベースモデルは凍結されたままです。
Input
├──► Shadow backbone (small, trainable) ──► s^(0)
└──► Base model (frozen, large)
block_0 ◄── inject(h, s) ─► h_0 ──► update ─► s_1
block_1 ◄── inject(h, s) ─► h_1 ──► update ─► s_2
... (the (hidden, shadow) pair rides the loop together)適応は静的な重み空間のデルタではなく、レイヤー空間における入力依存の軌跡(シャドウ状態がデータとともに進化します)であるため、ShadowPEFTはベースの重みにマージできません。merge、merge_adapter、またはmerge_and_unloadを呼び出すと、明示的なエラーが発生します。Transformersの言語モデルでは、model.base_model.unload_shadow()を呼び出すことで、軽量なシャドウネットワークを単独で取得できます。このメソッドは、独立したDetachedShadowModelを返します。Diffusersモデルでは、完全なデノイザーの再構築がアーキテクチャに依存するため、単独でのアンロードはサポートされていません。
複数のアダプターを追加し、set_adapterで切り替え、削除し、有効化/無効化することは、他のPEFTメソッドと同様に動作します。シャドウ状態はネットワークを通過する単一の軌跡であるため、同時にアクティブなアダプターは1つだけです。
シャドウバックボーンは、ShadowConfig.shadow_modelによって制御される2つの方法で構築できます。
"mirror"(デフォルト):より小さいシャドウバックボーンが自動的に作成されます。言語モデルでは、ベースアーキテクチャの縮小コピーが使用されます。バックエンドが登録されているDiffusersアーキテクチャでは、選択されたベースの重みから初期化された、縮小された類似アーキテクチャのモデルが使用されます。バックエンドのない互換性のあるアーキテクチャでは、トークンごとの残差MLPにフォールバックします。シャドウの隠れ層サイズがベースと異なる場合、学習済みの射影がその差を埋めます。- モデルIDまたはローカルパス: バックボーンは、より小さい事前学習済みモデルとして読み込まれます。Transformersモデルは
AutoModelを使用し、登録済みのDiffusersバックエンドは、互換性のあるチェックポイントの読み込みを独自に定義します。
アーキテクチャ対応のDiffusersサポートは、モデルクラスから自動的に選択されます。Flux2には現在、登録されたバックエンドがあります。その他の互換性のあるtransformerベースのDiffusersモデルは、汎用のMLPフォールバックを使用します。完全なデノイザーの再構築はアーキテクチャ固有であるため、すべてのDiffusersモデルにおいて、単独のunload_shadow()はサポートされていません。
LoRA方式の手法と比較すると、ShadowPEFTはより多くのパラメータと計算量(並列ネットワークを実行し、デコーダーブロック全体をラップする)を必要としますが、アダプターは自己完結型のネットワークであり、中央で学習でき、タスク間で再利用でき、事前学習済み的小型モデルから初期化できます。任意の補助損失(auxiliary_loss_weight)は、タスクヘッドを初期シャドウ状態 s^(0) に適用し、タスク損失に追加することで、分離可能なシャドウパスが単独でタスクを解決することを促します。因果言語モデルの場合、ベースの出力ヘッドが再利用されます。標準的なPEFTメカニズムを通じてこれを学習・保存するには、modules_to_save に "lm_head" を含めてください。
KVキャッシュ
ShadowPEFT は、dual KV キャッシュによる増分デコードをサポートしています。これは、凍結されたベースモデル用とシャドウバックボーン用の2つのキャッシュです。注入/更新はトークンローカルであるため、新しいトークンには自身のシャドウ状態 s だけで十分です。因果性により、プレフィックスのベースキー/バリュー(注入下で計算されたもの)が有効に保たれます。ペアとなるオブジェクトは ShadowCache で、use_cache=True の場合、past_key_values として返されます。generate() に use_cache=True を渡すことも通常通り可能です。
out = model.generate(input_ids, max_new_tokens=32) # dual KV cache enabled by default
# or explicitly:
out = model.generate(input_ids, use_cache=True, max_new_tokens=32)use_cache=False は引き続き動作し、各ステップでシーケンス全体を再処理します(デバッグに有用です)。
使用方法
from transformers import AutoModelForCausalLM
from peft import ShadowConfig, get_peft_model
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-0.6B")
config = ShadowConfig(r=8, shadow_num_hidden_layers=1, task_type="CAUSAL_LM")
model = get_peft_model(model, config)
model.print_healthcheck()
out = model.generate(input_ids, max_new_tokens=32)より小さい事前学習済みモデルからシャドウバックボーンを初期化するには、そのidまたはパスをshadow_modelとして渡します:
config = ShadowConfig(shadow_model="Qwen/Qwen3-0.6B", task_type="CAUSAL_LM")
model = get_peft_model(base_model, config)シャドウパスの評価
デフォルトでは、モデルの出力(logits)はシャドウ適応ベースモデルのものです。シャドウ補正が各層のベースモデルの隠れ状態に注入されるため、logitsにはすでにShadowPEFTが反映されています(比較のためにプレーンなベースモデルを取得するにはmodel.disable_adapter()を使用してください)。補助損失は、シャドウパスがタスクを単独で解決できるように訓練します。
Transformers の言語モデルにおけるスタンドアロンシャドウネットワーク(分離可能な軽量モデル — merge_and_unload の ShadowPEFT 相当)を評価するには、unload_shadow() を使用します。このメソッドは、head(projection(backbone(x))) を通常のタスクモデルとして返します。他のモデルと同様に評価できます。causal-LM タスクの場合、生成機能を持つ causal LM(generate() および KV キャッシングをサポート)となり、シーケンス分類タスクの場合、最後のトークンをプーリングしてクラス logits を返します。Diffusers モデルに対してこのメソッドを呼び出すと、NotImplementedError が発生します。
shadow = model.base_model.unload_shadow() # a DetachedShadowModel (a PreTrainedModel)
shadow.eval()
# causal LM:
out = shadow.generate(input_ids, max_new_tokens=32)
# sequence classification:
logits = shadow(input_ids=input_ids, attention_mask=attention_mask).logits # (batch, num_labels)デフォルトでは(copy=False)、返されるモデルは PEFT モデルとモジュールを共有し、凍結されたベースの入力埋め込みを共有するシャドウバックボーンが、サブモジュールではない参照を通じてそれらに到達します。評価のためには問題ありませんが、save_pretrained は埋め込みテーブルなしでチェックポイントを保存することになります。独立したモデルを保存またはプッシュする場合は、copy=True を渡してください。
shadow = model.base_model.unload_shadow(copy=True)
shadow.save_pretrained("standalone-shadow")API
ShadowConfig
クラス peft.ShadowConfig
< 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 = Falsetarget_modules: list[str] | str | None = Noneexclude_modules: list[str] | str | None = Noner: int = 8shadow_alpha: float = 0.1shadow_dropout: float = 0.2init_weights: bool = Trueshadow_model: str = 'mirror'shadow_num_hidden_layers: int | None = Noneshadow_hidden_size: int | None = Noneshadow_num_attention_heads: int | None = Noneshadow_intermediate_size: int | None = Noneshare_embeddings: bool = Trueupdate_hidden_size: int | None = Noneauxiliary_loss_weight: float = 0.05layers_to_transform: list[int] | int | None = Nonelayers_pattern: list[str] | str | None = Nonemodules_to_save: list[str] | None = None )
パラメータ
- target_modules (
Optional[Union[list[str], str]]) — シャドウ機構でラップする Transformer ブロック(線形層ではなく、デコーダーブロック全体)です。モジュール名のリスト、または正規表現を指定できます。例えば、r'.*\.layers\.\d+$'を指定すると、すべてのデコーダーブロックを対象とします。デフォルトはNoneで、この場合、ベースモデルのすべてのデコーダーブロックがラップされます。ラップされるブロックは連続している必要があります。シャドウ状態は、最初のラップされたブロックから最後のブロックまで、デコーダーのループに沿って伝搬するためです。 - exclude_modules (
Optional[Union[list[str], str]]) — シャドウ機構でラップしないモジュールの名前を、リストまたは正規表現として指定します。デフォルトはNoneです。 - r (
int) — 低ランク注入ボトルネックW_down/W_upのランクです。デフォルト値は8です。 - shadow_alpha (
float) — ブロック入力に追加される注入補正の強度(式 4)。デフォルト値は0.1です。 - shadow_dropout (
float) — ボトルネック(式 3)の前に適用される不一致シグナルのドロップアウト確率です。デフォルト値は0.2です。 - init_weights (
bool) —W_upをゼロ初期化して、学習開始時に注入が何もしない状態にするかどうか(LoRA のB=0の慣例に倣う)。何をしているか理解している場合を除き、変更しないでください。デフォルトはTrueです。 - shadow_model (
str) — シャドウバックボーンの構築方法。"mirror"(デフォルト)は、ベースモデルと同じアーキテクチャを持つが、レイヤー数が少なく小さい新しいバックボーンを構築します(shadow_*のオーバーライドを参照)。Shadow バックエンドが登録されている Diffusers アーキテクチャでは、縮小された類似アーキテクチャのモデルを使用し、その他の互換性のある拡散トランスフォーマーでは、汎用的なトークン単位の MLP にフォールバックします。その他の文字列は、モデル ID またはローカルパスとして扱われます。「projected」された Transformers シャドウチェックポイント(model_type == "causal_lm_with_hidden_projection"、例:shadow-llm/Qwen3-0.6B-H8B)は、事前学習済みバックボーンと、学習済みのシャドウ隠れ層 -> ベース隠れ層の射影を一緒に読み込みます。明示的な Diffusers チェックポイントには登録済みバックエンドが必要です。現在サポートされているのは Flux2 です。 - shadow_num_hidden_layers (
Optional[int]) — 自動構築される("mirror")シャドウバックボーンの深さです。Flux2 では、指定された数の double-stream ブロックと、その 2 倍の数の single-stream ブロックが作成されます。汎用的な Diffusers のフォールバックでは、残差 MLP ブロックの数を表します。デフォルトはNone(1レイヤー)です。 - shadow_hidden_size (
Optional[int]) — 自動構築されるシャドウバックボーンの隠れ層サイズです。ベースの隠れ層サイズと異なる場合があります(その場合、射影が自動的に挿入されます)。アーキテクチャのバックエンドによって追加の制約が課される可能性があります。Flux2 の縮小処理では、ベースの注意ヘッド次元を保持する必要があります。デフォルトはNone(ベースモデルと同じ)です。 - shadow_num_attention_heads (
Optional[int]) — 自動構築されるシャドウバックボーンの注意ヘッド数です。デフォルトはNone(ベースモデルと同じ)です。このオプションはアーキテクチャ対応バックエンドで使用されますが、汎用のDiffusers MLPフォールバックでは使用されません。 - shadow_intermediate_size (
Optional[int]) — 自動構築されるシャドウバックボーンのフィードフォワード幅です。デフォルトはNone(汎用のDiffusers MLPフォールバックでは、そのhidden sizeと同じ値になります)。 - share_embeddings (
bool) — シャドウバックボーンに独自の埋め込みテーブルではなく、凍結されたベースの入力埋め込みを(inputs_embedsを介して)再利用するかどうか。デフォルトはTrueです。 - update_hidden_size (
Optional[int]) —T(候補) およびG(ゲート) の更新 MLP の隠れ幅です。デフォルトはNone(rを使用) です。 - auxiliary_loss_weight (
float) —labelsが渡された場合にタスク損失に追加される、補助的なシャドウ損失(式 8-9)の重みlambdaです。Diffusion の学習ループでは、デタッチされたデノイジング損失に同じ値を使用できます。0に設定すると無効になります。デフォルト値は0.05です。 - layers_to_transform (
Optional[Union[list[int], int]]) — 変換対象のブロックのインデックスです。リストが渡された場合、そのインデックスのブロックにシャドウ機構が適用されます。単一の整数が渡された場合、そのインデックスのブロックにのみ適用されます。デフォルトはNone(一致したすべてのブロックが変換されます)。 - layers_pattern (
Optional[Union[list[str], str]]) —layers_to_transformがNoneと異なる場合にのみ使用される、レイヤーパターン名です。これは、デコーダーブロックを保持するnn.ModuleListの名前です(多くの場合、"layers"または"h"になります)。デフォルト値はNoneです。 - modules_to_save (
Optional[list[str]]) — 最終チェックポイントに学習可能として設定し、保存する追加のモジュール(例:"lm_head"または分類ヘッド)。デフォルトはNoneです。
ShadowModel(ShadowPEFT)の設定クラスです。
ShadowPEFTは、凍結されたベースのデコーダー専用モデルに、小さな学習可能な並列シャドウネットワークを追加します。シャドウバックボーンは初期のシャドウ状態s^(0)を生成し、これがベースモデルのデコーダーループに沿って進みます。対象とされた各ブロックにおいて、ベースの隠れ状態とシャドウ状態の間の差分がブロックの入力に注入されます(式2-4)、そしてシャドウ状態はブロック出力からのゲート付き残差更新によって前進します(式5-7)。学習されるのはシャドウコンポーネントのみであり、ベースモデルは凍結されたままです。適応が静的な重み差分ではなく、レイヤー空間における入力依存の軌跡であるため、ShadowPEFTはベースの重みにマージすることはできません。
ShadowModel
クラス peft.ShadowModel
< source >( modelpeft_config: Union[PeftConfig, dict[str, PeftConfig]]adapter_name: strlow_cpu_mem_usage: bool = Falsestate_dict: Optional[dict[str, torch.Tensor]] = None )
事前学習済みのTransformersモデルからShadowPEFTモデルを作成します。
ShadowPEFTは、凍結されたベースのデコーダー専用モデルに、小さな学習可能な並列shadowネットワークを追加します。shadowバックボーンは初期のshadow状態を生成し、これがベースのデコーダーループに沿って処理されます。対象とされた各ブロックにおいて、ベースの隠れ状態とshadow状態の間の差分がそのブロックに注入され、shadow状態はゲート付き残差更新によって更新されます。学習されるのはshadowコンポーネントのみです。設定についてはShadowConfigを参照してください。
このメソッドはベースの重みにマージできません(適応は入力依存の軌跡であり、静的な重み差分ではないため);代わりに独立したシャドウネットワークを取得するには、ShadowModel.unload_shadow()を使用してください。
シャドウパス自身のタスク損失、CE(shadow_head(s^(0)), labels)(重み付けなし;forwardが重みを適用します)。
損失は、初期のシャドウ状態 s^(0)(シャドウバックボーンの出力、射影後)に対して計算されます。これは、単体で動作する unload_shadow() モデルが head(projection(backbone(x))) として計算する値と完全に一致します。この点が、デタッチされたシャドウネットワークを単独で使用可能にする理由です。もし s^(L)(ベースモデルのレイヤーごとの出力に依存し、単独では存在しない最終状態)に対して学習を行おうとすると、デタッチされたモデルは学習されません。
unload_shadow
< source >( adapter_name: str | None = Nonecopy: bool = False )
ベースモデルを含まない形で、シャドウバックボーン(+ヘッド)を独立したモデルとして返します。
merge_and_unload の ShadowPEFT 版です。merge_and_unload が適応を焼き込んだベースモデルを返すのに対し、本メソッドは高効率なエッジ推論向けに、軽量なシャドウネットワークのみを返します。head(projection(backbone(x))) を実行します。ブロックごとの更新はベースモデルの出力を必要とするため、単独では存在しません。言語モデルの場合、結果は通常の因果言語モデルとして動作し、generate() および KV キャッシュに対応します。Diffusers のモデルはサポートされていません。完全な単独のデノイザーを再構築することは、各拡散アーキテクチャ固有のためです。
結果を変数に代入して使用します。copy=Falseの場合、モジュールはこのモデルと共有されたままになります。
スタンドアロンモデルをsave_pretrainedで保存する予定がある場合は、copy=Trueを渡してください。凍結されたベースモデルの入力埋め込みを共有するシャドウバックボーン(デフォルトの"mirror"構成)は、返されるモデルのサブモジュールではない参照を通じてそれらにアクセスするため、copy=Falseのチェックポイントには埋め込みテーブルが含まれていません。copy=Trueを指定すると、プライベートなコピーが再アタッチされ、完全なチェックポイントが保存されます。
ShadowCache
増分ShadowPEFTデコーディングのためのペアリングされたKVキャッシュ。
自己回帰生成には、ベースモデルのキャッシュ(シャドウ注入下で計算されたキー/バリュー)と、独立したシャドウモデルのキャッシュ(s^(0)をトークン単位で進めるために)が必要です。これは Transformers の Cache のサブクラスであり、バッチやシーケンスのレイアウトに影響を与える操作(reset、reorder、crop、repeat、select)は両方のキャッシュに適用されますが、アテンションのメタデータや更新はベースキャッシュに委譲されます。未知のキャッシュ属性も、アーキテクチャ固有のキャッシュ実装との互換性を保つため、ベースキャッシュに委譲されます。
ラッパーは意図的にコンパイル不可にされています。2つのキャッシュはレイヤーのレイアウトや隠れ層サイズが異なる可能性があるためです。レガシーのタプル変換はサポートされていません。単一のレガシータプルでは両方のパスを表現できないためです。シャドウ側はベースのフォワードの前にアンパックされ、出力時に再パックされます。ShadowModelのフックを参照してください。