-
Notifications
You must be signed in to change notification settings - Fork 7.1k
add a step_index counter #4347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add a step_index counter #4347
Changes from all commits
6523166
de6824a
36947b0
f50669a
8435516
ef3a07e
2d1510a
adcd0d5
315c008
eede2a8
5434664
57a0ec7
67f87ca
5ade10b
71c3710
57dc0cd
71f4a19
03d502f
9ba5533
2c42f9c
aca5c1f
3dff6cb
9c97566
724f8a2
c3acc9b
9093a72
a0df5e0
fadacf5
47b3a98
1983a78
16d0331
fb73cc7
76dbce5
affa2ba
00c9512
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -166,6 +166,8 @@ def __init__( | |
| self.timesteps = torch.from_numpy(timesteps) | ||
| self.is_scale_input_called = False | ||
|
|
||
| self._step_index = None | ||
|
|
||
| @property | ||
| def init_noise_sigma(self): | ||
| # standard deviation of the initial noise distribution | ||
|
|
@@ -174,6 +176,13 @@ def init_noise_sigma(self): | |
|
|
||
| return (self.sigmas.max() ** 2 + 1) ** 0.5 | ||
|
|
||
| @property | ||
| def step_index(self): | ||
| """ | ||
| The index counter for current timestep. It will increae 1 after each scheduler step. | ||
| """ | ||
| return self._step_index | ||
|
|
||
| def scale_model_input( | ||
| self, sample: torch.FloatTensor, timestep: Union[float, torch.FloatTensor] | ||
| ) -> torch.FloatTensor: | ||
|
|
@@ -187,10 +196,11 @@ def scale_model_input( | |
| Returns: | ||
| `torch.FloatTensor`: scaled input sample | ||
| """ | ||
| if isinstance(timestep, torch.Tensor): | ||
| timestep = timestep.to(self.timesteps.device) | ||
| step_index = (self.timesteps == timestep).nonzero().item() | ||
| sigma = self.sigmas[step_index] | ||
|
|
||
| if self.step_index is None: | ||
| self._init_step_index(timestep) | ||
|
|
||
| sigma = self.sigmas[self.step_index] | ||
| sample = sample / ((sigma**2 + 1) ** 0.5) | ||
| self.is_scale_input_called = True | ||
| return sample | ||
|
|
@@ -209,20 +219,20 @@ def set_timesteps(self, num_inference_steps: int, device: Union[str, torch.devic | |
|
|
||
| # "linspace", "leading", "trailing" corresponds to annotation of Table 2. of https://arxiv.org/abs/2305.08891 | ||
| if self.config.timestep_spacing == "linspace": | ||
| timesteps = np.linspace(0, self.config.num_train_timesteps - 1, num_inference_steps, dtype=float)[ | ||
| timesteps = np.linspace(0, self.config.num_train_timesteps - 1, num_inference_steps, dtype=np.float32)[ | ||
| ::-1 | ||
| ].copy() | ||
| elif self.config.timestep_spacing == "leading": | ||
| step_ratio = self.config.num_train_timesteps // self.num_inference_steps | ||
| # creates integer timesteps by multiplying by ratio | ||
| # casting to int to avoid issues when num_inference_step is power of 3 | ||
| timesteps = (np.arange(0, num_inference_steps) * step_ratio).round()[::-1].copy().astype(float) | ||
| timesteps = (np.arange(0, num_inference_steps) * step_ratio).round()[::-1].copy().astype(np.float32) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @patrickvonplaten Let me know if we need to run more tests before we can change everything to float32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. think this is fine indeed |
||
| timesteps += self.config.steps_offset | ||
| elif self.config.timestep_spacing == "trailing": | ||
| step_ratio = self.config.num_train_timesteps / self.num_inference_steps | ||
| # creates integer timesteps by multiplying by ratio | ||
| # casting to int to avoid issues when num_inference_step is power of 3 | ||
| timesteps = (np.arange(self.config.num_train_timesteps, 0, -step_ratio)).round().copy().astype(float) | ||
| timesteps = (np.arange(self.config.num_train_timesteps, 0, -step_ratio)).round().copy().astype(np.float32) | ||
| timesteps -= 1 | ||
| else: | ||
| raise ValueError( | ||
|
|
@@ -233,11 +243,27 @@ def set_timesteps(self, num_inference_steps: int, device: Union[str, torch.devic | |
| sigmas = np.interp(timesteps, np.arange(0, len(sigmas)), sigmas) | ||
| sigmas = np.concatenate([sigmas, [0.0]]).astype(np.float32) | ||
| self.sigmas = torch.from_numpy(sigmas).to(device=device) | ||
| if str(device).startswith("mps"): | ||
| # mps does not support float64 | ||
| self.timesteps = torch.from_numpy(timesteps).to(device, dtype=torch.float32) | ||
|
|
||
| self.timesteps = torch.from_numpy(timesteps).to(device=device) | ||
| self._step_index = None | ||
|
|
||
| # Copied from diffusers.schedulers.scheduling_euler_discrete.EulerDiscreteScheduler._init_step_index | ||
| def _init_step_index(self, timestep): | ||
| if isinstance(timestep, torch.Tensor): | ||
| timestep = timestep.to(self.timesteps.device) | ||
|
|
||
| index_candidates = (self.timesteps == timestep).nonzero() | ||
|
|
||
| # The sigma index that is taken for the **very** first `step` | ||
| # is always the second index (or the last index if there is only 1) | ||
| # This way we can ensure we don't accidentally skip a sigma in | ||
| # case we start in the middle of the denoising schedule (e.g. for image-to-image) | ||
| if len(index_candidates) > 1: | ||
| step_index = index_candidates[1] | ||
| else: | ||
| self.timesteps = torch.from_numpy(timesteps).to(device=device) | ||
| step_index = index_candidates[0] | ||
|
yiyixuxu marked this conversation as resolved.
|
||
|
|
||
| self._step_index = step_index.item() | ||
|
|
||
| def step( | ||
| self, | ||
|
|
@@ -285,11 +311,10 @@ def step( | |
| "See `StableDiffusionPipeline` for a usage example." | ||
| ) | ||
|
|
||
| if isinstance(timestep, torch.Tensor): | ||
| timestep = timestep.to(self.timesteps.device) | ||
| if self.step_index is None: | ||
| self._init_step_index(timestep) | ||
|
|
||
| step_index = (self.timesteps == timestep).nonzero().item() | ||
| sigma = self.sigmas[step_index] | ||
| sigma = self.sigmas[self.step_index] | ||
|
|
||
| # 1. compute predicted original sample (x_0) from sigma-scaled predicted noise | ||
| if self.config.prediction_type == "epsilon": | ||
|
|
@@ -304,8 +329,8 @@ def step( | |
| f"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, or `v_prediction`" | ||
| ) | ||
|
|
||
| sigma_from = self.sigmas[step_index] | ||
| sigma_to = self.sigmas[step_index + 1] | ||
| sigma_from = self.sigmas[self.step_index] | ||
| sigma_to = self.sigmas[self.step_index + 1] | ||
| sigma_up = (sigma_to**2 * (sigma_from**2 - sigma_to**2) / sigma_from**2) ** 0.5 | ||
| sigma_down = (sigma_to**2 - sigma_up**2) ** 0.5 | ||
|
|
||
|
|
@@ -321,6 +346,9 @@ def step( | |
|
|
||
| prev_sample = prev_sample + noise * sigma_up | ||
|
|
||
| # upon completion increase step index by one | ||
| self._step_index += 1 | ||
|
|
||
| if not return_dict: | ||
| return (prev_sample,) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@patrickvonplaten
pix2pix_zero has two denoising loops so we have to reset the timesteps before the second one to set the
_step_indextoNoneand restart the counter againis this ok?