Skip to content

feat: add logit-normal scheduler#1669

Open
stduhpf wants to merge 5 commits into
leejet:masterfrom
stduhpf:logit-normal
Open

feat: add logit-normal scheduler#1669
stduhpf wants to merge 5 commits into
leejet:masterfrom
stduhpf:logit-normal

Conversation

@stduhpf

@stduhpf stduhpf commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds support for the logit-normal schedule that supposed to be the default noise schedule for Ideogram4 (see https://github.com/ideogram-oss/ideogram4/blob/main/docs/pipeline.md#noise-schedule).

It's now set as default scheduler when running an Ideogram4 model.

Related Issue / Discussion

N/A

Additional Information

Uses Acklam's Algorithm to approximate the Inverse Normal CDF to avoid adding a boost dependency.

This scheduler has two tweakable parameters: muand std. Here are the values recommended for Ideogram (source: https://github.com/ideogram-oss/ideogram4/blob/main/src/ideogram4/sampler_configs.py)

  • 48 steps: mu=0.0, std = 1.5
  • 20 steps: mu=0.0, std = 1.75 (default)
  • 12 steps: mu=0.5, std = 1.75

They are set via the --extra-sample-args parameter. For example, for 12 steps generations, you should add --extra-sample-args "mu=0.5,std=1.75" to the cli args.

12 steps

Discrete scheduler Logit_normal scheduler (mu=0.5,std=1.75)
output output

20 steps

Discrete scheduler Logit_normal scheduler (mu=0,std=1.75)
output 1-l_n(1-x)

48 steps

Discrete scheduler Logit_normal scheduler (mu=0,std=1.5)
output - Copy (344) output - Copy (345)

Checklist

@stduhpf

stduhpf commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

I played around with the formula a bit, by carefully chosing the mean and std parameters, it seems to be possible to approximate roughly any other schedule...

Examples:

mean std closest schedule
0 1.7 discrete
0 2.6 smoothstep
-3.3 2.6 exponential

https://www.desmos.com/calculator/t8ji3ml3aq

For some reason, the recommended parameters seem to give subpar results compared to discrete (the current default), especially at high resolution (at 512x512 is should be pretty close but the resolution-aware thing steers it away at higher resolution).

Maybe it's just that I'm comparing with prompts/seeds that were cherry-picked because they were working great with the discrete scheduler.

@stduhpf stduhpf force-pushed the logit-normal branch 3 times, most recently from 6bc8091 to 9dd0471 Compare June 19, 2026 16:16
@stduhpf stduhpf marked this pull request as ready for review June 19, 2026 16:33
@stduhpf

stduhpf commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

@leejet @Green-Sky @rmatif @daniandtheweb or anyone who actualy understand this stuff, could you take a look?

I'm a bit confused by some things, like why is t_to_sigma not the inverse of sigma_to_t for Flow denoisers, and why some schedulers ignore t_to_sigma but others use it etc...

@stduhpf

stduhpf commented Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

https://github.com/Comfy-Org/ComfyUI/blob/master/comfy_extras/nodes_ideogram4.py

Looks like they flip the order and do 1-x here, I will try that and see how it looks lilke.

Edit: yeah, that's it. I must have missed something when looking at the original reference implementation.

@stduhpf stduhpf force-pushed the logit-normal branch 2 times, most recently from 4bc40ce to f4a1966 Compare June 20, 2026 14:30
Comment thread src/runtime/denoiser.hpp
Comment on lines +750 to +754
// which one is corrrect ?
float sigma = timestep;
// float sigma = t_to_sigma(timestep * TIMESTEPS);
// float sigma = t_to_sigma(timestep * (TIMESTEPS - 1));
// float sigma = t_to_sigma(timestep * TIMESTEPS - 1);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

PR is pretty much ready to merge, only thing I'd still like a second opinion on is part.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As far as I know in flow denoisers time = noise so there should be no need to be using any t_to_sigma to calculate the values.

@stduhpf stduhpf changed the title feat: add logit-normal schedule feat: add logit-normal scheduler Jun 21, 2026
@daniandtheweb

Copy link
Copy Markdown
Contributor

@leejet @Green-Sky @rmatif @daniandtheweb or anyone who actualy understand this stuff, could you take a look?

I'm a bit confused by some things, like why is t_to_sigma not the inverse of sigma_to_t for Flow denoisers, and why some schedulers ignore t_to_sigma but others use it etc...

It may not be the best explanation as I'm not really an expert on it but I'll try.

For your first question t_to_sigma is not the inverse of sigma_to_t for flow denoisers because of the need to add a shift during the denoising phase. If they were exact inverses they'd cancel the shift out.

About t_to_sigma being ignored by some schedulers I think it's mostly because some schedulers need to lookup the noise level while others calculate the noise curve independently.

@stduhpf

stduhpf commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

For your first question t_to_sigma is not the inverse of sigma_to_t for flow denoisers because of the need to add a shift during the denoising phase. If they were exact inverses they'd cancel the shift out.

I see, but even when there is no shifting, there's an off-by-one difference. I guess it's close enough?

some schedulers need to lookup the noise level while others calculate the noise curve independently.

Hmm. When the scheduler is calculating the noise curve independantly, doesn't it break compatibility with the different kinds of denoisers (or settings like flow shift)?

@wbruna

wbruna commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

I had notice that difference before (#1372). Note they are called in very different contexts; I suspect they are not really intended to be inverses of each other, despite their names.

or settings like flow shift

Hm. Yeah, I believe the schedulers should always call t_to_sigma, at least to apply the shift.

@daniandtheweb

Copy link
Copy Markdown
Contributor

I see, but even when there is no shifting, there's an off-by-one difference. I guess it's close enough?

From what I understand: yes, it's close enough.

Hmm. When the scheduler is calculating the noise curve independantly, doesn't it break compatibility with the different kinds of denoisers (or settings like flow shift)?

I haven't tested it but in theory not all schedulers should work for flow models.

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.

3 participants