Skip to content

Commit 2a49a2b

Browse files
committed
added more samplers
1 parent 5f52459 commit 2a49a2b

File tree

7 files changed

+170
-29
lines changed

7 files changed

+170
-29
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import numpy as np
2+
3+
4+
def get_alphas_cumprod(beta_start=0.00085, beta_end=0.0120, n_training_steps=1000):
5+
betas = np.linspace(beta_start ** 0.5, beta_end ** 0.5, n_training_steps, dtype=np.float32) ** 2
6+
alphas = 1.0 - betas
7+
alphas_cumprod = np.cumprod(alphas, axis=0)
8+
return alphas_cumprod
9+
10+
11+
12+
class KEulerSampler():
13+
def __init__(self, n_inference_steps=50, n_training_steps=1000):
14+
pass
15+
16+
def set_timesteps(self, n_inference_steps, n_training_steps=1000): #dg
17+
timesteps = np.linspace(n_training_steps - 1, 0, n_inference_steps)
18+
19+
alphas_cumprod = get_alphas_cumprod(n_training_steps=n_training_steps)
20+
sigmas = ((1 - alphas_cumprod) / alphas_cumprod) ** 0.5
21+
log_sigmas = np.log(sigmas)
22+
log_sigmas = np.interp(timesteps, range(n_training_steps), log_sigmas)
23+
sigmas = np.exp(log_sigmas)
24+
sigmas = np.append(sigmas, 0)
25+
26+
self.sigmas = sigmas
27+
self.initial_scale = sigmas.max()
28+
self.timesteps = timesteps
29+
self.n_inference_steps = n_inference_steps
30+
self.n_training_steps = n_training_steps
31+
self.step_count = 0
32+
33+
34+
def get_input_scale(self, step_count=None):
35+
if step_count is None:
36+
step_count = self.step_count
37+
sigma = self.sigmas[step_count]
38+
return 1 / (sigma ** 2 + 1) ** 0.5
39+
40+
def add_noise(self, latent, noise, idx ): #dg
41+
for i in idx:
42+
assert idx[0] == i
43+
sc = self.sigmas[idx[0]]
44+
return latent + noise*sc
45+
46+
47+
def step(self, output , t , latents , seed=None ): #dg
48+
49+
50+
sigma_from = self.sigmas[t]
51+
sigma_to = self.sigmas[t + 1]
52+
latents += output * (sigma_to - sigma_from)
53+
return {"prev_sample": latents } #latents
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import numpy as np
2+
3+
4+
def get_alphas_cumprod(beta_start=0.00085, beta_end=0.0120, n_training_steps=1000):
5+
betas = np.linspace(beta_start ** 0.5, beta_end ** 0.5, n_training_steps, dtype=np.float32) ** 2
6+
alphas = 1.0 - betas
7+
alphas_cumprod = np.cumprod(alphas, axis=0)
8+
return alphas_cumprod
9+
10+
11+
class KEulerAncestralSampler():
12+
def __init__(self):
13+
pass
14+
15+
16+
def set_timesteps(self, n_inference_steps, n_training_steps=1000): #dg
17+
timesteps = np.linspace(n_training_steps - 1, 0, n_inference_steps)
18+
19+
alphas_cumprod = get_alphas_cumprod(n_training_steps=n_training_steps)
20+
sigmas = ((1 - alphas_cumprod) / alphas_cumprod) ** 0.5
21+
log_sigmas = np.log(sigmas)
22+
log_sigmas = np.interp(timesteps, range(n_training_steps), log_sigmas)
23+
sigmas = np.exp(log_sigmas)
24+
sigmas = np.append(sigmas, 0)
25+
26+
self.sigmas = sigmas
27+
self.initial_scale = sigmas.max()
28+
self.timesteps = timesteps
29+
self.n_inference_steps = n_inference_steps
30+
self.n_training_steps = n_training_steps
31+
32+
33+
def get_input_scale(self, step_count=None):
34+
sigma = self.sigmas[step_count]
35+
return 1 / (sigma ** 2 + 1) ** 0.5
36+
37+
# def set_strength(self, strength=1):
38+
# start_step = self.n_inference_steps - int(self.n_inference_steps * strength)
39+
# self.timesteps = np.linspace(self.n_training_steps - 1, 0, self.n_inference_steps)
40+
# self.timesteps = self.timesteps[start_step:]
41+
# self.initial_scale = self.sigmas[start_step]
42+
# self.step_count = start_step
43+
44+
45+
def add_noise(self, latent, noise, idx ): #dg
46+
for i in idx:
47+
assert idx[0] == i
48+
sc = self.sigmas[idx[0]]
49+
return latent + noise*sc
50+
51+
def step(self, output , t , latents , seed ): #dg
52+
53+
54+
sigma_from = self.sigmas[t]
55+
sigma_to = self.sigmas[t + 1]
56+
sigma_up = sigma_to * (1 - (sigma_to ** 2 / sigma_from ** 2)) ** 0.5
57+
sigma_down = sigma_to ** 2 / sigma_from
58+
latents += output * (sigma_down - sigma_from)
59+
noise = np.random.RandomState(seed).normal(size=latents.shape).astype('float32')
60+
latents += noise * sigma_up
61+
return {"prev_sample": latents } #latents

backends/stable_diffusion/schedulers/scheduling_ddim.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ def __init__(
130130
self.config = self
131131
self.set_format(tensor_format=tensor_format)
132132

133+
self.initial_scale = 1
134+
135+
def get_input_scale(self, _ ):
136+
return 1
137+
133138
def _get_variance(self, timestep, prev_timestep):
134139
alpha_prod_t = self.alphas_cumprod[timestep]
135140
alpha_prod_t_prev = self.alphas_cumprod[prev_timestep] if prev_timestep >= 0 else self.final_alpha_cumprod
@@ -160,11 +165,15 @@ def step(
160165
model_output: Union[ np.ndarray],
161166
timestep: int,
162167
sample: Union[ np.ndarray],
168+
seed=None,
163169
eta: float = 0.0,
164170
use_clipped_model_output: bool = False,
165171
generator=None,
166172
return_dict: bool = True,
167173
) -> Union[ Tuple]:
174+
175+
timestep = self.timesteps[timestep]
176+
168177
"""
169178
Predict the sample at the previous timestep by reversing the SDE. Core function to propagate the diffusion
170179
process from the learned model outputs (most often the predicted noise).
@@ -249,6 +258,11 @@ def add_noise(
249258
noise: Union[ np.ndarray],
250259
timesteps: Union[np.ndarray],
251260
) -> Union[ np.ndarray]:
261+
262+
263+
timesteps = np.array([ self.timesteps[i] for i in timesteps ])
264+
265+
252266
sqrt_alpha_prod = self.alphas_cumprod[timesteps] ** 0.5
253267
sqrt_alpha_prod = self.match_shape(sqrt_alpha_prod, original_samples)
254268
sqrt_one_minus_alpha_prod = (1 - self.alphas_cumprod[timesteps]) ** 0.5

backends/stable_diffusion/schedulers/scheduling_lms_discrete.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ def __init__(
9191
self.timestep_values = timestep_values
9292
self.tensor_format = tensor_format
9393

94+
self.initial_scale = self.sigmas[0]
95+
96+
def get_input_scale(self, step_count=None):
97+
sigma = self.sigmas[step_count]
98+
return 1 / (sigma ** 2 + 1) ** 0.5
99+
94100
def get_lms_coefficient(self, order, t, current_order):
95101
"""
96102
Compute a linear multistep coefficient.
@@ -138,6 +144,7 @@ def step(
138144
model_output: Union[torch.FloatTensor, np.ndarray],
139145
timestep: int,
140146
sample: Union[torch.FloatTensor, np.ndarray],
147+
seed=None,
141148
order: int = 4,
142149
return_dict: bool = True,
143150
) -> Union[ Tuple]:

backends/stable_diffusion/schedulers/scheduling_pndm.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ def __init__(
132132
self.config = self
133133
self.set_format(tensor_format=tensor_format)
134134

135+
self.initial_scale = 1
136+
137+
def get_input_scale(self, _ ):
138+
return 1
139+
135140
def set_timesteps(self, num_inference_steps: int, offset: int = 0):
136141
"""
137142
Sets the discrete timesteps used for the diffusion chain. Supporting function to be run before inference.
@@ -175,8 +180,12 @@ def step(
175180
model_output: Union[ np.ndarray],
176181
timestep: int,
177182
sample: Union[ np.ndarray],
183+
seed=None,
178184
return_dict: bool = True,
179185
) -> Union[SchedulerOutput, Tuple]:
186+
187+
timestep = self.timesteps[timestep]
188+
180189
"""
181190
Predict the sample at the previous timestep by reversing the SDE. Core function to propagate the diffusion
182191
process from the learned model outputs (most often the predicted noise).
@@ -354,6 +363,9 @@ def add_noise(
354363
noise: Union[ np.ndarray],
355364
timesteps: Union[ np.ndarray],
356365
) :
366+
367+
timesteps = np.array([ self.timesteps[i] for i in timesteps ])
368+
357369
# mps requires indices to be in the same device, so we use cpu as is the default with cuda
358370
timesteps = timesteps.to(self.alphas_cumprod.device)
359371
sqrt_alpha_prod = self.alphas_cumprod[timesteps] ** 0.5

backends/stable_diffusion/stable_diffusion.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
from schedulers.scheduling_ddim import DDIMScheduler
4343
from schedulers.scheduling_lms_discrete import LMSDiscreteScheduler
4444
from schedulers.scheduling_pndm import PNDMScheduler
45+
from schedulers.k_euler_ancestral import KEulerAncestralSampler
46+
from schedulers.k_euler import KEulerSampler
4547

4648
def process_inp_img(input_image):
4749
input_image = Image.open(input_image)
@@ -128,6 +130,12 @@ def get_scheduler(name):
128130
skip_prk_steps = True,
129131
tensor_format="np")
130132

133+
if name == "k_euler_ancestral":
134+
return KEulerAncestralSampler()
135+
136+
if name == "k_euler":
137+
return KEulerSampler()
138+
131139

132140
def dummy_callback(state="" , progress=-1):
133141
pass
@@ -283,18 +291,14 @@ def prepare_init_latent(self , sd_run):
283291
# latent_np = latent_np * np.float64(self.scheduler.init_noise_sigma)
284292
sd_run.latent = latent_np
285293

286-
if isinstance(self.scheduler, LMSDiscreteScheduler):
287-
sd_run.latent = sd_run.latent * self.scheduler.sigmas[0]
294+
sd_run.latent = sd_run.latent * self.scheduler.initial_scale
288295

289296
else:
290297
latent = self.get_encoded_img(sd_run , sd_run.input_image_processed )
291298
sd_run.encoded_img_unmasked = np.copy(latent)
292299

293-
if isinstance(self.scheduler, LMSDiscreteScheduler):
294-
start_timestep = np.array([self.t_to_i(sd_run.start_timestep)] * sd_run.batch_size, dtype=np.int64 )
295-
else:
296-
start_timestep = np.array([sd_run.start_timestep] * sd_run.batch_size, dtype=np.int64 )
297-
300+
start_timestep = np.array([self.t_to_i(sd_run.start_timestep)] * sd_run.batch_size, dtype=np.int64 )
301+
298302
noise = self.get_noise(sd_run.seed , latent.shape )
299303
latent = self.scheduler.add_noise(latent, noise, start_timestep )
300304
sd_run.latent = latent
@@ -344,12 +348,8 @@ def get_unet_out(self, sd_run):
344348
np.repeat( (1 - sd_run.processed_mask_downscaled ), sd_run.batch_size , axis=0) ,
345349
sd_run.encoded_masked_img
346350
], axis=-1)
347-
348-
if isinstance(self.scheduler, LMSDiscreteScheduler):
349-
sigma = self.scheduler.sigmas[self.t_to_i(t)]
350-
latent_model_input = latent_model_input / ((sigma**2 + 1) ** 0.5)
351-
352-
# latent_model_input = self.scheduler.scale_model_input(sd_run.latent, t)
351+
352+
latent_model_input = latent_model_input * self.scheduler.get_input_scale(self.t_to_i(t))
353353

354354
if sd_run.combine_unet_run:
355355
latent_combined = np.concatenate([latent_model_input,latent_model_input])
@@ -374,22 +374,16 @@ def get_next_latent(self, sd_run ):
374374
eta = 0.0 # should be between 0 and 1, but 0 for now
375375
extra_step_kwargs["eta"] = eta
376376

377-
if isinstance(self.scheduler, LMSDiscreteScheduler):
378-
latents = self.scheduler.step(noise_pred, self.t_to_i(t), sd_run.latent, **extra_step_kwargs)["prev_sample"]
379-
else:
380-
latents = self.scheduler.step(noise_pred, t, sd_run.latent, **extra_step_kwargs)["prev_sample"]
377+
step_seed = sd_run.seed + 10000 + self.t_to_i(t)*4242
378+
latents = self.scheduler.step(noise_pred, self.t_to_i(t), sd_run.latent , seed=step_seed , **extra_step_kwargs)["prev_sample"]
379+
381380

382381
if sd_run.do_masking:
383382

384383
latent_proper = np.copy(sd_run.encoded_img_unmasked)
385384

386385
noise = self.get_noise(sd_run.seed , latent_proper.shape )
387-
388-
if isinstance(self.scheduler, LMSDiscreteScheduler):
389-
latent_proper = self.scheduler.add_noise(latent_proper, noise, np.array([self.t_to_i(sd_run.current_t)] * sd_run.batch_size, dtype=np.int64 ) )
390-
else:
391-
latent_proper = self.scheduler.add_noise(latent_proper, noise, np.array([sd_run.current_t] * sd_run.batch_size, dtype=np.int64 ) )
392-
386+
latent_proper = self.scheduler.add_noise(latent_proper, noise, np.array([self.t_to_i(sd_run.current_t)] * sd_run.batch_size, dtype=np.int64 ) )
393387

394388
latents = (latent_proper * sd_run.processed_mask_downscaled) + (latents * (1 - sd_run.processed_mask_downscaled))
395389

@@ -413,7 +407,7 @@ def generate(
413407
mask_image=None,
414408
negative_prompt="",
415409
input_image_strength=0.5,
416-
scheduler='pndm',
410+
scheduler='k_euler',
417411
tdict_path=None, # if none then it will just use current one
418412
dtype='float16',
419413
mode="txt2img" # txt2img , img2img, inpaint_15

electron_app/src/bridge.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@ function start_bridge() {
9292

9393
if(RESTART_BACKEND_ON_CLOSE){
9494
// dialog.showMessageBox( win , { message: "Error in backend : " + last_few_err }); // this is non blocking
95-
if(!(last_few_err.includes("leaked semaphore objects to clean up at shutdown"))){
96-
// this leaked semaphore issue just happens sometimes. so for now lets just silently restart
97-
dialog.showMessageBox( { message: "Error in backend : " + last_few_err });
98-
}
99-
95+
// if(!(last_few_err.includes("leaked semaphore objects to clean up at shutdown"))){
96+
// // this leaked semaphore issue just happens sometimes. so for now lets just silently restart
97+
// dialog.showMessageBox( { message: "Error in backend : " + last_few_err });
98+
// }
99+
dialog.showMessageBox( { message: "Error in backend : " + last_few_err });
100100
return start_bridge()
101101
}
102102
else{

0 commit comments

Comments
 (0)