Skip to content

Commit 34f726c

Browse files
dg845ayushmangalayushtuespatrickvonplaten
authored
Add Consistency Models Pipeline (huggingface#3492)
* initial commit * Improve consistency models sampling implementation. * Add CMStochasticIterativeScheduler, which implements the multi-step sampler (stochastic_iterative_sampler) in the original code, and make further improvements to sampling. * Add Unet blocks for consistency models * Add conversion script for Unet * Fix bug in new unet blocks * Fix attention weight loading * Make design improvements to ConsistencyModelPipeline and CMStochasticIterativeScheduler and add initial version of tests. * make style * Make small random test UNet class conditional and set resnet_time_scale_shift to 'scale_shift' to better match consistency model checkpoints. * Add support for converting a test UNet and non-class-conditional UNets to the consistency models conversion script. * make style * Change num_class_embeds to 1000 to better match the original consistency models implementation. * Add support for distillation in pipeline_consistency_models.py. * Improve consistency model tests: - Get small testing checkpoints from hub - Modify tests to take into account "distillation" parameter of ConsistencyModelPipeline - Add onestep, multistep tests for distillation and distillation + class conditional - Add expected image slices for onestep tests * make style * Improve ConsistencyModelPipeline: - Add initial support for class-conditional generation - Fix initial sigma for onestep generation - Fix some sigma shape issues * make style * Improve ConsistencyModelPipeline: - add latents __call__ argument and prepare_latents method - add check_inputs method - add initial docstrings for ConsistencyModelPipeline.__call__ * make style * Fix bug when randomly generating class labels for class-conditional generation. * Switch CMStochasticIterativeScheduler to configuring a sigma schedule and make related changes to the pipeline and tests. * Remove some unused code and make style. * Fix small bug in CMStochasticIterativeScheduler. * Add expected slices for multistep sampling tests and make them pass. * Work on consistency model fast tests: - in pipeline, call self.scheduler.scale_model_input before denoising - get expected slices for Euler and Heun scheduler tests - make Euler test pass - mark Heun test as expected fail because it doesn't support prediction_type "sample" yet - remove DPM and Euler Ancestral tests because they don't support use_karras_sigmas * make style * Refactor conversion script to make it easier to add more model architectures to convert in the future. * Work on ConsistencyModelPipeline tests: - Fix device bug when handling class labels in ConsistencyModelPipeline.__call__ - Add slow tests for onestep and multistep sampling and make them pass - Refactor fast tests - Refactor ConsistencyModelPipeline.__init__ * make style * Remove the add_noise and add_noise_to_input methods from CMStochasticIterativeScheduler for now. * Run python utils/check_copies.py --fix_and_overwrite python utils/check_dummies.py --fix_and_overwrite to make dummy objects for new pipeline and scheduler. * Make fast tests from PipelineTesterMixin pass. * make style * Refactor consistency models pipeline and scheduler: - Remove support for Karras schedulers (only support CMStochasticIterativeScheduler) - Move sigma manipulation, input scaling, denoising from pipeline to scheduler - Make corresponding changes to tests and ensure they pass * make style * Add docstrings and further refactor pipeline and scheduler. * make style * Add initial version of the consistency models documentation. * Refactor custom timesteps logic following DDPMScheduler/IFPipeline and temporarily add torch 2.0 SDPA kernel selection logic for debugging. * make style * Convert current slow tests to use fp16 and flash attention. * make style * Add slow tests for normal attention on cuda device. * make style * Fix attention weights loading * Update consistency model fast tests for new test checkpoints with attention fix. * make style * apply suggestions * Add add_noise method to CMStochasticIterativeScheduler (copied from EulerDiscreteScheduler). * Conversion script now outputs pipeline instead of UNet and add support for LSUN-256 models and different schedulers. * When both timesteps and num_inference_steps are supplied, raise warning instead of error (timesteps take precedence). * make style * Add remaining diffusers model checkpoints for models in the original consistency model release and update usage example. * apply suggestions from review * make style * fix attention naming * Add tests for CMStochasticIterativeScheduler. * make style * Make CMStochasticIterativeScheduler tests pass. * make style * Override test_step_shape in CMStochasticIterativeSchedulerTest instead of modifying it in SchedulerCommonTest. * make style * rename some models * Improve API * rename some models * Remove duplicated block * Add docstring and make torch compile work * More fixes * Fixes * Apply suggestions from code review * Apply suggestions from code review * add more docstring * update consistency conversion script --------- Co-authored-by: ayushmangal <ayushmangal@microsoft.com> Co-authored-by: Ayush Mangal <43698245+ayushtues@users.noreply.github.com> Co-authored-by: Patrick von Platen <patrick.v.platen@gmail.com>
1 parent 5582f56 commit 34f726c

9 files changed

Lines changed: 825 additions & 9 deletions

File tree

__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
)
5959
from .pipelines import (
6060
AudioPipelineOutput,
61+
ConsistencyModelPipeline,
6162
DanceDiffusionPipeline,
6263
DDIMPipeline,
6364
DDPMPipeline,
@@ -72,6 +73,7 @@
7273
ScoreSdeVePipeline,
7374
)
7475
from .schedulers import (
76+
CMStochasticIterativeScheduler,
7577
DDIMInverseScheduler,
7678
DDIMParallelScheduler,
7779
DDIMScheduler,

models/unet_2d.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ class UNet2DModel(ModelMixin, ConfigMixin):
6666
layers_per_block (`int`, *optional*, defaults to `2`): The number of layers per block.
6767
mid_block_scale_factor (`float`, *optional*, defaults to `1`): The scale factor for the mid block.
6868
downsample_padding (`int`, *optional*, defaults to `1`): The padding for the downsample convolution.
69+
downsample_type (`str`, *optional*, defaults to `conv`):
70+
The downsample type for downsampling layers. Choose between "conv" and "resnet"
71+
upsample_type (`str`, *optional*, defaults to `conv`):
72+
The upsample type for upsampling layers. Choose between "conv" and "resnet"
6973
act_fn (`str`, *optional*, defaults to `"silu"`): The activation function to use.
7074
attention_head_dim (`int`, *optional*, defaults to `8`): The attention head dimension.
7175
norm_num_groups (`int`, *optional*, defaults to `32`): The number of groups for normalization.
@@ -96,6 +100,8 @@ def __init__(
96100
layers_per_block: int = 2,
97101
mid_block_scale_factor: float = 1,
98102
downsample_padding: int = 1,
103+
downsample_type: str = "conv",
104+
upsample_type: str = "conv",
99105
act_fn: str = "silu",
100106
attention_head_dim: Optional[int] = 8,
101107
norm_num_groups: int = 32,
@@ -168,6 +174,7 @@ def __init__(
168174
attention_head_dim=attention_head_dim if attention_head_dim is not None else output_channel,
169175
downsample_padding=downsample_padding,
170176
resnet_time_scale_shift=resnet_time_scale_shift,
177+
downsample_type=downsample_type,
171178
)
172179
self.down_blocks.append(down_block)
173180

@@ -207,6 +214,7 @@ def __init__(
207214
resnet_groups=norm_num_groups,
208215
attention_head_dim=attention_head_dim if attention_head_dim is not None else output_channel,
209216
resnet_time_scale_shift=resnet_time_scale_shift,
217+
upsample_type=upsample_type,
210218
)
211219
self.up_blocks.append(up_block)
212220
prev_output_channel = output_channel

models/unet_2d_blocks.py

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def get_down_block(
5151
resnet_out_scale_factor=1.0,
5252
cross_attention_norm=None,
5353
attention_head_dim=None,
54+
downsample_type=None,
5455
):
5556
# If attn head dim is not defined, we default it to the number of heads
5657
if attention_head_dim is None:
@@ -88,18 +89,22 @@ def get_down_block(
8889
output_scale_factor=resnet_out_scale_factor,
8990
)
9091
elif down_block_type == "AttnDownBlock2D":
92+
if add_downsample is False:
93+
downsample_type = None
94+
else:
95+
downsample_type = downsample_type or "conv" # default to 'conv'
9196
return AttnDownBlock2D(
9297
num_layers=num_layers,
9398
in_channels=in_channels,
9499
out_channels=out_channels,
95100
temb_channels=temb_channels,
96-
add_downsample=add_downsample,
97101
resnet_eps=resnet_eps,
98102
resnet_act_fn=resnet_act_fn,
99103
resnet_groups=resnet_groups,
100104
downsample_padding=downsample_padding,
101105
attention_head_dim=attention_head_dim,
102106
resnet_time_scale_shift=resnet_time_scale_shift,
107+
downsample_type=downsample_type,
103108
)
104109
elif down_block_type == "CrossAttnDownBlock2D":
105110
if cross_attention_dim is None:
@@ -239,6 +244,7 @@ def get_up_block(
239244
resnet_out_scale_factor=1.0,
240245
cross_attention_norm=None,
241246
attention_head_dim=None,
247+
upsample_type=None,
242248
):
243249
# If attn head dim is not defined, we default it to the number of heads
244250
if attention_head_dim is None:
@@ -319,18 +325,23 @@ def get_up_block(
319325
cross_attention_norm=cross_attention_norm,
320326
)
321327
elif up_block_type == "AttnUpBlock2D":
328+
if add_upsample is False:
329+
upsample_type = None
330+
else:
331+
upsample_type = upsample_type or "conv" # default to 'conv'
332+
322333
return AttnUpBlock2D(
323334
num_layers=num_layers,
324335
in_channels=in_channels,
325336
out_channels=out_channels,
326337
prev_output_channel=prev_output_channel,
327338
temb_channels=temb_channels,
328-
add_upsample=add_upsample,
329339
resnet_eps=resnet_eps,
330340
resnet_act_fn=resnet_act_fn,
331341
resnet_groups=resnet_groups,
332342
attention_head_dim=attention_head_dim,
333343
resnet_time_scale_shift=resnet_time_scale_shift,
344+
upsample_type=upsample_type,
334345
)
335346
elif up_block_type == "SkipUpBlock2D":
336347
return SkipUpBlock2D(
@@ -747,11 +758,12 @@ def __init__(
747758
attention_head_dim=1,
748759
output_scale_factor=1.0,
749760
downsample_padding=1,
750-
add_downsample=True,
761+
downsample_type="conv",
751762
):
752763
super().__init__()
753764
resnets = []
754765
attentions = []
766+
self.downsample_type = downsample_type
755767

756768
if attention_head_dim is None:
757769
logger.warn(
@@ -793,14 +805,32 @@ def __init__(
793805
self.attentions = nn.ModuleList(attentions)
794806
self.resnets = nn.ModuleList(resnets)
795807

796-
if add_downsample:
808+
if downsample_type == "conv":
797809
self.downsamplers = nn.ModuleList(
798810
[
799811
Downsample2D(
800812
out_channels, use_conv=True, out_channels=out_channels, padding=downsample_padding, name="op"
801813
)
802814
]
803815
)
816+
elif downsample_type == "resnet":
817+
self.downsamplers = nn.ModuleList(
818+
[
819+
ResnetBlock2D(
820+
in_channels=out_channels,
821+
out_channels=out_channels,
822+
temb_channels=temb_channels,
823+
eps=resnet_eps,
824+
groups=resnet_groups,
825+
dropout=dropout,
826+
time_embedding_norm=resnet_time_scale_shift,
827+
non_linearity=resnet_act_fn,
828+
output_scale_factor=output_scale_factor,
829+
pre_norm=resnet_pre_norm,
830+
down=True,
831+
)
832+
]
833+
)
804834
else:
805835
self.downsamplers = None
806836

@@ -810,11 +840,14 @@ def forward(self, hidden_states, temb=None, upsample_size=None):
810840
for resnet, attn in zip(self.resnets, self.attentions):
811841
hidden_states = resnet(hidden_states, temb)
812842
hidden_states = attn(hidden_states)
813-
output_states += (hidden_states,)
843+
output_states = output_states + (hidden_states,)
814844

815845
if self.downsamplers is not None:
816846
for downsampler in self.downsamplers:
817-
hidden_states = downsampler(hidden_states)
847+
if self.downsample_type == "resnet":
848+
hidden_states = downsampler(hidden_states, temb=temb)
849+
else:
850+
hidden_states = downsampler(hidden_states)
818851

819852
output_states += (hidden_states,)
820853

@@ -1860,12 +1893,14 @@ def __init__(
18601893
resnet_pre_norm: bool = True,
18611894
attention_head_dim=1,
18621895
output_scale_factor=1.0,
1863-
add_upsample=True,
1896+
upsample_type="conv",
18641897
):
18651898
super().__init__()
18661899
resnets = []
18671900
attentions = []
18681901

1902+
self.upsample_type = upsample_type
1903+
18691904
if attention_head_dim is None:
18701905
logger.warn(
18711906
f"It is not recommend to pass `attention_head_dim=None`. Defaulting `attention_head_dim` to `in_channels`: {out_channels}."
@@ -1908,8 +1943,26 @@ def __init__(
19081943
self.attentions = nn.ModuleList(attentions)
19091944
self.resnets = nn.ModuleList(resnets)
19101945

1911-
if add_upsample:
1946+
if upsample_type == "conv":
19121947
self.upsamplers = nn.ModuleList([Upsample2D(out_channels, use_conv=True, out_channels=out_channels)])
1948+
elif upsample_type == "resnet":
1949+
self.upsamplers = nn.ModuleList(
1950+
[
1951+
ResnetBlock2D(
1952+
in_channels=out_channels,
1953+
out_channels=out_channels,
1954+
temb_channels=temb_channels,
1955+
eps=resnet_eps,
1956+
groups=resnet_groups,
1957+
dropout=dropout,
1958+
time_embedding_norm=resnet_time_scale_shift,
1959+
non_linearity=resnet_act_fn,
1960+
output_scale_factor=output_scale_factor,
1961+
pre_norm=resnet_pre_norm,
1962+
up=True,
1963+
)
1964+
]
1965+
)
19131966
else:
19141967
self.upsamplers = None
19151968

@@ -1925,7 +1978,10 @@ def forward(self, hidden_states, res_hidden_states_tuple, temb=None, upsample_si
19251978

19261979
if self.upsamplers is not None:
19271980
for upsampler in self.upsamplers:
1928-
hidden_states = upsampler(hidden_states)
1981+
if self.upsample_type == "resnet":
1982+
hidden_states = upsampler(hidden_states, temb=temb)
1983+
else:
1984+
hidden_states = upsampler(hidden_states)
19291985

19301986
return hidden_states
19311987

pipelines/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
except OptionalDependencyNotAvailable:
1717
from ..utils.dummy_pt_objects import * # noqa F403
1818
else:
19+
from .consistency_models import ConsistencyModelPipeline
1920
from .dance_diffusion import DanceDiffusionPipeline
2021
from .ddim import DDIMPipeline
2122
from .ddpm import DDPMPipeline
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .pipeline_consistency_models import ConsistencyModelPipeline

0 commit comments

Comments
 (0)