CoolFace
Apppublic

declare-lab/tango2

sourceHugging Faceupdated 2y agoView on Hugging Face
92likes
unet_2d_condition_flax.py338 linesDownload Raw Back to models
1# Copyright 2023 The HuggingFace Team. All rights reserved.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7#     http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14from typing import Tuple, Union15 16import flax17import flax.linen as nn18import jax19import jax.numpy as jnp20from flax.core.frozen_dict import FrozenDict21 22from ..configuration_utils import ConfigMixin, flax_register_to_config23from ..utils import BaseOutput24from .embeddings_flax import FlaxTimestepEmbedding, FlaxTimesteps25from .modeling_flax_utils import FlaxModelMixin26from .unet_2d_blocks_flax import (27    FlaxCrossAttnDownBlock2D,28    FlaxCrossAttnUpBlock2D,29    FlaxDownBlock2D,30    FlaxUNetMidBlock2DCrossAttn,31    FlaxUpBlock2D,32)33 34 35@flax.struct.dataclass36class FlaxUNet2DConditionOutput(BaseOutput):37    """38    Args:39        sample (`jnp.ndarray` of shape `(batch_size, num_channels, height, width)`):40            Hidden states conditioned on `encoder_hidden_states` input. Output of last layer of model.41    """42 43    sample: jnp.ndarray44 45 46@flax_register_to_config47class FlaxUNet2DConditionModel(nn.Module, FlaxModelMixin, ConfigMixin):48    r"""49    FlaxUNet2DConditionModel is a conditional 2D UNet model that takes in a noisy sample, conditional state, and a50    timestep and returns sample shaped output.51 52    This model inherits from [`FlaxModelMixin`]. Check the superclass documentation for the generic methods the library53    implements for all the models (such as downloading or saving, etc.)54 55    Also, this model is a Flax Linen [flax.linen.Module](https://flax.readthedocs.io/en/latest/flax.linen.html#module)56    subclass. Use it as a regular Flax linen Module and refer to the Flax documentation for all matter related to57    general usage and behavior.58 59    Finally, this model supports inherent JAX features such as:60    - [Just-In-Time (JIT) compilation](https://jax.readthedocs.io/en/latest/jax.html#just-in-time-compilation-jit)61    - [Automatic Differentiation](https://jax.readthedocs.io/en/latest/jax.html#automatic-differentiation)62    - [Vectorization](https://jax.readthedocs.io/en/latest/jax.html#vectorization-vmap)63    - [Parallelization](https://jax.readthedocs.io/en/latest/jax.html#parallelization-pmap)64 65    Parameters:66        sample_size (`int`, *optional*):67            The size of the input sample.68        in_channels (`int`, *optional*, defaults to 4):69            The number of channels in the input sample.70        out_channels (`int`, *optional*, defaults to 4):71            The number of channels in the output.72        down_block_types (`Tuple[str]`, *optional*, defaults to `("CrossAttnDownBlock2D", "CrossAttnDownBlock2D", "CrossAttnDownBlock2D", "DownBlock2D")`):73            The tuple of downsample blocks to use. The corresponding class names will be: "FlaxCrossAttnDownBlock2D",74            "FlaxCrossAttnDownBlock2D", "FlaxCrossAttnDownBlock2D", "FlaxDownBlock2D"75        up_block_types (`Tuple[str]`, *optional*, defaults to `("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D",)`):76            The tuple of upsample blocks to use. The corresponding class names will be: "FlaxUpBlock2D",77            "FlaxCrossAttnUpBlock2D", "FlaxCrossAttnUpBlock2D", "FlaxCrossAttnUpBlock2D"78        block_out_channels (`Tuple[int]`, *optional*, defaults to `(320, 640, 1280, 1280)`):79            The tuple of output channels for each block.80        layers_per_block (`int`, *optional*, defaults to 2):81            The number of layers per block.82        attention_head_dim (`int` or `Tuple[int]`, *optional*, defaults to 8):83            The dimension of the attention heads.84        cross_attention_dim (`int`, *optional*, defaults to 768):85            The dimension of the cross attention features.86        dropout (`float`, *optional*, defaults to 0):87            Dropout probability for down, up and bottleneck blocks.88        flip_sin_to_cos (`bool`, *optional*, defaults to `True`):89            Whether to flip the sin to cos in the time embedding.90        freq_shift (`int`, *optional*, defaults to 0): The frequency shift to apply to the time embedding.91 92    """93 94    sample_size: int = 3295    in_channels: int = 496    out_channels: int = 497    down_block_types: Tuple[str] = (98        "CrossAttnDownBlock2D",99        "CrossAttnDownBlock2D",100        "CrossAttnDownBlock2D",101        "DownBlock2D",102    )103    up_block_types: Tuple[str] = ("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D")104    only_cross_attention: Union[bool, Tuple[bool]] = False105    block_out_channels: Tuple[int] = (320, 640, 1280, 1280)106    layers_per_block: int = 2107    attention_head_dim: Union[int, Tuple[int]] = 8108    cross_attention_dim: int = 1280109    dropout: float = 0.0110    use_linear_projection: bool = False111    dtype: jnp.dtype = jnp.float32112    flip_sin_to_cos: bool = True113    freq_shift: int = 0114 115    def init_weights(self, rng: jax.random.KeyArray) -> FrozenDict:116        # init input tensors117        sample_shape = (1, self.in_channels, self.sample_size, self.sample_size)118        sample = jnp.zeros(sample_shape, dtype=jnp.float32)119        timesteps = jnp.ones((1,), dtype=jnp.int32)120        encoder_hidden_states = jnp.zeros((1, 1, self.cross_attention_dim), dtype=jnp.float32)121 122        params_rng, dropout_rng = jax.random.split(rng)123        rngs = {"params": params_rng, "dropout": dropout_rng}124 125        return self.init(rngs, sample, timesteps, encoder_hidden_states)["params"]126 127    def setup(self):128        block_out_channels = self.block_out_channels129        time_embed_dim = block_out_channels[0] * 4130 131        # input132        self.conv_in = nn.Conv(133            block_out_channels[0],134            kernel_size=(3, 3),135            strides=(1, 1),136            padding=((1, 1), (1, 1)),137            dtype=self.dtype,138        )139 140        # time141        self.time_proj = FlaxTimesteps(142            block_out_channels[0], flip_sin_to_cos=self.flip_sin_to_cos, freq_shift=self.config.freq_shift143        )144        self.time_embedding = FlaxTimestepEmbedding(time_embed_dim, dtype=self.dtype)145 146        only_cross_attention = self.only_cross_attention147        if isinstance(only_cross_attention, bool):148            only_cross_attention = (only_cross_attention,) * len(self.down_block_types)149 150        attention_head_dim = self.attention_head_dim151        if isinstance(attention_head_dim, int):152            attention_head_dim = (attention_head_dim,) * len(self.down_block_types)153 154        # down155        down_blocks = []156        output_channel = block_out_channels[0]157        for i, down_block_type in enumerate(self.down_block_types):158            input_channel = output_channel159            output_channel = block_out_channels[i]160            is_final_block = i == len(block_out_channels) - 1161 162            if down_block_type == "CrossAttnDownBlock2D":163                down_block = FlaxCrossAttnDownBlock2D(164                    in_channels=input_channel,165                    out_channels=output_channel,166                    dropout=self.dropout,167                    num_layers=self.layers_per_block,168                    attn_num_head_channels=attention_head_dim[i],169                    add_downsample=not is_final_block,170                    use_linear_projection=self.use_linear_projection,171                    only_cross_attention=only_cross_attention[i],172                    dtype=self.dtype,173                )174            else:175                down_block = FlaxDownBlock2D(176                    in_channels=input_channel,177                    out_channels=output_channel,178                    dropout=self.dropout,179                    num_layers=self.layers_per_block,180                    add_downsample=not is_final_block,181                    dtype=self.dtype,182                )183 184            down_blocks.append(down_block)185        self.down_blocks = down_blocks186 187        # mid188        self.mid_block = FlaxUNetMidBlock2DCrossAttn(189            in_channels=block_out_channels[-1],190            dropout=self.dropout,191            attn_num_head_channels=attention_head_dim[-1],192            use_linear_projection=self.use_linear_projection,193            dtype=self.dtype,194        )195 196        # up197        up_blocks = []198        reversed_block_out_channels = list(reversed(block_out_channels))199        reversed_attention_head_dim = list(reversed(attention_head_dim))200        only_cross_attention = list(reversed(only_cross_attention))201        output_channel = reversed_block_out_channels[0]202        for i, up_block_type in enumerate(self.up_block_types):203            prev_output_channel = output_channel204            output_channel = reversed_block_out_channels[i]205            input_channel = reversed_block_out_channels[min(i + 1, len(block_out_channels) - 1)]206 207            is_final_block = i == len(block_out_channels) - 1208 209            if up_block_type == "CrossAttnUpBlock2D":210                up_block = FlaxCrossAttnUpBlock2D(211                    in_channels=input_channel,212                    out_channels=output_channel,213                    prev_output_channel=prev_output_channel,214                    num_layers=self.layers_per_block + 1,215                    attn_num_head_channels=reversed_attention_head_dim[i],216                    add_upsample=not is_final_block,217                    dropout=self.dropout,218                    use_linear_projection=self.use_linear_projection,219                    only_cross_attention=only_cross_attention[i],220                    dtype=self.dtype,221                )222            else:223                up_block = FlaxUpBlock2D(224                    in_channels=input_channel,225                    out_channels=output_channel,226                    prev_output_channel=prev_output_channel,227                    num_layers=self.layers_per_block + 1,228                    add_upsample=not is_final_block,229                    dropout=self.dropout,230                    dtype=self.dtype,231                )232 233            up_blocks.append(up_block)234            prev_output_channel = output_channel235        self.up_blocks = up_blocks236 237        # out238        self.conv_norm_out = nn.GroupNorm(num_groups=32, epsilon=1e-5)239        self.conv_out = nn.Conv(240            self.out_channels,241            kernel_size=(3, 3),242            strides=(1, 1),243            padding=((1, 1), (1, 1)),244            dtype=self.dtype,245        )246 247    def __call__(248        self,249        sample,250        timesteps,251        encoder_hidden_states,252        down_block_additional_residuals=None,253        mid_block_additional_residual=None,254        return_dict: bool = True,255        train: bool = False,256    ) -> Union[FlaxUNet2DConditionOutput, Tuple]:257        r"""258        Args:259            sample (`jnp.ndarray`): (batch, channel, height, width) noisy inputs tensor260            timestep (`jnp.ndarray` or `float` or `int`): timesteps261            encoder_hidden_states (`jnp.ndarray`): (batch_size, sequence_length, hidden_size) encoder hidden states262            return_dict (`bool`, *optional*, defaults to `True`):263                Whether or not to return a [`models.unet_2d_condition_flax.FlaxUNet2DConditionOutput`] instead of a264                plain tuple.265            train (`bool`, *optional*, defaults to `False`):266                Use deterministic functions and disable dropout when not training.267 268        Returns:269            [`~models.unet_2d_condition_flax.FlaxUNet2DConditionOutput`] or `tuple`:270            [`~models.unet_2d_condition_flax.FlaxUNet2DConditionOutput`] if `return_dict` is True, otherwise a `tuple`.271            When returning a tuple, the first element is the sample tensor.272        """273        # 1. time274        if not isinstance(timesteps, jnp.ndarray):275            timesteps = jnp.array([timesteps], dtype=jnp.int32)276        elif isinstance(timesteps, jnp.ndarray) and len(timesteps.shape) == 0:277            timesteps = timesteps.astype(dtype=jnp.float32)278            timesteps = jnp.expand_dims(timesteps, 0)279 280        t_emb = self.time_proj(timesteps)281        t_emb = self.time_embedding(t_emb)282 283        # 2. pre-process284        sample = jnp.transpose(sample, (0, 2, 3, 1))285        sample = self.conv_in(sample)286 287        # 3. down288        down_block_res_samples = (sample,)289        for down_block in self.down_blocks:290            if isinstance(down_block, FlaxCrossAttnDownBlock2D):291                sample, res_samples = down_block(sample, t_emb, encoder_hidden_states, deterministic=not train)292            else:293                sample, res_samples = down_block(sample, t_emb, deterministic=not train)294            down_block_res_samples += res_samples295 296        if down_block_additional_residuals is not None:297            new_down_block_res_samples = ()298 299            for down_block_res_sample, down_block_additional_residual in zip(300                down_block_res_samples, down_block_additional_residuals301            ):302                down_block_res_sample += down_block_additional_residual303                new_down_block_res_samples += (down_block_res_sample,)304 305            down_block_res_samples = new_down_block_res_samples306 307        # 4. mid308        sample = self.mid_block(sample, t_emb, encoder_hidden_states, deterministic=not train)309 310        if mid_block_additional_residual is not None:311            sample += mid_block_additional_residual312 313        # 5. up314        for up_block in self.up_blocks:315            res_samples = down_block_res_samples[-(self.layers_per_block + 1) :]316            down_block_res_samples = down_block_res_samples[: -(self.layers_per_block + 1)]317            if isinstance(up_block, FlaxCrossAttnUpBlock2D):318                sample = up_block(319                    sample,320                    temb=t_emb,321                    encoder_hidden_states=encoder_hidden_states,322                    res_hidden_states_tuple=res_samples,323                    deterministic=not train,324                )325            else:326                sample = up_block(sample, temb=t_emb, res_hidden_states_tuple=res_samples, deterministic=not train)327 328        # 6. post-process329        sample = self.conv_norm_out(sample)330        sample = nn.silu(sample)331        sample = self.conv_out(sample)332        sample = jnp.transpose(sample, (0, 3, 1, 2))333 334        if not return_dict:335            return (sample,)336 337        return FlaxUNet2DConditionOutput(sample=sample)338