EN | 日本語
Adaptive Projected Guidance (APG) extension for Stable Diffusion WebUI (Forge-based).
Implementation of Eliminating Oversaturation and Artifacts of High Guidance Scales in Diffusion Models (ICLR 2025), Algorithm 1.
APG reduces the oversaturation and artifacts that appear at high CFG scales, letting you raise CFG for stronger prompt adherence without the usual color burn and contrast blowout.
- Paper formulation, not the ComfyUI node formulation — the neutral settings reproduce standard CFG exactly (verified by fixed-seed pixel-level A/B comparison).
- Works on reForge / Forge Classic (Pre-CFG hook) and Forge Neo (Post-CFG hook); the backend is detected automatically.
- Rank-agnostic projection — supports both 4-D SDXL latents and 5-D Anima / NextDiT latents.
- Composes with the rest of the guidance suite via
sorting_priority. - XYZ Grid axes for all parameters.
- Generation parameters are embedded in PNG infotext for reproducibility.
Extensions → Install from URL:
https://github.com/seti9585/sd-webui-APG
This extension relies on the Forge backend hook API. It is not available in A1111 (AUTOMATIC1111).
APG decomposes the guidance vector into a component parallel to the conditional prediction and a component orthogonal to it. The parallel component is what pushes the latent along the direction it is already heading — the main cause of oversaturation at high CFG. Scaling it down keeps the semantic steering (orthogonal part) while removing the burn.
diff = cond - uncond
diff = momentum_buffer.update(diff) (optional, beta != 0)
diff = clamp L2 norm to norm_threshold (optional, threshold > 0)
par, orth = project diff onto cond
update = orth + eta * par
final = cond + (cond_scale - 1) * update
| Control | Range | Default | Description |
|---|---|---|---|
| Enable APG | — | Off | Master switch. |
| Eta | 0.0 – 2.0 | 0.0 | How much of the parallel component to keep. 0 is the paper's recommended default; 1.0 keeps it fully, which disables the projection. Raise it if the result looks flat or desaturated. |
| Norm Threshold | 0.0 – 50.0 | 15.0 | Per-sample L2 clamp on the guidance vector. 0 disables. The paper uses 15 for SDXL. |
| Momentum | -1.5 – 1.0 | 0.0 | Running-average coefficient (beta). 0 disables. The paper uses negative values such as -0.5. See the warning below before enabling. |
Eta 1.0 / Norm Threshold 0 / Momentum 0
These reproduce standard CFG bit-for-bit. Use them as the A/B baseline when measuring what APG actually changes.
| Situation | Eta | Norm Threshold | Momentum |
|---|---|---|---|
| Paper default (single extension, high CFG) | 0.0 | 15.0 | 0.0 |
| Result looks washed out or low-contrast | 0.3 – 0.7 | 15.0 | 0.0 |
| Stacking with other guidance extensions | 1.0 | 0.0 | 0.0 |
When APG runs on top of TCFG / SkimmedCFG / DifferenceCFG and others, the paper defaults are usually too strong: each extension in the chain is already reducing the guidance magnitude. Start from the neutral settings and lower Eta gradually from there.
Momentum is not recommended with multi-stage or adaptive ODE solvers.
The momentum buffer keeps a running average across model evaluations, so
the integrand is no longer a function of (x, sigma) alone. This breaks the
stateless right-hand-side assumption that ODE solvers rely on:
- Multi-stage methods evaluate the model several times per step
(
kutta4= 4 evaluations), so the buffer accumulates several times faster than it does with a single-stage method at the same step count. - Adaptive step control re-evaluates rejected steps, making the accumulation rate depend on the tolerance settings.
Fixed-seed measurements (SDXL, 35 steps, Align Your Steps, CFG 7) showed that this is not simply a matter of scaling the coefficient. With a 4-stage solver, changing a momentum-related parameter by a very small amount moved the result about as far as it was from the baseline in the first place — the output jumped to an unrelated solution instead of changing proportionally. With a single-stage solver the same change produced roughly half the displacement, but the value-to-result relationship was still not monotonic.
Interpretation. Once momentum is enabled, a high-order solver's intermediate stages no longer improve the estimate; they amplify small early perturbations instead. The higher the order, the stronger the amplification — so the accuracy you are paying extra model evaluations for is lost.
Recommendation.
| Sampler | Momentum |
|---|---|
| Euler, LMS, and other single-stage methods | Usable |
| Heun, DPM++ 2M / 3M, and other multi-stage methods | Not recommended |
| TDE Sampler / RK Sampler (multi-stage or adaptive solvers) | Not recommended |
Momentum defaults to 0 (off), which keeps APG a purely stateless
per-evaluation transform and safe to combine with any sampler.
sorting_priority = 14.5 places APG last in the pre-CFG chain:
TCFG (13.0) → SkimmedCFG (14.0) → DifferenceCFG (14.2) → APG (14.5)
→ CFG → CFGZeroStar (15.0) → MaHiRo (15.5)
This matches the "final polish before CFG" role recommended for APG.
On Forge Neo, TCFG's damped uncond is read from the shared
model_options dict when TCFG ran earlier in the same post-CFG call.
Both differences are deliberate.
| This extension | ComfyUI APG node |
|
|---|---|---|
| Final combination | cond + (cond_scale - 1) * update (paper Algorithm 1) |
effectively cond + cond_scale * update |
| Reduction dims | all non-batch dims (range(1, ndim)) |
fixed dim=[-1, -2, -3] |
The first means the neutral settings reduce to standard CFG exactly, which the ComfyUI node cannot do — it is always one guidance unit stronger.
The second is identical to the paper for 4-D (B, C, H, W) latents but keeps
the paper's per-sample semantics for 5-D (B, C, T, H, W) latents instead of
silently becoming per-channel. HuggingFace diffusers'
AdaptiveProjectedGuidance makes the same choice (norm_dim=None).
APG Eta, APG Norm Threshold, APG Momentum
APG Eta is written only while APG is active, so its presence in the
infotext doubles as the enable marker on read-back.
Images generated with v1.x may also carry an
APG Adaptive Momentumkey. That feature has been removed; the key is ignored on read and does not prevent the rest of the settings from being restored.
Releases before v2.0 offered an Adaptive Momentum slider, an original addition that faded the momentum coefficient to zero over the early part of the sigma schedule. It has been removed.
Fixed-seed testing showed that the parameter did not behave as a continuous control at any setting:
- Below roughly
0.21it had no effect at all (bit-identical to momentum applied normally). - Above that threshold it took effect, but the value and the result were not related monotonically — neighbouring values produced results as far apart from each other as they were from the baseline.
- Raising it toward
1.0did not converge on momentum-off behaviour, because the coefficient decays but never stops being applied.
The exact threshold also moved depending on the solver, since it is the number of model evaluations before the cut-off that decides the outcome. A slider whose value cannot be reasoned about is worse than no slider, so it was dropped rather than documented as a quirk.
Stable Diffusion WebUI(Forge 系)向けの Adaptive Projected Guidance(APG)拡張機能です。
Eliminating Oversaturation and Artifacts of High Guidance Scales in Diffusion Models(ICLR 2025)の Algorithm 1 の実装です。
APG は高い CFG スケールで発生する彩度過多やアーチファクトを抑えます。 色飛びやコントラストの破綻を気にせず CFG を上げ、プロンプトへの追従を 強められます。
- ComfyUI ノードではなく論文の式に忠実。中立設定で標準 CFG を完全に再現します(固定シードのピクセル単位 A/B 比較で確認済み)。
- reForge / Forge Classic(Pre-CFG フック)と Forge Neo(Post-CFG フック)に対応。バックエンドは自動判別します。
- 階数非依存の射影により、4 次元の SDXL latent と 5 次元の Anima / NextDiT latent の両方に対応。
sorting_priorityにより他のガイダンス拡張と正しい順序で合成されます。- 全パラメータの XYZ Grid 軸を提供。
- 生成パラメータを PNG infotext に埋め込み、再現可能です。
Extensions → Install from URL:
https://github.com/seti9585/sd-webui-APG
この拡張機能は Forge バックエンドのフック API を利用します。 A1111(AUTOMATIC1111)では動作しません。
APG はガイダンスベクトルを、条件付き予測に平行な成分と直交する成分に分解します。平行成分は latent を既に進んでいる方向へさらに押し込むもので、高 CFG における彩度過多の主因です。これを縮小すれば、意味的な誘導(直交成分)を保ったまま色飛びだけを取り除けます。
diff = cond - uncond
diff = momentum_buffer.update(diff) (任意、beta != 0 のとき)
diff = L2 ノルムを norm_threshold にクランプ (任意、threshold > 0 のとき)
par, orth = diff を cond に射影して分解
update = orth + eta * par
final = cond + (cond_scale - 1) * update
| 項目 | 範囲 | 既定値 | 説明 |
|---|---|---|---|
| Enable APG | — | オフ | 有効化スイッチ。 |
| Eta | 0.0 〜 2.0 | 0.0 | 平行成分をどれだけ残すか。0 が論文推奨の既定値、1.0 で全て残す(=射影が無効)。結果が平坦・低彩度に見える場合は上げます。 |
| Norm Threshold | 0.0 〜 50.0 | 15.0 | ガイダンスベクトルのサンプルごとの L2 クランプ。0 で無効。論文は SDXL に 15 を使用。 |
| Momentum | -1.5 〜 1.0 | 0.0 | 移動平均係数(beta)。0 で無効。論文は -0.5 などの負値を使用。有効化する前に下の警告を必ずお読みください。 |
Eta 1.0 / Norm Threshold 0 / Momentum 0
この設定は標準 CFG をビット単位で再現します。APG が実際に何を変えているかを測る際の A/B 基準として使えます。
| 状況 | Eta | Norm Threshold | Momentum |
|---|---|---|---|
| 論文既定値(単独使用・高 CFG) | 0.0 | 15.0 | 0.0 |
| 結果が眠い・コントラスト不足 | 0.3 〜 0.7 | 15.0 | 0.0 |
| 他のガイダンス拡張と併用 | 1.0 | 0.0 | 0.0 |
TCFG / SkimmedCFG / DifferenceCFG などの上に APG を重ねる場合、論文の既定値は通常強すぎます。チェーン内の各拡張がすでにガイダンスの大きさを削っているためです。中立設定から始め、Eta を少しずつ下げていくことをお勧めします。
Momentum は多段ソルバーおよび可変ステップソルバーとの併用を推奨しません。
momentum バッファはモデル評価をまたいで移動平均を保持します。そのため被積分関数が (x, sigma) だけの関数ではなくなり、ODE ソルバーが前提とする「右辺が無状態である」という条件が崩れます。
- 多段法は 1 ステップあたり複数回モデルを評価するため(
kutta4は 4 回)、同じステップ数でも単段法よりバッファの蓄積が数倍速くなります。 - 可変ステップ制御は棄却されたステップを再評価するため、蓄積速度が許容誤差の設定に依存します。
固定シードでの実測(SDXL / 35 ステップ / Align Your Steps / CFG 7)では、これが単なる係数のスケールの違いではないことが確認されました。4 段ソルバーでは、momentum 関連のパラメータをごくわずかに変えただけで、結果が「元の基準からの距離とほぼ同じだけ」動きました。つまり比例して変化するのではなく、無関係な別の解に飛んだということです。単段ソルバーでは変位はおよそ半分でしたが、値と結果の対応が単調でない点は変わりませんでした。
解釈。 momentum を有効にした時点で、高次ソルバーの中間段はもはや推定精度を改善しません。代わりに初期の微小な摂動を増幅します。次数が高いほど増幅は強くなるため、余分なモデル評価を払って得ていたはずの精度が失われます。
推奨。
| サンプラー | Momentum |
|---|---|
| Euler、LMS その他の単段法 | 使用可 |
| Heun、DPM++ 2M / 3M その他の多段法 | 非推奨 |
| TDE Sampler / RK Sampler(多段・可変ステップソルバー) | 非推奨 |
Momentum の既定値は 0(オフ)です。この状態では APG は完全に無状態な評価ごとの変換であり、どのサンプラーと組み合わせても安全です。
sorting_priority = 14.5 により、APG は pre-CFG チェーンの最後に配置されます。
TCFG (13.0) → SkimmedCFG (14.0) → DifferenceCFG (14.2) → APG (14.5)
→ CFG → CFGZeroStar (15.0) → MaHiRo (15.5)
これは APG に推奨される「CFG 直前の最終調整」という役割に一致します。
Forge Neo では、同一の post-CFG 呼び出し内で TCFG が先に実行されていた場合、共有の model_options から TCFG の減衰済み uncond を読み取ります。
いずれも意図的な相違です。
| 本拡張 | ComfyUI APG ノード |
|
|---|---|---|
| 最終合成 | cond + (cond_scale - 1) * update(論文 Algorithm 1) |
実質 cond + cond_scale * update |
| 縮約次元 | バッチ以外の全次元(range(1, ndim)) |
固定の dim=[-1, -2, -3] |
第一の相違により、中立設定が標準 CFG に完全に一致します。ComfyUI ノードでは常にガイダンス 1 単位分強いため、これができません。
第二の相違は 4 次元 (B, C, H, W) latent では論文と同一です。5 次元 (B, C, T, H, W) latent において、暗黙にチャンネルごとの処理になってしまうのを避け、論文のサンプル単位の意味を保ちます。HuggingFace diffusers の AdaptiveProjectedGuidance も同じ選択をしています(norm_dim=None)。
APG Eta, APG Norm Threshold, APG Momentum
APG Eta は APG が有効なときのみ書き込まれるため、infotext 中の存在自体が読み込み時の有効化マーカーを兼ねます。
v1.x で生成した画像には
APG Adaptive Momentumキーが含まれている場合があります。この機能は削除されましたが、当該キーは読み込み時に無視されるだけで、他の設定の復元を妨げません。
v2.0 より前のリリースには Adaptive Momentum スライダーがありました。これは本移植独自の追加機能で、シグマスケジュールの前半にかけて momentum 係数をゼロへ減衰させるものでしたが、削除されました。
固定シードでの検証により、この値がどの設定でも連続的な制御として機能しないことが判明したためです。
- おおよそ
0.21以下では効果が一切ありませんでした(momentum をそのまま適用した場合とビット単位で一致)。 - それ以上では効果が出ますが、値と結果が単調に対応しませんでした。隣り合う値どうしの結果が、基準からの距離と同じだけ離れていました。
1.0に近づけても momentum オフの挙動には収束しません。係数は減衰しますが、適用され続けること自体は止まらないためです。
閾値の位置もソルバーによって移動します。結果を決めているのが打ち切りまでのモデル評価回数だからです。値について推論できないスライダーは、無いほうがましだと判断し、仕様として文書化するのではなく削除しました。
MIT License
Paper / 論文
Sadat, S., Hilliges, O., & Weber, R. M. Eliminating Oversaturation and Artifacts of High Guidance Scales in Diffusion Models. ICLR 2025. arXiv:2410.02416
Inspiration / 着想
The author first learned of APG through the note.com articles of Shiba-2-shiba, whose TCFG-APG-Mahiro-for-ForgeClassic implementation for Forge Classic was also consulted. This extension is written from the paper above; the pointer that made it knowable is gratefully acknowledged.
APG の存在は Shiba-2-shiba 氏の note.com の記事によって知りました。Forge Classic 向けの実装である TCFG-APG-Mahiro-for-ForgeClassic も参考にさせていただいています。本拡張機能は上記論文をもとに記述したものですが、知るきっかけを与えてくださったことに深く感謝します。
Reference implementations / 参考実装
- ComfyUI built-in
APGnode (comfy_extras/nodes_apg.py) - HuggingFace diffusers
AdaptiveProjectedGuidance