Civitai 等のモデルページを見ていると、 Sampler が指定されています。
diffusers では、 Scheduler がそれに相当するようです。
この記事では Scheduler について調べてみます。
Scheduler とは
schedulers define the whole denoising process.
Scheduler はノイズ除去プロセス全体を定義してくれるとのことです。
Scheduler の確認方法
So it can be accessed via the "scheduler" property.
scheduler プロパティでアクセスできるとのことですね。
# パイプラインのスケジューラを確認する print(pipe.scheduler) --- PNDMScheduler { "_class_name": "PNDMScheduler", "_diffusers_version": "0.25.1", "beta_end": 0.012, "beta_schedule": "scaled_linear", "beta_start": 0.00085, "clip_sample": false, "num_train_timesteps": 1000, "prediction_type": "epsilon", "set_alpha_to_one": false, "skip_prk_steps": true, "steps_offset": 1, "timestep_spacing": "leading", "trained_betas": null }
ロードしているパイプラインのデフォルトに設定されているものになるんですかね?
scheduler の変更方法
Every scheduler has a property compatibles which defines all compatible schedulers.
スケジューラには compatibles
というプロパティがあって、互換性のあるスケジューラが定義されているようです
print(pipe.scheduler.compatibles) --- [ <class 'diffusers.schedulers.scheduling_pndm.PNDMScheduler'>, <class 'diffusers.schedulers.scheduling_k_dpm_2_discrete.KDPM2DiscreteScheduler'>, <class 'diffusers.schedulers.scheduling_unipc_multistep.UniPCMultistepScheduler'>, <class 'diffusers.schedulers.scheduling_euler_discrete.EulerDiscreteScheduler'>, <class 'diffusers.schedulers.scheduling_ddpm.DDPMScheduler'>, <class 'diffusers.schedulers.scheduling_euler_ancestral_discrete.EulerAncestralDiscreteScheduler'>, <class 'diffusers.utils.dummy_torch_and_torchsde_objects.DPMSolverSDEScheduler'>, <class 'diffusers.schedulers.scheduling_deis_multistep.DEISMultistepScheduler'>, <class 'diffusers.schedulers.scheduling_heun_discrete.HeunDiscreteScheduler'>, <class 'diffusers.schedulers.scheduling_dpmsolver_multistep.DPMSolverMultistepScheduler'>, <class 'diffusers.schedulers.scheduling_dpmsolver_singlestep.DPMSolverSinglestepScheduler'>, <class 'diffusers.schedulers.scheduling_k_dpm_2_ancestral_discrete.KDPM2AncestralDiscreteScheduler'>, <class 'diffusers.schedulers.scheduling_ddim.DDIMScheduler'>, <class 'diffusers.schedulers.scheduling_lms_discrete.LMSDiscreteScheduler'> ]
たくさんありました。
To change the scheduler of the pipeline you can make use of the convenient config property in combination with the from_config() function.
スケジューラは config
というプロパティも持っていて、
from_config()
メソッドと組み合わせて使うらしいです。
from diffusers import DDIMScheduler ddim_scheduler = DDIMScheduler.from_config(pipe.scheduler.config) pipe.scheduler = ddim_scheduler print(pipe.scheduler) --- DDIMScheduler { "_class_name": "DDIMScheduler", "_diffusers_version": "0.25.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": "epsilon", "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 }
変わりましたね。
実際に実行してみる
ドキュメントにある通り、以下の条件で実行してみようと思います。
- モデル: runwayml/stable-diffusion-v1-5
- プロンプト: "A photograph of an astronaut riding a horse on Mars, high resolution, high definition."
- seed: 8
- ステップ数: スケジューラによって変える
デフォルト (PNDMScheduler)
おお、ドキュメントと全く同じものが出ました!
DDIMScheduler
おお!これも全く同じものが出ました!
今までモデルページのプロンプトに合わせて実行してても全く同じものは出なかったので嬉しいぃ!
LMSDiscreteScheduler
LMSDiscreteScheduler usually leads to better results:
通常、こっちのほうが良い結果が得られる!?
良い結果かどうかはちょっとわからないですが、
これもドキュメントと同じものが出ました!
EulerDiscreteScheduler, EulerAncestralDiscreteScheduler
EulerDiscreteScheduler and EulerAncestralDiscreteScheduler can generate high quality results with as little as 30 steps.
これらは、30ステップで良い結果が得られるとな!?
ということは、、、前回の記事(以下の記事)で、
30ステップで品質が悪くなったように見えるのは Scheduler のせいである可能性が高いですね!
とりあえず EulerDiscreteScheduler
と EulerAncestralDiscreteScheduler
を 30 ステップで実行してみましょう
全く同じのが出るって気持ちいい!
DPMSolverMultistepScheduler
DPMSolverMultistepScheduler gives a reasonable speed/quality trade-off and can be run with as little as 20 steps.
こちらはスピードとクオリティのトレードオフにより20ステップで出来るって書いてあるっぽいですね?
確かに早いですね。
2秒くらいで出来ました。
まとめ
スケジューラによってプロセスが異なるということで、
品質やステップ数などに影響が出るため、スケジューラーの指定は重要そうな気がしました!
そして上記には、 Web UI と Diffusers の Scheduler 比較表がありました。
A1111-k-diffusion | diffusers | Usage |
---|---|---|
DPM++ 2M | DPMSolverMultistepScheduler | |
DPM++ 2M Karras | DPMSolverMultistepScheduler | init with use_karras_sigmas=True |
DPM++ 2M SDE | DPMSolverMultistepScheduler | init with algorithm_type="sde-dpmsolver++" |
DPM++ 2M SDE Karras | DPMSolverMultistepScheduler | init with use_karras_sigmas=True and algorithm_type="sde-dpmsolver++" |
DPM++ 2S a | N/A | very similar to DPMSolverSinglestepScheduler |
DPM++ 2S a Karras | N/A | very similar to DPMSolverSinglestepScheduler(use_karras_sigmas=True, ...) |
DPM++ SDE | DPMSolverSinglestepScheduler | |
DPM++ SDE Karras | DPMSolverSinglestepScheduler | init with use_karras_sigmas=True |
DPM2 | KDPM2DiscreteScheduler | |
DPM2 Karras | KDPM2DiscreteScheduler | init with use_karras_sigmas=True |
DPM2 a | KDPM2AncestralDiscreteScheduler | |
DPM2 a Karras | KDPM2AncestralDiscreteScheduler | init with use_karras_sigmas=True |
DPM adaptive | N/A | |
DPM fast | N/A | |
Euler | EulerDiscreteScheduler | |
Euler a | EulerAncestralDiscreteScheduler | |
Heun | HeunDiscreteScheduler | |
LMS | LMSDiscreteScheduler | |
LMS Karras | LMSDiscreteScheduler | init with use_karras_sigmas=True |
N/A | DEISMultistepScheduler | |
N/A | UniPCMultistepScheduler |
これで勝つるかもしれません!