Stable Diffusionを使ったイラスト作成の記録(15) ~ 画質レイヤーのパラメータ ~
前回の記事
シリーズ一覧
Layered Diffusion Pipelineを使うためのリンク集
ライブラリの入手先と使用法(英語) : Githubリポジトリ
日本語での使用方法の解説 : Noteの記事
今回は予定を変更してお送りします。
今回は予定では、前回求めた画質タグを使って、どういう組み合わせにするとどういう結果が得られるのか、という点を調査することにしていました。
しかし、予備実験中に次の画像を生成したことで、急遽予定を変更することになりました。
左と右の画像では、ただ重みが違うだけの全く同じプロンプトで同じレイヤー構成が使われています。しかし、絵のタッチに絶対的な違いがあります。
極めて興味深いことに、2つの画像では、絵のタッチ以外にほとんど違いがありません。画像の構成、人物の姿勢、色合いデザインなど、細部を除いてはほとんど同じものが描かれています。
そこで、この変化は何の影響によるもので、思い通りにコントロール可能なものなのかどうかを調べるのが、今回の課題になります。
実験の設定
スクリプト
まず、実験用に使う画像生成のスクリプトを1つに決めます。これには余分なものが含まれない最小限の構成であることが望ましいので、上記の画像を生成したものとはプロンプトが異なります。
# スクリプト(15-1)
negative_quality_tags = """
blurry,
lowres,
duplicate,
morbid,
deformed,
monochrome,
greyscale,
comic,
4koma,
2koma,
chibi,
sepia,
lineart,
sketch,
simple background,
rough,
unfinished,
"""
novel_tags = """
novel illustration,
official art,
"""
sketch_tags = """
colored pencil,
sketch,
"""
images = pipe(
num_steps=30,
size=image_size,
rand_seed=rand_seed,
initialize=Randomly(strength=using(0.99999, until=1.0)),
iterate=[
Layer(
prompt="1girl",
negative_prompt=negative_quality_tags,
),
Layer(
prompt=novel_tags,
negative_prompt=sketch_tags,
strength=using(0.5, after=0.8),
is_zero_sum=True,
)
]
)
1つ目のレイヤーには、プロンプトを"1girl"にし、ネガティブプロンプトを以前から使っているネガティブ画質タグにします。今回は、前回同様にネガティブSPレイヤーを使っていません。
2つ目のレイヤーは、画質レイヤーとしてゼロ和レイヤーのプロンプトに前回分析した挿絵タグと手書きタグ(millipenを除く)を用いています。
実験1「画質レイヤーのネガティブプロンプトの重みを変える」
プロンプトとネガティブプロンプトのエンコーディングはShiftEncodingを使っています。このエンコーディング方式は、各タグごとに重みを設定することができます。(注:重みの計算は、LPW(Long Prompt Weighting)と同じ計算式を使っています。)
例えば、画像レイヤーのネガティブプロンプトである手書きタグの重みを2.0にするには、次のようにします。
sketch_tags = """
colored pencil :2.0,
sketch :2.0,
"""
このようにして、重みを1.0, 2.0, 2.5, 3.0, 5.0と変化させて生成画像の変化を確認しました。
生成画像
結果は、最初の生成画像で観察されたのと同様に、画像の構成などは変化せず、絵のタッチだけが変化するという結果になりました。
ただし、最初の生成画像は重みが8.0で生成された画像でしたが、ネガティブプロンプトに余計なタグが含まれていたため、内容を単純化した実験用スクリプトでは重み2.5あたりで最初の生成画像と同程度の絵のタッチとなったようです。
実験2「画質レイヤーのStrengthを変える」
ネガティブプロンプトの重みを変えるということが何を意味してどういう効果があるかを明確にするため、他のパラメータも変更してみます。
まずは、Strengthを変化させます。なお、ゼロ和レイヤーの場合、CFGスケールとStrengthには比例関係にあるので、Strengthを2倍にすることはCFGスケールを2倍にするのと同じ効果があります。
実験のスクリプトでStrengthの初期値は0.5で、これを1.0, 2.0, 3.0と変化させました。
生成画像
この場合も、画像の構成などには大きな変化が起きることなく、絵のタッチのみが変化しました。が、その変化の方向性は、最初の生成画像とは大きく異なっています。
実験3「画質レイヤーのStrengthとネガティブプロンプトの重みを同時に変える」
次に、実験1と実験2の変化を同時に加えた場合にどうなるかを試してみました。Strengthを2.0に固定して、ネガティブプロンプトの重みを1.0, 1.5, 2.0と変化させました。
生成画像
実験1と同様、ネガティブプロンプトの重みを増やすと絵のタッチが変化します。ただし、実験1の時は重みが2.5程度で最初の生成画像と同程度のタッチになりましたが、実験3では重みが2.0ですでに過剰となっています。
この重みの違いが起きる原因としては、Strengthが0.5から2.0へと4倍になることで、ネガティブプロンプトに掛かる係数が増えていることが考えられます。しかし、Strengthの値とネガティブプロンプトの重みの値の関係の換算式ははっきりとはしていません。
一つの仮説として、1つ目のレイヤーのCFGスケールが4.0でネガティブプロンプトの係数は3.0であり、画質レイヤーのStrengthの変化がネガティブプロンプトの係数の2.0から8.0への変化に相当するので、画質レイヤーのネガティブプロンプトの係数の割合は0.4から0.73に増加しています。
それに対し、ネガティブプロンプトの重みが2.5の時に重みの増分は1.5で、これが係数の増加と相殺するように重みを計算すると1.82(= 1.0 + 1.5 * 0.4 / 0.73)となります。上記生成画像でも、1.5から2.0の間に相当する重みがあるように見え、計算と表面的には符合しています。
実験4「画質レイヤーのプロンプトの重みを変える」
ネガティブプロンプトの重みの代わりに、プロンプトの重みを変えてみるとどうなるかを試してみました。例えば、重みを2倍にするには次のように記述します。
novel_tags = """
novel illustration :2.0,
official art :2.0,
"""
実験では、重みを1.0, 2.0, 3.0と変化させました。
生成画像
プロンプトの重みを増やすと、Strengthを増やした時と似たような方向性の変化が起きます。例えば、プロンプトの重みが2.0(初期値の2倍)の画像は、Strengthが1.0(初期値の2倍)の画像との類似性があります。
ただし、Strengthの時とは違い画像の乱れが起き、重みが3.0に至ってはほぼ崩れて絵として成立していません。
まとめ
画質レイヤーのネガティブプロンプトの重みを増やす
ネガティブプロンプトの重みを増やすと、画像の細部や色合い、塗り方などが単純化して、ポスターやアニメ絵のような雰囲気の画像になります。
画質レイヤーのStrength(またはCFGスケール)を増やす
Strength(またはCFGスケール)を増やすと、ネガティブプロンプトの重みを増やすのとは違う形で画像が変化します。変化は画像の細部、色合い、塗り方などが明確化して、画質レイヤーで指定された画質のタイプがより強化される方向で起こります。
画質レイヤーのプロンプトの重みを増やす
プロンプトの重みを増やす場合の効果は、Strength(またはCFGスケール)を増やす効果と類似性があります。しかし、重みが増えるにつれ、画像に乱れが発生し、最終的には画像が崩れてしまいます。
プロンプトの重みと係数の関係
Strength(またはCFGスケール)は画像生成プロセス内部では、対応するプロンプト・ネガティブプロンプトに対応する潜在変数への係数に換算されますが、この係数とプロンプトのエンコーディング時の重みには反比例に近い関係があるように思われます。