Home About
Stable Diffusion , Diffusers

Diffusers の Scheduler を試した

Coffee Cups

詳細はここ https://huggingface.co/docs/diffusers/using-diffusers/schedulers に書いてある。

先日の実験では DPMSolverMultistepScheduler を使うと真っ黒の画像になる、などと書いていたが、 今回あらためて試したところ、普通に作動した。

EulerDiscreteScheduler

基本にするコード:

main.py

import torch
from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler

model_id = "stabilityai/stable-diffusion-2-1"
device = "mps"
seed = 46
prompt = "A cup of coffee, simple background, art by Hokusai."

scheduler = EulerDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
pipeline = StableDiffusionPipeline.from_pretrained(model_id, scheduler=scheduler)
pipeline = pipeline.to(device)

pipeline.enable_attention_slicing()

generator = torch.Generator(device).manual_seed(seed)
image = pipeline(prompt, guidance_scale=7.5, generator=generator).images[0]
image.save("a-cup-of-coffee.png")

実行すると次の絵ができました。

A cup of coffee

実際に出力されるのは 768x768 ですが、例によって 320x320 のサイズにリサイズして掲載しています。

スケジューラーを適用する部分のコードが現状はこれ:

scheduler = EulerDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
pipeline = StableDiffusionPipeline.from_pretrained(model_id, scheduler=scheduler)
pipeline = pipeline.to(device)

この記述は、次のようにスッキリ記述できるとのこと。

pipeline = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
pipeline.scheduler = EulerDiscreteScheduler.from_config(pipeline.scheduler.config)
pipeline = pipeline.to(device)

DPMSolverMultistepScheduler

DPMSolverMultistepScheduler に差し替えてみます。

main.py

import torch
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler

model_id = "stabilityai/stable-diffusion-2-1"
device = "mps"
seed = 46
prompt = "A cup of coffee, simple background, art by Hokusai."


pipeline = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
pipeline.scheduler = DPMSolverMultistepScheduler.from_config(pipeline.scheduler.config)
pipeline = pipeline.to(device)

pipeline.enable_attention_slicing()

generator = torch.Generator(device).manual_seed(seed)
image = pipeline(prompt, guidance_scale=7.5, generator=generator).images[0]
image.save("a-cup-of-coffee.png")

これを実行してできあがった画像はこちら:

A cup of coffee

実際に出力されるのは 768x768 ですが、例によって 320x320 のサイズにリサイズして掲載しています。

シードもプロンプトも同じなので完全に同じ絵になるかと思ったのですが、少しは異なります。

ちなみに torch_dtype=torch.float16 指定しているがこれを外したらどうなるのか? もっときれいな画像になるのであろうか?

#pipeline = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
pipeline = StableDiffusionPipeline.from_pretrained(model_id)

実行結果の画像:

A cup of coffee

まあ、大差ない。

そもそも device が CUDA ではないから、このオプションがもともと有効ではなかった可能性あり。

デフォルトのスケジューラーの確認

StableDiffusionPipeline.from_pretrained で pipeline を組み立てた時点でセットされている scheduler は pipeline.scheduler すれば把握できる。

pipeline = StableDiffusionPipeline.from_pretrained(model_id)
print(pipeline.scheduler)

次のように出力された。 DDIMScheduler がセットされている。

DDIMScheduler {
  "_class_name": "DDIMScheduler",
  "_diffusers_version": "0.23.1",
  "beta_end": 0.012,
  "beta_schedule": "scaled_linear",
  "beta_start": 0.00085,
  "clip_sample": false,
  "clip_sample_range": 1.0,
  "dynamic_thresholding_ratio": 0.995,
  "num_train_timesteps": 1000,
  "prediction_type": "v_prediction",
  "rescale_betas_zero_snr": false,
  "sample_max_value": 1.0,
  "set_alpha_to_one": false,
  "skip_prk_steps": true,
  "steps_offset": 1,
  "thresholding": false,
  "timestep_spacing": "leading",
  "trained_betas": null
}

pipeline.scheduler.compatibles すると、使えるスケジューラーの一覧が入手できるらしい。

pipeline = StableDiffusionPipeline.from_pretrained(model_id)

#print(pipeline.scheduler.compatibles)
for it in pipeline.scheduler.compatibles:
    print(it)
<class 'diffusers.schedulers.scheduling_deis_multistep.DEISMultistepScheduler'>
<class 'diffusers.utils.dummy_torch_and_scipy_objects.LMSDiscreteScheduler'>
<class 'diffusers.schedulers.scheduling_euler_ancestral_discrete.EulerAncestralDiscreteScheduler'>
<class 'diffusers.schedulers.scheduling_ddpm.DDPMScheduler'>
<class 'diffusers.schedulers.scheduling_k_dpm_2_discrete.KDPM2DiscreteScheduler'>
<class 'diffusers.schedulers.scheduling_euler_discrete.EulerDiscreteScheduler'>
<class 'diffusers.schedulers.scheduling_k_dpm_2_ancestral_discrete.KDPM2AncestralDiscreteScheduler'>
<class 'diffusers.schedulers.scheduling_dpmsolver_multistep.DPMSolverMultistepScheduler'>
<class 'diffusers.schedulers.scheduling_ddim.DDIMScheduler'>
<class 'diffusers.schedulers.scheduling_pndm.PNDMScheduler'>
<class 'diffusers.schedulers.scheduling_heun_discrete.HeunDiscreteScheduler'>
<class 'diffusers.utils.dummy_torch_and_torchsde_objects.DPMSolverSDEScheduler'>
<class 'diffusers.schedulers.scheduling_dpmsolver_singlestep.DPMSolverSinglestepScheduler'>
<class 'diffusers.schedulers.scheduling_unipc_multistep.UniPCMultistepScheduler'>

試しに DPMSolverSinglestepScheduler を使ってみる。

DPMSolverSinglestepScheduler の説明: https://huggingface.co/docs/diffusers/v0.23.1/en/api/schedulers/singlestep_dpm_solver

だいたい 10ステップで高品質な絵ができるという話なのでやってみる。

import torch
from diffusers import StableDiffusionPipeline, DPMSolverSinglestepScheduler

model_id = "stabilityai/stable-diffusion-2-1"
seed = 46
device = "mps"
prompt = "A cup of coffee, simple background, art by Hokusai."

pipeline = StableDiffusionPipeline.from_pretrained(model_id)

pipeline.scheduler = DPMSolverSinglestepScheduler.from_config(pipeline.scheduler.config)
pipeline = pipeline.to(device)

pipeline.enable_attention_slicing()

generator = torch.Generator(device).manual_seed(seed)
image = pipeline(
	prompt,
	guidance_scale=7.5,
	num_inference_steps=10,
	generator=generator).images[0]
image.save("a-cup-of-coffee.png")

num_inference_steps=10 を pipeline に指定することでステップ数を指定できる。 デフォルトの 50 ステップが 10ステップで絵ができるので、生成時間は 1/3 程度(本来は 1/5 になるべき?)です。

生成された絵はこれ:

A cup of coffee

これが少ないステップ数で高品質になったのかわからないので、 デフォルトのスケジューラー( DDIMScheduler )で 10ステップ にした画像を生成してみます。

これ:

A cup of coffee

あぁ確かに。これは「まだ早すぎたんだ」感がすごい。

では DPMSolverSinglestepScheduler を使って 25ステップ を試します。

A cup of coffee

確かに品質が高くなっています。100ステップにしたらどうなるんだろう?

A cup of coffee

すくなくとも スケジューラーとして DPMSolverSinglestepScheduler を使った場合については、 カップの取っ手の部分の描画がよくなってきてはいるものの、 ステップ数を増やしたからといって劇的によくなった感じはしない。 ある程度(50ステップ)以上は それほど変わりがないのかもしれない。

まとめ

10,25,100ステップと並べてみると違いがわかる。

Coffee Cups

Liked some of this entry? Buy me a coffee, please.