【WebUI 1111】CPU向き低ステップ(9~15)サンプラー Euler+DPM++ 2M karras 追加方法 【Stable diffusion】

 

12 Step

概要

CPU向きの低ステップサンプラーです。リアルモデルで9ステップぐらいから使えます。

Eulerの絵は柔らかい感じの絵なので、途中からDPM++ 2Mに変えて少しパキッとした絵になるサンプラーにしました。

 

7 StepまではEuler Karrasと同じ絵になります。

あわせて読みたい

【WebUI 1111】低ステップ最強サンプラー Euler karras 追加方法 【Stable diffusion】

 

DPM++ 2Mは下記のサイトを参考に低ステップ向きに改良しています。

https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/8457

 

https://scrapbox.io/work4ai/hallatore%E6%B0%8F%E6%94%B9%E8%89%AF%E7%89%88DPM++_2M_Karras


追加方法 


stable-diffusion-webui\modules\sd_samplers_kdiffusion.py の samplers_k_diffusionに下記の行を追加します。
    ('DPM++ 2M Karras test mix', 'sample_dpmpp_2m_test_mix', ['k_dpmpp_2m_ka'], {'scheduler': 'karras',}),
 
stable-diffusion-webui\repositories\k-diffusion\k_diffusion\sampling.pyの最後に下記のコードを追加します。
@torch.no_grad()
def sample_dpmpp_2m_test_mix(model, x, sigmas, extra_args=None, callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.):
    """DPM-Solver++(2M) SDE."""
    extra_args = {} if extra_args is None else extra_args
    s_in = x.new_ones([x.shape[0]])
    sigma_fn = lambda t: t.neg().exp()
    t_fn = lambda sigma: sigma.log().neg()

    old_denoised = None
    h = None
    old_r = None

    #7stepまでEuler karrasと同じ
    eulr = 5

    for i in trange(len(sigmas) - 1, disable=disable):
        if(i <= eulr):
            gamma = min(s_churn / (len(sigmas) - 1), 2 ** 0.5 - 1) if s_tmin <= sigmas[i] <= s_tmax else 0.
            eps = torch.randn_like(x) * s_noise
            sigma_hat = sigmas[i] * (gamma + 1)
            if gamma > 0:
                x = x + eps * (sigma_hat ** 2 - sigmas[i] ** 2) ** 0.5
            denoised = model(x, sigma_hat * s_in, **extra_args)
            d = to_d(x, sigma_hat, denoised)
            if callback is not None:
                callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigma_hat, 'denoised': denoised})
            dt = sigmas[i + 1] - sigma_hat
            # Euler method
            x = x + d * dt

            sigma_progress = i / len(sigmas)
            adjustment_factor = 1 - (0.14 * (sigma_progress * sigma_progress))
            old_denoised = denoised * adjustment_factor
        else:
            denoised = model(x, sigmas[i] * s_in, **extra_args)
            if callback is not None:
                callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigmas[i], 'denoised': denoised})
            t, t_next = t_fn(sigmas[i]), t_fn(sigmas[i + 1])
            h = t_next - t
           
            t_min = min(sigma_fn(t_next), sigma_fn(t))
            t_max = max(sigma_fn(t_next), sigma_fn(t))

            if old_denoised is None or sigmas[i + 1] == 0:
                x = (t_min / t_max) * x - (-h).expm1() * denoised
                old_r = None
            else:
                h_last = t - t_fn(sigmas[i - 1])

                h_min = min(h_last, h)
                h_max = max(h_last, h)
                r = h_max / h_min
                if old_r is None:
                    old_r = r

                h_d = h
                denoised_d = (1 + 1 / (2 * r)) * denoised - (1 / (2 * r)) * old_denoised
                x = (t_min / t_max) * x - (-h_d).expm1() * denoised_d
                old_r = r
            #test new sampler
            sigma_progress = i / len(sigmas)
            adjustment_factor = 1 - (0.14 * (sigma_progress * sigma_progress))
            old_denoised = denoised * adjustment_factor

    return x
 
 再起動とリロードすると  DPM++ 2M Karras test mix が追加されます。
 

参考画像

 

アニメモデル

12 Step

9 Step

リアルモデル

12 Step

目が少し変なのはモデルの特徴だと思う。アップスケールすると治るかも。

 

12 Step


yuki

初めての作業で調べた事、困った時の解決方法を記録するブログ。 主なテーマは、パソコン、プログラミング、カメラ、DTM、スピリチュアル、化学物質過敏症

コメントを投稿

Please Select Embedded Mode To Show The Comment System.*