CFG Scale とは何か

KSampler で指定する cfg は、よく『プロンプトの効きやすさを決める値』として説明され、実際にその通りの効果があります。 しかし最初にその名前 "cfg"、"CFG scale"、"classifier-free guidance scale" を見たときには、何の値なのかまったく分からなかったのではないでしょうか。

このページでは、"CFG scale" という名前になった経緯とその実際の動作について、かなり雑に説明します。

まとめ
  • 現在に至るまでの経緯:
    • ランダムな画像生成
    • コンディショニング
    • クラス分類器によるガイダンス
    • コンディショニングとガイダンスが融合。更にクラス分類器無しでもガイドできるように
    • 民間療法で uncond が negative prompt に (←今ココ)
  • KSampler は negative と positive の 2回、サンプリングする
  • negative = uncond = 基準点
  • そのステップでのノイズ除去済み画像 = uncond + (cond - uncond) * cfg

目次

現在に至るまでの経緯

拡散モデルに基いた画像生成の話です。 生成した画像について、たとえ画像としては成り立っていても、その中身は運にまかせるしかない、というのでは不便です。 まず『コンディショニング』という考え方で、生成画像をコントロールするようになりました。

コンディショニングは、画像生成の事前条件を与えるものです。 しかし、学習データに近い画像では有効なもののそれ以外では効果が薄く、効果の強さを調整することもできませんでした。

その後、『ガイダンス』という考え方で、生成画像をコントロールするようになりました。 ガイダンスは、画像生成過程の途中で都度介入して方向を誘導するものです。 誘導の強さも調整できます。 その手法の一つは画像分類器を利用するものでした。 しかし、生成器の他に、ノイズ混じりの画像に何が写っているのかを分類できる分類器まで同時に学習しなくてはならなかったり、挙動が不安定だったりしました。

その後、コンディショニングを使ってガイダンスを行う、融合手法が考案されました。 画像分類器 (classifier) を使わないので、『classifier-free diffusion guidance (CFG)』と呼ばれます。 従来手法のコンディショニングを使い、単一モデルの学習だけで済み、画像生成時の処理も簡単で、ガイダンスが安定かつ強力で、強さの調整も可能、という手法です。 Stable Diffusion が採用したのがこれです。

Stable Diffusion など、拡散モデルに基づいた画像生成が研究者以外にも広く使われるようになりました。 その中で、classifier-free guidance を利用して、逆方向のガイドも行う方法が広まりました。 現在で言う negative prompt です。

CFG に対応するための Stable Diffusion の学習

Stable Diffusion では、U-Net に組み込んだ cross attention block にプロンプトを入れてコンディショニングを実現します。 (CFG には関係しませんが、inpainting 用モデルでは、入力された latent 画像にマスク画像を直接追加・結合する方法も併用します。)

Stable Diffsion の U-Net の学習では、二種類の学習を混ぜて行います。

  • ランダムな画像を選び、その画像のキャプションを CLIP text encoder でエンコードしてコンディショニングに使い学習する (条件有りなので cond と呼ばれる)
  • ランダムな画像を選び、画像によらず常に同一の空のキャプションを CLIP text encoder でエンコードしてコンディショニングに使い学習する (意味のある条件が無いので uncond と呼ばれる)

このように学習された U-Net は、

  • 何らかのテキストプロンプトが与えられると、それに対応する方面の画像を前提にしたノイズ推定を行うように、
  • 空のプロンプトが与えられると、中立な画像を前提にしたノイズ推定を行うように

なります。

ComfyUI における画像生成と CFG scale

画像生成については色々な方法があり得るので、ComfyUI の KSampler に positive/negative 単一ペアのプロンプトが与えられた場合のみを取り上げます。

KSampler では、もっとも単純な場合、U-Net でのノイズ推定を、各ステップあたり 2回行います。

  • positive を使ってノイズ推定、を 1回 (慣例に従って cond と呼ばれる)
  • negative を使ってノイズ推定、を 1回 (慣例に従って uncond と呼ばれる)

cond の結果 (の推定ノイズを除いた画像) は、positive prompt に従った画像です。 これは、ガイダンスが無かった時代の、コンディショニングのみを使った画像生成と同じです。 同様に、uncond の結果 (の推定ノイズを除いた画像) は、negative prompt に従った画像です。 このとき negative が空なら、中立な画像が得られます。 これはさらに古い、コンディショニング無しの無条件の画像生成と同じです。

実際には、cond や uncond の結果をそのまま使うのではなく、以下の式に従って混ぜたものがそのステップでの最終的な画像になります。

そのステップでのノイズ除去済み画像 = uncond の結果 + (cond の結果 - uncond の結果) * cfg

まず uncond が基準にあって、そこから cond へのベクトルを cfg 倍するということです (線形補間、線形内挿、線形外挿)。 cfg0 なら基準点となる uncond (negative) が結果になります。 cfg1 ならコンディショニングありの cond (positive) が結果になります。 そして、cfg1 より大きければ、uncond を基準に cond を伸ばした先の点が結果になります。

さて、negative が空で文字通り uncond なら上の理解でいいのですが、negative に空でない何らかのプロンプトが入っていた場合はどうなのか。 その場合も uncond と同様に、negative から遠ざかる方向に cfg による調整が効きます。 生成されて欲しくないものを negative で指定できるということです。

ただ、negative が空でないと、ガイダンスの式から本来の uncond が無くなってしまいます。 negative が基準点となってしまい、それ自身は cfg の影響を受けません。 positivenegative の中身によっては、期待通りの動きをしないこともあるのではないでしょうか (個人の想像です)。 結局、uncond のサンプリングもすると計算負荷がさらに上がるし、よく分からないけど実際にはそれなりに動いているからこのままにしよう、という感じなのではないかと思います。

どうでもいい雑学 - CFG scale の性質

上の式を再掲します (『の結果』は省略)。

画像 = uncond + (cond - uncond) * cfg

これをユーザ側の用語に置き換えてちょっと変形すると、こうなります (『の結果』は省略)。

画像 = (positive + negative) * 0.5 + (positive - negative) * (cfg - 0.5)

わざわざ変形しなくても直観的に分かることではありますが、cfg = 0.5 を境に、positivenegative の立場が逆転します。 つまり、negativepositive として使える領域があります。

CFG scale と起きること
0 positive が無効に。 negativepositive のように働く。 ガイダンス無し時代と同じ動作。
(0 .. 0.5) negativepositive のように働く。 positivenegative のように働く。
0.5 negativepositive が同じ重み。 negativepositivepositive のように働く。
(0.5 .. 1) 面白いことは起きない。
1 negative が無効に。 ガイダンス無し時代と同じ動作。
> 1 negativenegative らしく。 positivepositive らしく。
CFG scale が大きすぎると、生成が破綻する
(positivenegative が同一の場合は例外で cfg = 0 相当、破綻しない)。