CoolFace
Apppublic

cocktailpeanut/MotionDirector

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
0likes
unet_3d_condition.py501 linesDownload Raw Back to models
1# Copyright 2023 Alibaba DAMO-VILAB and The HuggingFace Team. All rights reserved.2# Copyright 2023 The ModelScope Team.3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8#     http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.15from dataclasses import dataclass16from typing import Any, Dict, List, Optional, Tuple, Union17 18import torch19import torch.nn as nn20import torch.utils.checkpoint21 22from diffusers.configuration_utils import ConfigMixin, register_to_config23from diffusers.utils import BaseOutput, logging24from diffusers.models.embeddings import TimestepEmbedding, Timesteps25from diffusers.models.modeling_utils import ModelMixin26from diffusers.models.transformer_temporal import TransformerTemporalModel27from .unet_3d_blocks import (28    CrossAttnDownBlock3D,29    CrossAttnUpBlock3D,30    DownBlock3D,31    UNetMidBlock3DCrossAttn,32    UpBlock3D,33    get_down_block,34    get_up_block,35    transformer_g_c36)37 38 39logger = logging.get_logger(__name__)  # pylint: disable=invalid-name40 41 42@dataclass43class UNet3DConditionOutput(BaseOutput):44    """45    Args:46        sample (`torch.FloatTensor` of shape `(batch_size, num_frames, num_channels, height, width)`):47            Hidden states conditioned on `encoder_hidden_states` input. Output of last layer of model.48    """49 50    sample: torch.FloatTensor51 52 53class UNet3DConditionModel(ModelMixin, ConfigMixin):54    r"""55    UNet3DConditionModel is a conditional 2D UNet model that takes in a noisy sample, conditional state, and a timestep56    and returns sample shaped output.57 58    This model inherits from [`ModelMixin`]. Check the superclass documentation for the generic methods the library59    implements for all the models (such as downloading or saving, etc.)60 61    Parameters:62        sample_size (`int` or `Tuple[int, int]`, *optional*, defaults to `None`):63            Height and width of input/output sample.64        in_channels (`int`, *optional*, defaults to 4): The number of channels in the input sample.65        out_channels (`int`, *optional*, defaults to 4): The number of channels in the output.66        down_block_types (`Tuple[str]`, *optional*, defaults to `("CrossAttnDownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D", "DownBlock2D")`):67            The tuple of downsample blocks to use.68        up_block_types (`Tuple[str]`, *optional*, defaults to `("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D",)`):69            The tuple of upsample blocks to use.70        block_out_channels (`Tuple[int]`, *optional*, defaults to `(320, 640, 1280, 1280)`):71            The tuple of output channels for each block.72        layers_per_block (`int`, *optional*, defaults to 2): The number of layers per block.73        downsample_padding (`int`, *optional*, defaults to 1): The padding to use for the downsampling convolution.74        mid_block_scale_factor (`float`, *optional*, defaults to 1.0): The scale factor to use for the mid block.75        act_fn (`str`, *optional*, defaults to `"silu"`): The activation function to use.76        norm_num_groups (`int`, *optional*, defaults to 32): The number of groups to use for the normalization.77            If `None`, it will skip the normalization and activation layers in post-processing78        norm_eps (`float`, *optional*, defaults to 1e-5): The epsilon to use for the normalization.79        cross_attention_dim (`int`, *optional*, defaults to 1280): The dimension of the cross attention features.80        attention_head_dim (`int`, *optional*, defaults to 8): The dimension of the attention heads.81    """82 83    _supports_gradient_checkpointing = True84 85    @register_to_config86    def __init__(87        self,88        sample_size: Optional[int] = None,89        in_channels: int = 4,90        out_channels: int = 4,91        down_block_types: Tuple[str] = (92            "CrossAttnDownBlock3D",93            "CrossAttnDownBlock3D",94            "CrossAttnDownBlock3D",95            "DownBlock3D",96        ),97        up_block_types: Tuple[str] = ("UpBlock3D", "CrossAttnUpBlock3D", "CrossAttnUpBlock3D", "CrossAttnUpBlock3D"),98        block_out_channels: Tuple[int] = (320, 640, 1280, 1280),99        layers_per_block: int = 2,100        downsample_padding: int = 1,101        mid_block_scale_factor: float = 1,102        act_fn: str = "silu",103        norm_num_groups: Optional[int] = 32,104        norm_eps: float = 1e-5,105        cross_attention_dim: int = 1024,106        attention_head_dim: Union[int, Tuple[int]] = 64,107    ):108        super().__init__()109 110        self.sample_size = sample_size111        self.gradient_checkpointing = False112        # Check inputs113        if len(down_block_types) != len(up_block_types):114            raise ValueError(115                f"Must provide the same number of `down_block_types` as `up_block_types`. `down_block_types`: {down_block_types}. `up_block_types`: {up_block_types}."116            )117 118        if len(block_out_channels) != len(down_block_types):119            raise ValueError(120                f"Must provide the same number of `block_out_channels` as `down_block_types`. `block_out_channels`: {block_out_channels}. `down_block_types`: {down_block_types}."121            )122 123        if not isinstance(attention_head_dim, int) and len(attention_head_dim) != len(down_block_types):124            raise ValueError(125                f"Must provide the same number of `attention_head_dim` as `down_block_types`. `attention_head_dim`: {attention_head_dim}. `down_block_types`: {down_block_types}."126            )127 128        # input129        conv_in_kernel = 3130        conv_out_kernel = 3131        conv_in_padding = (conv_in_kernel - 1) // 2132        self.conv_in = nn.Conv2d(133            in_channels, block_out_channels[0], kernel_size=conv_in_kernel, padding=conv_in_padding134        )135 136        # time137        time_embed_dim = block_out_channels[0] * 4138        self.time_proj = Timesteps(block_out_channels[0], True, 0)139        timestep_input_dim = block_out_channels[0]140 141        self.time_embedding = TimestepEmbedding(142            timestep_input_dim,143            time_embed_dim,144            act_fn=act_fn,145        )146 147        self.transformer_in = TransformerTemporalModel(148            num_attention_heads=8,149            attention_head_dim=attention_head_dim,150            in_channels=block_out_channels[0],151            num_layers=1,152        )153 154        # class embedding155        self.down_blocks = nn.ModuleList([])156        self.up_blocks = nn.ModuleList([])157 158        if isinstance(attention_head_dim, int):159            attention_head_dim = (attention_head_dim,) * len(down_block_types)160 161        # down162        output_channel = block_out_channels[0]163        for i, down_block_type in enumerate(down_block_types):164            input_channel = output_channel165            output_channel = block_out_channels[i]166            is_final_block = i == len(block_out_channels) - 1167 168            down_block = get_down_block(169                down_block_type,170                num_layers=layers_per_block,171                in_channels=input_channel,172                out_channels=output_channel,173                temb_channels=time_embed_dim,174                add_downsample=not is_final_block,175                resnet_eps=norm_eps,176                resnet_act_fn=act_fn,177                resnet_groups=norm_num_groups,178                cross_attention_dim=cross_attention_dim,179                attn_num_head_channels=attention_head_dim[i],180                downsample_padding=downsample_padding,181                dual_cross_attention=False,182            )183            self.down_blocks.append(down_block)184 185        # mid186        self.mid_block = UNetMidBlock3DCrossAttn(187            in_channels=block_out_channels[-1],188            temb_channels=time_embed_dim,189            resnet_eps=norm_eps,190            resnet_act_fn=act_fn,191            output_scale_factor=mid_block_scale_factor,192            cross_attention_dim=cross_attention_dim,193            attn_num_head_channels=attention_head_dim[-1],194            resnet_groups=norm_num_groups,195            dual_cross_attention=False,196        )197 198        # count how many layers upsample the images199        self.num_upsamplers = 0200 201        # up202        reversed_block_out_channels = list(reversed(block_out_channels))203        reversed_attention_head_dim = list(reversed(attention_head_dim))204 205        output_channel = reversed_block_out_channels[0]206        for i, up_block_type in enumerate(up_block_types):207            is_final_block = i == len(block_out_channels) - 1208 209            prev_output_channel = output_channel210            output_channel = reversed_block_out_channels[i]211            input_channel = reversed_block_out_channels[min(i + 1, len(block_out_channels) - 1)]212 213            # add upsample block for all BUT final layer214            if not is_final_block:215                add_upsample = True216                self.num_upsamplers += 1217            else:218                add_upsample = False219 220            up_block = get_up_block(221                up_block_type,222                num_layers=layers_per_block + 1,223                in_channels=input_channel,224                out_channels=output_channel,225                prev_output_channel=prev_output_channel,226                temb_channels=time_embed_dim,227                add_upsample=add_upsample,228                resnet_eps=norm_eps,229                resnet_act_fn=act_fn,230                resnet_groups=norm_num_groups,231                cross_attention_dim=cross_attention_dim,232                attn_num_head_channels=reversed_attention_head_dim[i],233                dual_cross_attention=False,234            )235            self.up_blocks.append(up_block)236            prev_output_channel = output_channel237 238        # out239        if norm_num_groups is not None:240            self.conv_norm_out = nn.GroupNorm(241                num_channels=block_out_channels[0], num_groups=norm_num_groups, eps=norm_eps242            )243            self.conv_act = nn.SiLU()244        else:245            self.conv_norm_out = None246            self.conv_act = None247 248        conv_out_padding = (conv_out_kernel - 1) // 2249        self.conv_out = nn.Conv2d(250            block_out_channels[0], out_channels, kernel_size=conv_out_kernel, padding=conv_out_padding251        )252 253    def set_attention_slice(self, slice_size):254        r"""255        Enable sliced attention computation.256 257        When this option is enabled, the attention module will split the input tensor in slices, to compute attention258        in several steps. This is useful to save some memory in exchange for a small speed decrease.259 260        Args:261            slice_size (`str` or `int` or `list(int)`, *optional*, defaults to `"auto"`):262                When `"auto"`, halves the input to the attention heads, so attention will be computed in two steps. If263                `"max"`, maxium amount of memory will be saved by running only one slice at a time. If a number is264                provided, uses as many slices as `attention_head_dim // slice_size`. In this case, `attention_head_dim`265                must be a multiple of `slice_size`.266        """267        sliceable_head_dims = []268 269        def fn_recursive_retrieve_slicable_dims(module: torch.nn.Module):270            if hasattr(module, "set_attention_slice"):271                sliceable_head_dims.append(module.sliceable_head_dim)272 273            for child in module.children():274                fn_recursive_retrieve_slicable_dims(child)275 276        # retrieve number of attention layers277        for module in self.children():278            fn_recursive_retrieve_slicable_dims(module)279 280        num_slicable_layers = len(sliceable_head_dims)281 282        if slice_size == "auto":283            # half the attention head size is usually a good trade-off between284            # speed and memory285            slice_size = [dim // 2 for dim in sliceable_head_dims]286        elif slice_size == "max":287            # make smallest slice possible288            slice_size = num_slicable_layers * [1]289 290        slice_size = num_slicable_layers * [slice_size] if not isinstance(slice_size, list) else slice_size291 292        if len(slice_size) != len(sliceable_head_dims):293            raise ValueError(294                f"You have provided {len(slice_size)}, but {self.config} has {len(sliceable_head_dims)} different"295                f" attention layers. Make sure to match `len(slice_size)` to be {len(sliceable_head_dims)}."296            )297 298        for i in range(len(slice_size)):299            size = slice_size[i]300            dim = sliceable_head_dims[i]301            if size is not None and size > dim:302                raise ValueError(f"size {size} has to be smaller or equal to {dim}.")303 304        # Recursively walk through all the children.305        # Any children which exposes the set_attention_slice method306        # gets the message307        def fn_recursive_set_attention_slice(module: torch.nn.Module, slice_size: List[int]):308            if hasattr(module, "set_attention_slice"):309                module.set_attention_slice(slice_size.pop())310 311            for child in module.children():312                fn_recursive_set_attention_slice(child, slice_size)313 314        reversed_slice_size = list(reversed(slice_size))315        for module in self.children():316            fn_recursive_set_attention_slice(module, reversed_slice_size)317 318    def _set_gradient_checkpointing(self, value=False):319        self.gradient_checkpointing = value320        self.mid_block.gradient_checkpointing = value321        for module in self.down_blocks + self.up_blocks:322            if isinstance(module, (CrossAttnDownBlock3D, DownBlock3D, CrossAttnUpBlock3D, UpBlock3D)):323                module.gradient_checkpointing = value324 325    def forward(326        self,327        sample: torch.FloatTensor,328        timestep: Union[torch.Tensor, float, int],329        encoder_hidden_states: torch.Tensor,330        class_labels: Optional[torch.Tensor] = None,331        timestep_cond: Optional[torch.Tensor] = None,332        attention_mask: Optional[torch.Tensor] = None,333        cross_attention_kwargs: Optional[Dict[str, Any]] = None,334        down_block_additional_residuals: Optional[Tuple[torch.Tensor]] = None,335        mid_block_additional_residual: Optional[torch.Tensor] = None,336        return_dict: bool = True,337    ) -> Union[UNet3DConditionOutput, Tuple]:338        r"""339        Args:340            sample (`torch.FloatTensor`): (batch, num_frames, channel, height, width) noisy inputs tensor341            timestep (`torch.FloatTensor` or `float` or `int`): (batch) timesteps342            encoder_hidden_states (`torch.FloatTensor`): (batch, sequence_length, feature_dim) encoder hidden states343            return_dict (`bool`, *optional*, defaults to `True`):344                Whether or not to return a [`models.unet_2d_condition.UNet3DConditionOutput`] instead of a plain tuple.345            cross_attention_kwargs (`dict`, *optional*):346                A kwargs dictionary that if specified is passed along to the `AttentionProcessor` as defined under347                `self.processor` in348                [diffusers.cross_attention](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/cross_attention.py).349 350        Returns:351            [`~models.unet_2d_condition.UNet3DConditionOutput`] or `tuple`:352            [`~models.unet_2d_condition.UNet3DConditionOutput`] if `return_dict` is True, otherwise a `tuple`. When353            returning a tuple, the first element is the sample tensor.354        """355        # By default samples have to be AT least a multiple of the overall upsampling factor.356        # The overall upsampling factor is equal to 2 ** (# num of upsampling layears).357        # However, the upsampling interpolation output size can be forced to fit any upsampling size358        # on the fly if necessary.359        default_overall_up_factor = 2**self.num_upsamplers360 361        # upsample size should be forwarded when sample is not a multiple of `default_overall_up_factor`362        forward_upsample_size = False363        upsample_size = None364 365        if any(s % default_overall_up_factor != 0 for s in sample.shape[-2:]):366            logger.info("Forward upsample size to force interpolation output size.")367            forward_upsample_size = True368 369        # prepare attention_mask370        if attention_mask is not None:371            attention_mask = (1 - attention_mask.to(sample.dtype)) * -10000.0372            attention_mask = attention_mask.unsqueeze(1)373 374        # 1. time375        timesteps = timestep376        if not torch.is_tensor(timesteps):377            # TODO: this requires sync between CPU and GPU. So try to pass timesteps as tensors if you can378            # This would be a good case for the `match` statement (Python 3.10+)379            is_mps = sample.device.type == "mps"380            if isinstance(timestep, float):381                dtype = torch.float32 if is_mps else torch.float64382            else:383                dtype = torch.int32 if is_mps else torch.int64384            timesteps = torch.tensor([timesteps], dtype=dtype, device=sample.device)385        elif len(timesteps.shape) == 0:386            timesteps = timesteps[None].to(sample.device)387 388        # broadcast to batch dimension in a way that's compatible with ONNX/Core ML389        num_frames = sample.shape[2]390        timesteps = timesteps.expand(sample.shape[0])391 392        t_emb = self.time_proj(timesteps)393 394        # timesteps does not contain any weights and will always return f32 tensors395        # but time_embedding might actually be running in fp16. so we need to cast here.396        # there might be better ways to encapsulate this.397        t_emb = t_emb.to(dtype=self.dtype)398 399        emb = self.time_embedding(t_emb, timestep_cond)400        emb = emb.repeat_interleave(repeats=num_frames, dim=0)401        encoder_hidden_states = encoder_hidden_states.repeat_interleave(repeats=num_frames, dim=0)402 403        # 2. pre-process404        sample = sample.permute(0, 2, 1, 3, 4).reshape((sample.shape[0] * num_frames, -1) + sample.shape[3:])405        sample = self.conv_in(sample)406        407        if num_frames > 1:408            if self.gradient_checkpointing:409                sample = transformer_g_c(self.transformer_in, sample, num_frames)410            else:411                sample = self.transformer_in(sample, num_frames=num_frames).sample412 413        # 3. down414        down_block_res_samples = (sample,)415        for downsample_block in self.down_blocks:416            if hasattr(downsample_block, "has_cross_attention") and downsample_block.has_cross_attention:417                sample, res_samples = downsample_block(418                    hidden_states=sample,419                    temb=emb,420                    encoder_hidden_states=encoder_hidden_states,421                    attention_mask=attention_mask,422                    num_frames=num_frames,423                    cross_attention_kwargs=cross_attention_kwargs,424                )425            else:426                sample, res_samples = downsample_block(hidden_states=sample, temb=emb, num_frames=num_frames)427 428            down_block_res_samples += res_samples429 430        if down_block_additional_residuals is not None:431            new_down_block_res_samples = ()432 433            for down_block_res_sample, down_block_additional_residual in zip(434                down_block_res_samples, down_block_additional_residuals435            ):436                down_block_res_sample = down_block_res_sample + down_block_additional_residual437                new_down_block_res_samples += (down_block_res_sample,)438 439            down_block_res_samples = new_down_block_res_samples440 441        # 4. mid442        if self.mid_block is not None:443            sample = self.mid_block(444                sample,445                emb,446                encoder_hidden_states=encoder_hidden_states,447                attention_mask=attention_mask,448                num_frames=num_frames,449                cross_attention_kwargs=cross_attention_kwargs,450            )451 452        if mid_block_additional_residual is not None:453            sample = sample + mid_block_additional_residual454 455        # 5. up456        for i, upsample_block in enumerate(self.up_blocks):457            is_final_block = i == len(self.up_blocks) - 1458 459            res_samples = down_block_res_samples[-len(upsample_block.resnets) :]460            down_block_res_samples = down_block_res_samples[: -len(upsample_block.resnets)]461 462            # if we have not reached the final block and need to forward the463            # upsample size, we do it here464            if not is_final_block and forward_upsample_size:465                upsample_size = down_block_res_samples[-1].shape[2:]466 467            if hasattr(upsample_block, "has_cross_attention") and upsample_block.has_cross_attention:468                sample = upsample_block(469                    hidden_states=sample,470                    temb=emb,471                    res_hidden_states_tuple=res_samples,472                    encoder_hidden_states=encoder_hidden_states,473                    upsample_size=upsample_size,474                    attention_mask=attention_mask,475                    num_frames=num_frames,476                    cross_attention_kwargs=cross_attention_kwargs,477                )478            else:479                sample = upsample_block(480                    hidden_states=sample,481                    temb=emb,482                    res_hidden_states_tuple=res_samples,483                    upsample_size=upsample_size,484                    num_frames=num_frames,485                )486 487        # 6. post-process488        if self.conv_norm_out:489            sample = self.conv_norm_out(sample)490            sample = self.conv_act(sample)491 492        sample = self.conv_out(sample)493 494        # reshape to (batch, channel, framerate, width, height)495        sample = sample[None, :].reshape((-1, num_frames) + sample.shape[1:]).permute(0, 2, 1, 3, 4)496 497        if not return_dict:498            return (sample,)499 500        return UNet3DConditionOutput(sample=sample)501