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 multistep DPM-Solver discrete scheduler #1132

Merged

Conversation

LuChengTHU
Copy link
Contributor

@LuChengTHU LuChengTHU commented Nov 4, 2022

Add the multistep version of DPM-Solver, accepting discrete time steps as DDPM, DDIM, and PNDM.

The solver can successfully run with the stable-diffusion pipeline for both pytorch and jax versions.

Currently, it supports the following algorithms:

  • multistep DPM-Solver (for discretizing the integral w.r.t. noise prediction model) with order = 1, 2, 3
  • multistep DPM-Solver++ (for discretizing the integral w.r.t. data prediction model) with order = 1, 2, 3

For more details of the algorithms, please refer to https://github.com/LuChengTHU/dpm-solver

#1101

@HuggingFaceDocBuilderDev
Copy link

HuggingFaceDocBuilderDev commented Nov 4, 2022

The documentation is not available anymore as the PR was closed or merged.

Copy link
Contributor

@patil-suraj patil-suraj left a comment

Choose a reason for hiding this comment

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

Great work @LuChengTHU, super cool PR!

The PR already looks super good, I just left some nits.

Also tried it out with stable diffusion and it works really well, and generates really good output with 20-25 steps, for some examples even 10-15 🤯 !

QQ: What are the recommended setting for stable diffusion, I used the following and it worked super well. We will need to update these in the config of sd checkpoints.

dpm = DPMSolverDiscreteScheduler.from_config("CompVis/stable-diffusion-v1-4", subfolder="scheduler", solver_order=2, predict_x0=False, denoise_final=True)

And is this scheduler different from the DPM version which requires two model evaluation per step ?

We are still thinking about an API for schedulers that require two model evaluations. Will have a draft PR next week. Then we can add the other version of DPM once the API is finalised.

Also, to differentiate it from the other scheduler could we call this DPMMultiStepScheduler ?

src/diffusers/__init__.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_discrete.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_discrete.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_discrete.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_discrete.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_discrete.py Outdated Show resolved Hide resolved
tests/test_config.py Outdated Show resolved Hide resolved
tests/test_config.py Outdated Show resolved Hide resolved
tests/test_scheduler.py Outdated Show resolved Hide resolved
@LuChengTHU
Copy link
Contributor Author

LuChengTHU commented Nov 4, 2022

Great work @LuChengTHU, super cool PR!

The PR already looks super good, I just left some nits.

Also tried it out with stable diffusion and it works really well, and generates really good output with 20-25 steps, for some examples even 10-15 🤯 !

QQ: What are the recommended setting for stable diffusion, I used the following and it worked super well. We will need to update these in the config of sd checkpoints.

dpm = DPMSolverDiscreteScheduler.from_config("CompVis/stable-diffusion-v1-4", subfolder="scheduler", solver_order=2, predict_x0=False, denoise_final=True)

And is this scheduler different from the DPM version which requires two model evaluation per step ?

We are still thinking about an API for schedulers that require two model evaluations. Will have a draft PR next week. Then we can add the other version of DPM once the API is finalised.

Also, to differentiate it from the other scheduler could we call this DPMMultiStepScheduler ?

Thank you very much for the quick and high-quality review!

Q1: What are the recommended settings for stable diffusion?

I use the following setting, which works similarly to your settings:

dpm = DPMSolverMultistepScheduler.from_config(
    "CompVis/stable-diffusion-v1-4",  # or use the v1-5 version
    subfolder="scheduler",
    solver_order=2,
    predict_epsilon=True,
    thresholding=False,
    algorithm_type="dpmsolver++",
    solver_type="midpoint",
    denoise_final=True,  # the influence of this trick is effective for small (e.g. <=10) steps
)

Q2: is this scheduler different from the DPM version, which requires two model evaluations per step?

Yes, they are different. The DPM version you mentioned is actually the singlestep DPM-Solver in my repo, which is proposed by my paper "DPM-Solver". The currently committed PR version is the multistep DPM-Solver in my repo, which is proposed by my other paper "DPM-Solver++".

In the paper "DPM-Solver++", I carefully compare the different settings of the solvers for guided sampling (i.e. conditional sampling) by diffusion models, and I find that:

  1. All previous high-order solvers are unstable and fail to generate samples for large guidance scales and small steps (<20).

  2. We further proposed algorithms that discretize the integral w.r.t. the data prediction model, and can greatly stabilize the sample quality for small steps (<20). We use it as algorithm_type="dpmsolver++".

  3. We find that for large guidance scales, higher-order solvers are extremely unstable. So we only use the 2nd-order solver for guided sampling.

  4. We find that the multistep version is slightly better than the singlestep version.

Therefore, I suggest using the 2nd-order multistep DPM-Solver++, which is the above default settings.

However, the 3rd-order method is still useful for unconditional sampling, and it can achieve a better sample quality than the 2nd-order method for unconditional sampling. So I also provide a 3rd-order method in this PR.

References:
[1] DPM-Solver: https://arxiv.org/abs/2206.00927
[2] DPM-Solver++: https://arxiv.org/abs/2211.01095

Q3: We are still thinking about an API for schedulers that require two model evaluations. Will have a draft PR next week. Then we can add the other version of DPM once the API is finalised.

Great to know it! I can help to add the corresponding singlestep DPM-Solver at that time.

Q4: To differentiate it from the other scheduler could we call this DPMMultiStepScheduler ?

I've changed the name by "DPMSolverMultistepScheduler"

Q5: other modifications.

Thanks for your careful review! I will fix them in the latter commits.

@patil-suraj
Copy link
Contributor

Thanks a lot for the detailed answer and addressing the review comments @LuChengTHU ! Good to merge for me :)

@patrickvonplaten or @anton-l would be nice if you could also take quick look :)

@LuChengTHU LuChengTHU force-pushed the multistep-dpm-solver-scheduler branch from a497362 to 3ac6ab4 Compare November 6, 2022 12:40
Copy link
Contributor

@patrickvonplaten patrickvonplaten left a comment

Choose a reason for hiding this comment

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

Amazing addition @LuChengTHU!

The API choices are great and it's amazing that it fits so well with the existing API of Stable Diffusion :-)

Only left a couple of nits:

  • suggestion to rename predict_x0 to predict_epsilon for consistency
  • Add the DPM-Solver scheduler as a compatible scheduler to all other schedulers

src/diffusers/schedulers/scheduling_dpmsolver_multistep.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_multistep.py Outdated Show resolved Hide resolved
tests/test_scheduler.py Outdated Show resolved Hide resolved
tests/test_scheduler.py Outdated Show resolved Hide resolved
tests/test_scheduler.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_multistep.py Outdated Show resolved Hide resolved
src/diffusers/schedulers/scheduling_dpmsolver_multistep.py Outdated Show resolved Hide resolved
@LuChengTHU
Copy link
Contributor Author

LuChengTHU commented Nov 6, 2022

Hi @patrickvonplaten, thank you for the quick reviews! I've fixed all the modifications. The main difference is that I've changed the APIs for predict_epsilon, algorithm_type, and solver_type to a clearer way (and also changed the docs).

Looking forward to your reply!

@patil-suraj
Copy link
Contributor

Thank you for addressing the comments, let's go!

@patil-suraj patil-suraj merged commit b4a1ed8 into huggingface:main Nov 6, 2022
@LuChengTHU LuChengTHU deleted the multistep-dpm-solver-scheduler branch November 7, 2022 07:03
yoonseokjin pushed a commit to yoonseokjin/diffusers that referenced this pull request Dec 25, 2023
* add dpmsolver discrete pytorch scheduler

* fix some typos in dpm-solver pytorch

* add dpm-solver pytorch in stable-diffusion pipeline

* add jax/flax version dpm-solver

* change code style

* change code style

* add docs

* add `add_noise` method for dpmsolver

* add pytorch unit test for dpmsolver

* add dummy object for pytorch dpmsolver

* Update src/diffusers/schedulers/scheduling_dpmsolver_discrete.py

Co-authored-by: Suraj Patil <surajp815@gmail.com>

* Update tests/test_config.py

Co-authored-by: Suraj Patil <surajp815@gmail.com>

* Update tests/test_config.py

Co-authored-by: Suraj Patil <surajp815@gmail.com>

* resolve the code comments

* rename the file

* change class name

* fix code style

* add auto docs for dpmsolver multistep

* add more explanations for the stabilizing trick (for steps < 15)

* delete the dummy file

* change the API name of predict_epsilon, algorithm_type and solver_type

* add compatible lists

Co-authored-by: Suraj Patil <surajp815@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