Skip to content
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 EDMEulerScheduler #7109

Merged
merged 6 commits into from
Feb 27, 2024
Merged

Add EDMEulerScheduler #7109

merged 6 commits into from
Feb 27, 2024

Conversation

patil-suraj
Copy link
Contributor

@patil-suraj patil-suraj commented Feb 27, 2024

What does this PR do?

This PR is based on #4481 by @dg845 !

This PR adds Euler scheduler with EDM formulation. The difference between this and EulerDiscreteScheduler is that

  • EulerDiscreteScheduler was essentially designed for DDPM models to use euler-style sampling algorithms with discrete timesteps.
  • EDMEulerScheduler follows the EDM formulation as closely as possible and is solely intended for models that use EDM formulation, like SVD. It does not support epsilon scaling as that's already covered by EulerDiscreteScheduler. So models that still DDPM (the alphas and betas schedules) should keep using EulerDiscreteScheduler

Why add a new scheduler class ?
While it is possible to support this in EulerDiscreteScheduler by introducing an argument maybe called scaling_type, which could correspond to epsilon (ddpm) v-scaling or edm, the issue is that:

  • the naming is inconsistent. With edm, the model is conditioned on continuous noise scales rather than discrete timesteps.
  • There is some functionality in EulerDiscreteScheduler that is not required for EDM, such as computing betas, rescaling for zero terminal SNR, interpolating sigmas etc.

Hence with the current schedule API if we support full EDM formulation in EulerDiscreteScheduler, the code will be confusing to follow with lot's of if/else branches.

API

scheduler = EDMEulerScheduler(sigma_min=0.002, sigma_max=80.0, sigma_data=0.5)

scheduler.sigmas # computed directly as per the karras paper 
scheduler.timesteps # this is the `c_noise` which is fed to the model instead of discrete timestep

# to precondition input
sample = scheduler.precondition_inputs(sample, sigma)

# to get the c_noise
c_noise = scheduler.precondition_noise(sigma) 

# precondition output
output = scheduler.precondition_outputs(sample, model_output, sigma)

These pre-conditioning methods can be used during training to easily scale the input/output based on sigma values, which the user is free to sample in any way they want during training.

We could also consider adding a method to help with sigma sampling as per here

The rest of the API follows the existing scheduler API.

I would love to have your thoughts here @yiyixuxu @sayakpaul @dhruvrnaik @dg845

@HuggingFaceDocBuilderDev

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

Comment on lines +305 to +307
s_churn (`float`):
s_tmin (`float`):
s_tmax (`float`):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to have docstrings.


return EDMEulerSchedulerOutput(prev_sample=prev_sample, pred_original_sample=pred_original_sample)

def add_noise(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

Comment on lines +165 to +170
if self.config.prediction_type == "epsilon":
c_out = sigma * sigma_data / (sigma**2 + sigma_data**2) ** 0.5
elif self.config.prediction_type == "v_prediction":
c_out = -sigma * sigma_data / (sigma**2 + sigma_data**2) ** 0.5
else:
raise ValueError(f"Prediction type {self.config.prediction_type} is not supported.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess users will have to do this bit manually during training when experimenting with different prediction types?

Copy link
Member

@sayakpaul sayakpaul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design looks very nice to me!

Copy link
Collaborator

@yiyixuxu yiyixuxu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good to me:)

question:
for v_prediction: does it work the same as in what's currently implemented in EulerDiscreteScheduler?

src/diffusers/schedulers/scheduling_edm_euler.py Outdated Show resolved Hide resolved
@patil-suraj
Copy link
Contributor Author

for v_prediction: does it work the same as in what's currently implemented in EulerDiscreteScheduler?

@yiyixuxu Yes, that's right. EulerDiscreteScheduler would work the same way if sigma_min , sigma_max is provided and timestep_type==continuous

Actually not sure if we should put it here, it's used to SVD and follows EDM as well.

@sayakpaul
Copy link
Member

I think okay to put it there as it helps the community to experiment with different prediction types and provide us feedback if needed. We can iterate on top of that.

@patil-suraj patil-suraj marked this pull request as ready for review February 27, 2024 08:37
Co-authored-by: Daniel Gu dgu8957@gmail.com
@patil-suraj patil-suraj merged commit f57e7bd into main Feb 27, 2024
15 checks passed
@patil-suraj patil-suraj deleted the edm-euler branch February 27, 2024 12:21
Beinsezii pushed a commit to Beinsezii/diffusers that referenced this pull request Feb 28, 2024
* Add EDMEulerScheduler

* address review comments

* fix import

* fix test

* add tests

* add co-author

Co-authored-by:  @dg845 dgu8957@gmail.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants