CoolFace
Apppublic

Anonymous-123/ImageNet-Editing

sourceHugging Facecreativeml-openrail-mupdated 4y agoView on Hugging Face
1likes
unet.py895 linesDownload Raw Back to guided_diffusion
1from abc import abstractmethod2 3import math4 5import numpy as np6import torch as th7import torch.nn as nn8import torch.nn.functional as F9 10from .fp16_util import convert_module_to_f16, convert_module_to_f3211from .nn import (12    checkpoint,13    conv_nd,14    linear,15    avg_pool_nd,16    zero_module,17    normalization,18    timestep_embedding,19)20 21 22class AttentionPool2d(nn.Module):23    """24    Adapted from CLIP: https://github.com/openai/CLIP/blob/main/clip/model.py25    """26 27    def __init__(28        self,29        spacial_dim: int,30        embed_dim: int,31        num_heads_channels: int,32        output_dim: int = None,33    ):34        super().__init__()35        self.positional_embedding = nn.Parameter(36            th.randn(embed_dim, spacial_dim ** 2 + 1) / embed_dim ** 0.537        )38        self.qkv_proj = conv_nd(1, embed_dim, 3 * embed_dim, 1)39        self.c_proj = conv_nd(1, embed_dim, output_dim or embed_dim, 1)40        self.num_heads = embed_dim // num_heads_channels41        self.attention = QKVAttention(self.num_heads)42 43    def forward(self, x):44        b, c, *_spatial = x.shape45        x = x.reshape(b, c, -1)  # NC(HW)46        x = th.cat([x.mean(dim=-1, keepdim=True), x], dim=-1)  # NC(HW+1)47        x = x + self.positional_embedding[None, :, :].to(x.dtype)  # NC(HW+1)48        x = self.qkv_proj(x)49        x = self.attention(x)50        x = self.c_proj(x)51        return x[:, :, 0]52 53 54class TimestepBlock(nn.Module):55    """56    Any module where forward() takes timestep embeddings as a second argument.57    """58 59    @abstractmethod60    def forward(self, x, emb):61        """62        Apply the module to `x` given `emb` timestep embeddings.63        """64 65 66class TimestepEmbedSequential(nn.Sequential, TimestepBlock):67    """68    A sequential module that passes timestep embeddings to the children that69    support it as an extra input.70    """71 72    def forward(self, x, emb):73        for layer in self:74            if isinstance(layer, TimestepBlock):75                x = layer(x, emb)76            else:77                x = layer(x)78        return x79 80 81class Upsample(nn.Module):82    """83    An upsampling layer with an optional convolution.84 85    :param channels: channels in the inputs and outputs.86    :param use_conv: a bool determining if a convolution is applied.87    :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then88                 upsampling occurs in the inner-two dimensions.89    """90 91    def __init__(self, channels, use_conv, dims=2, out_channels=None):92        super().__init__()93        self.channels = channels94        self.out_channels = out_channels or channels95        self.use_conv = use_conv96        self.dims = dims97        if use_conv:98            self.conv = conv_nd(dims, self.channels, self.out_channels, 3, padding=1)99 100    def forward(self, x):101        assert x.shape[1] == self.channels102        if self.dims == 3:103            x = F.interpolate(104                x, (x.shape[2], x.shape[3] * 2, x.shape[4] * 2), mode="nearest"105            )106        else:107            x = F.interpolate(x, scale_factor=2, mode="nearest")108        if self.use_conv:109            x = self.conv(x)110        return x111 112 113class Downsample(nn.Module):114    """115    A downsampling layer with an optional convolution.116 117    :param channels: channels in the inputs and outputs.118    :param use_conv: a bool determining if a convolution is applied.119    :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then120                 downsampling occurs in the inner-two dimensions.121    """122 123    def __init__(self, channels, use_conv, dims=2, out_channels=None):124        super().__init__()125        self.channels = channels126        self.out_channels = out_channels or channels127        self.use_conv = use_conv128        self.dims = dims129        stride = 2 if dims != 3 else (1, 2, 2)130        if use_conv:131            self.op = conv_nd(132                dims, self.channels, self.out_channels, 3, stride=stride, padding=1133            )134        else:135            assert self.channels == self.out_channels136            self.op = avg_pool_nd(dims, kernel_size=stride, stride=stride)137 138    def forward(self, x):139        assert x.shape[1] == self.channels140        return self.op(x)141 142 143class ResBlock(TimestepBlock):144    """145    A residual block that can optionally change the number of channels.146 147    :param channels: the number of input channels.148    :param emb_channels: the number of timestep embedding channels.149    :param dropout: the rate of dropout.150    :param out_channels: if specified, the number of out channels.151    :param use_conv: if True and out_channels is specified, use a spatial152        convolution instead of a smaller 1x1 convolution to change the153        channels in the skip connection.154    :param dims: determines if the signal is 1D, 2D, or 3D.155    :param use_checkpoint: if True, use gradient checkpointing on this module.156    :param up: if True, use this block for upsampling.157    :param down: if True, use this block for downsampling.158    """159 160    def __init__(161        self,162        channels,163        emb_channels,164        dropout,165        out_channels=None,166        use_conv=False,167        use_scale_shift_norm=False,168        dims=2,169        use_checkpoint=False,170        up=False,171        down=False,172    ):173        super().__init__()174        self.channels = channels175        self.emb_channels = emb_channels176        self.dropout = dropout177        self.out_channels = out_channels or channels178        self.use_conv = use_conv179        self.use_checkpoint = use_checkpoint180        self.use_scale_shift_norm = use_scale_shift_norm181 182        self.in_layers = nn.Sequential(183            normalization(channels),184            nn.SiLU(),185            conv_nd(dims, channels, self.out_channels, 3, padding=1),186        )187 188        self.updown = up or down189 190        if up:191            self.h_upd = Upsample(channels, False, dims)192            self.x_upd = Upsample(channels, False, dims)193        elif down:194            self.h_upd = Downsample(channels, False, dims)195            self.x_upd = Downsample(channels, False, dims)196        else:197            self.h_upd = self.x_upd = nn.Identity()198 199        self.emb_layers = nn.Sequential(200            nn.SiLU(),201            linear(202                emb_channels,203                2 * self.out_channels if use_scale_shift_norm else self.out_channels,204            ),205        )206        self.out_layers = nn.Sequential(207            normalization(self.out_channels),208            nn.SiLU(),209            nn.Dropout(p=dropout),210            zero_module(211                conv_nd(dims, self.out_channels, self.out_channels, 3, padding=1)212            ),213        )214 215        if self.out_channels == channels:216            self.skip_connection = nn.Identity()217        elif use_conv:218            self.skip_connection = conv_nd(219                dims, channels, self.out_channels, 3, padding=1220            )221        else:222            self.skip_connection = conv_nd(dims, channels, self.out_channels, 1)223 224    def forward(self, x, emb):225        """226        Apply the block to a Tensor, conditioned on a timestep embedding.227 228        :param x: an [N x C x ...] Tensor of features.229        :param emb: an [N x emb_channels] Tensor of timestep embeddings.230        :return: an [N x C x ...] Tensor of outputs.231        """232        return checkpoint(233            self._forward, (x, emb), self.parameters(), self.use_checkpoint234        )235 236    def _forward(self, x, emb):237        if self.updown:238            in_rest, in_conv = self.in_layers[:-1], self.in_layers[-1]239            h = in_rest(x)240            h = self.h_upd(h)241            x = self.x_upd(x)242            h = in_conv(h)243        else:244            h = self.in_layers(x)245        emb_out = self.emb_layers(emb).type(h.dtype)246        while len(emb_out.shape) < len(h.shape):247            emb_out = emb_out[..., None]248        if self.use_scale_shift_norm:249            out_norm, out_rest = self.out_layers[0], self.out_layers[1:]250            scale, shift = th.chunk(emb_out, 2, dim=1)251            h = out_norm(h) * (1 + scale) + shift252            h = out_rest(h)253        else:254            h = h + emb_out255            h = self.out_layers(h)256        return self.skip_connection(x) + h257 258 259class AttentionBlock(nn.Module):260    """261    An attention block that allows spatial positions to attend to each other.262 263    Originally ported from here, but adapted to the N-d case.264    https://github.com/hojonathanho/diffusion/blob/1e0dceb3b3495bbe19116a5e1b3596cd0706c543/diffusion_tf/models/unet.py#L66.265    """266 267    def __init__(268        self,269        channels,270        num_heads=1,271        num_head_channels=-1,272        use_checkpoint=False,273        use_new_attention_order=False,274    ):275        super().__init__()276        self.channels = channels277        if num_head_channels == -1:278            self.num_heads = num_heads279        else:280            assert (281                channels % num_head_channels == 0282            ), f"q,k,v channels {channels} is not divisible by num_head_channels {num_head_channels}"283            self.num_heads = channels // num_head_channels284        self.use_checkpoint = use_checkpoint285        self.norm = normalization(channels)286        self.qkv = conv_nd(1, channels, channels * 3, 1)287        if use_new_attention_order:288            # split qkv before split heads289            self.attention = QKVAttention(self.num_heads)290        else:291            # split heads before split qkv292            self.attention = QKVAttentionLegacy(self.num_heads)293 294        self.proj_out = zero_module(conv_nd(1, channels, channels, 1))295 296    def forward(self, x):297        return checkpoint(self._forward, (x,), self.parameters(), True)298 299    def _forward(self, x):300        b, c, *spatial = x.shape301        x = x.reshape(b, c, -1)302        qkv = self.qkv(self.norm(x))303        h = self.attention(qkv)304        h = self.proj_out(h)305        return (x + h).reshape(b, c, *spatial)306 307 308def count_flops_attn(model, _x, y):309    """310    A counter for the `thop` package to count the operations in an311    attention operation.312    Meant to be used like:313        macs, params = thop.profile(314            model,315            inputs=(inputs, timestamps),316            custom_ops={QKVAttention: QKVAttention.count_flops},317        )318    """319    b, c, *spatial = y[0].shape320    num_spatial = int(np.prod(spatial))321    # We perform two matmuls with the same number of ops.322    # The first computes the weight matrix, the second computes323    # the combination of the value vectors.324    matmul_ops = 2 * b * (num_spatial ** 2) * c325    model.total_ops += th.DoubleTensor([matmul_ops])326 327 328class QKVAttentionLegacy(nn.Module):329    """330    A module which performs QKV attention. Matches legacy QKVAttention + input/ouput heads shaping331    """332 333    def __init__(self, n_heads):334        super().__init__()335        self.n_heads = n_heads336 337    def forward(self, qkv):338        """339        Apply QKV attention.340 341        :param qkv: an [N x (H * 3 * C) x T] tensor of Qs, Ks, and Vs.342        :return: an [N x (H * C) x T] tensor after attention.343        """344        bs, width, length = qkv.shape345        assert width % (3 * self.n_heads) == 0346        ch = width // (3 * self.n_heads)347        q, k, v = qkv.reshape(bs * self.n_heads, ch * 3, length).split(ch, dim=1)348        scale = 1 / math.sqrt(math.sqrt(ch))349        weight = th.einsum(350            "bct,bcs->bts", q * scale, k * scale351        )  # More stable with f16 than dividing afterwards352        weight = th.softmax(weight.float(), dim=-1).type(weight.dtype)353        a = th.einsum("bts,bcs->bct", weight, v)354        return a.reshape(bs, -1, length)355 356    @staticmethod357    def count_flops(model, _x, y):358        return count_flops_attn(model, _x, y)359 360 361class QKVAttention(nn.Module):362    """363    A module which performs QKV attention and splits in a different order.364    """365 366    def __init__(self, n_heads):367        super().__init__()368        self.n_heads = n_heads369 370    def forward(self, qkv):371        """372        Apply QKV attention.373 374        :param qkv: an [N x (3 * H * C) x T] tensor of Qs, Ks, and Vs.375        :return: an [N x (H * C) x T] tensor after attention.376        """377        bs, width, length = qkv.shape378        assert width % (3 * self.n_heads) == 0379        ch = width // (3 * self.n_heads)380        q, k, v = qkv.chunk(3, dim=1)381        scale = 1 / math.sqrt(math.sqrt(ch))382        weight = th.einsum(383            "bct,bcs->bts",384            (q * scale).view(bs * self.n_heads, ch, length),385            (k * scale).view(bs * self.n_heads, ch, length),386        )  # More stable with f16 than dividing afterwards387        weight = th.softmax(weight.float(), dim=-1).type(weight.dtype)388        a = th.einsum("bts,bcs->bct", weight, v.reshape(bs * self.n_heads, ch, length))389        return a.reshape(bs, -1, length)390 391    @staticmethod392    def count_flops(model, _x, y):393        return count_flops_attn(model, _x, y)394 395 396class UNetModel(nn.Module):397    """398    The full UNet model with attention and timestep embedding.399 400    :param in_channels: channels in the input Tensor.401    :param model_channels: base channel count for the model.402    :param out_channels: channels in the output Tensor.403    :param num_res_blocks: number of residual blocks per downsample.404    :param attention_resolutions: a collection of downsample rates at which405        attention will take place. May be a set, list, or tuple.406        For example, if this contains 4, then at 4x downsampling, attention407        will be used.408    :param dropout: the dropout probability.409    :param channel_mult: channel multiplier for each level of the UNet.410    :param conv_resample: if True, use learned convolutions for upsampling and411        downsampling.412    :param dims: determines if the signal is 1D, 2D, or 3D.413    :param num_classes: if specified (as an int), then this model will be414        class-conditional with `num_classes` classes.415    :param use_checkpoint: use gradient checkpointing to reduce memory usage.416    :param num_heads: the number of attention heads in each attention layer.417    :param num_heads_channels: if specified, ignore num_heads and instead use418                               a fixed channel width per attention head.419    :param num_heads_upsample: works with num_heads to set a different number420                               of heads for upsampling. Deprecated.421    :param use_scale_shift_norm: use a FiLM-like conditioning mechanism.422    :param resblock_updown: use residual blocks for up/downsampling.423    :param use_new_attention_order: use a different attention pattern for potentially424                                    increased efficiency.425    """426 427    def __init__(428        self,429        image_size,430        in_channels,431        model_channels,432        out_channels,433        num_res_blocks,434        attention_resolutions,435        dropout=0,436        channel_mult=(1, 2, 4, 8),437        conv_resample=True,438        dims=2,439        num_classes=None,440        use_checkpoint=False,441        use_fp16=False,442        num_heads=1,443        num_head_channels=-1,444        num_heads_upsample=-1,445        use_scale_shift_norm=False,446        resblock_updown=False,447        use_new_attention_order=False,448    ):449        super().__init__()450 451        if num_heads_upsample == -1:452            num_heads_upsample = num_heads453 454        self.image_size = image_size455        self.in_channels = in_channels456        self.model_channels = model_channels457        self.out_channels = out_channels458        self.num_res_blocks = num_res_blocks459        self.attention_resolutions = attention_resolutions460        self.dropout = dropout461        self.channel_mult = channel_mult462        self.conv_resample = conv_resample463        self.num_classes = num_classes464        self.use_checkpoint = use_checkpoint465        self.dtype = th.float16 if use_fp16 else th.float32466        self.num_heads = num_heads467        self.num_head_channels = num_head_channels468        self.num_heads_upsample = num_heads_upsample469 470        time_embed_dim = model_channels * 4471        self.time_embed = nn.Sequential(472            linear(model_channels, time_embed_dim),473            nn.SiLU(),474            linear(time_embed_dim, time_embed_dim),475        )476 477        if self.num_classes is not None:478            self.label_emb = nn.Embedding(num_classes, time_embed_dim)479 480        ch = input_ch = int(channel_mult[0] * model_channels)481        self.input_blocks = nn.ModuleList(482            [TimestepEmbedSequential(conv_nd(dims, in_channels, ch, 3, padding=1))]483        )484        self._feature_size = ch485        input_block_chans = [ch]486        ds = 1487        for level, mult in enumerate(channel_mult):488            for _ in range(num_res_blocks):489                layers = [490                    ResBlock(491                        ch,492                        time_embed_dim,493                        dropout,494                        out_channels=int(mult * model_channels),495                        dims=dims,496                        use_checkpoint=use_checkpoint,497                        use_scale_shift_norm=use_scale_shift_norm,498                    )499                ]500                ch = int(mult * model_channels)501                if ds in attention_resolutions:502                    layers.append(503                        AttentionBlock(504                            ch,505                            use_checkpoint=use_checkpoint,506                            num_heads=num_heads,507                            num_head_channels=num_head_channels,508                            use_new_attention_order=use_new_attention_order,509                        )510                    )511                self.input_blocks.append(TimestepEmbedSequential(*layers))512                self._feature_size += ch513                input_block_chans.append(ch)514            if level != len(channel_mult) - 1:515                out_ch = ch516                self.input_blocks.append(517                    TimestepEmbedSequential(518                        ResBlock(519                            ch,520                            time_embed_dim,521                            dropout,522                            out_channels=out_ch,523                            dims=dims,524                            use_checkpoint=use_checkpoint,525                            use_scale_shift_norm=use_scale_shift_norm,526                            down=True,527                        )528                        if resblock_updown529                        else Downsample(530                            ch, conv_resample, dims=dims, out_channels=out_ch531                        )532                    )533                )534                ch = out_ch535                input_block_chans.append(ch)536                ds *= 2537                self._feature_size += ch538 539        self.middle_block = TimestepEmbedSequential(540            ResBlock(541                ch,542                time_embed_dim,543                dropout,544                dims=dims,545                use_checkpoint=use_checkpoint,546                use_scale_shift_norm=use_scale_shift_norm,547            ),548            AttentionBlock(549                ch,550                use_checkpoint=use_checkpoint,551                num_heads=num_heads,552                num_head_channels=num_head_channels,553                use_new_attention_order=use_new_attention_order,554            ),555            ResBlock(556                ch,557                time_embed_dim,558                dropout,559                dims=dims,560                use_checkpoint=use_checkpoint,561                use_scale_shift_norm=use_scale_shift_norm,562            ),563        )564        self._feature_size += ch565 566        self.output_blocks = nn.ModuleList([])567        for level, mult in list(enumerate(channel_mult))[::-1]:568            for i in range(num_res_blocks + 1):569                ich = input_block_chans.pop()570                layers = [571                    ResBlock(572                        ch + ich,573                        time_embed_dim,574                        dropout,575                        out_channels=int(model_channels * mult),576                        dims=dims,577                        use_checkpoint=use_checkpoint,578                        use_scale_shift_norm=use_scale_shift_norm,579                    )580                ]581                ch = int(model_channels * mult)582                if ds in attention_resolutions:583                    layers.append(584                        AttentionBlock(585                            ch,586                            use_checkpoint=use_checkpoint,587                            num_heads=num_heads_upsample,588                            num_head_channels=num_head_channels,589                            use_new_attention_order=use_new_attention_order,590                        )591                    )592                if level and i == num_res_blocks:593                    out_ch = ch594                    layers.append(595                        ResBlock(596                            ch,597                            time_embed_dim,598                            dropout,599                            out_channels=out_ch,600                            dims=dims,601                            use_checkpoint=use_checkpoint,602                            use_scale_shift_norm=use_scale_shift_norm,603                            up=True,604                        )605                        if resblock_updown606                        else Upsample(ch, conv_resample, dims=dims, out_channels=out_ch)607                    )608                    ds //= 2609                self.output_blocks.append(TimestepEmbedSequential(*layers))610                self._feature_size += ch611 612        self.out = nn.Sequential(613            normalization(ch),614            nn.SiLU(),615            zero_module(conv_nd(dims, input_ch, out_channels, 3, padding=1)),616        )617 618    def convert_to_fp16(self):619        """620        Convert the torso of the model to float16.621        """622        self.input_blocks.apply(convert_module_to_f16)623        self.middle_block.apply(convert_module_to_f16)624        self.output_blocks.apply(convert_module_to_f16)625 626    def convert_to_fp32(self):627        """628        Convert the torso of the model to float32.629        """630        self.input_blocks.apply(convert_module_to_f32)631        self.middle_block.apply(convert_module_to_f32)632        self.output_blocks.apply(convert_module_to_f32)633 634    def forward(self, x, timesteps, y=None):635        """636        Apply the model to an input batch.637 638        :param x: an [N x C x ...] Tensor of inputs.639        :param timesteps: a 1-D batch of timesteps.640        :param y: an [N] Tensor of labels, if class-conditional.641        :return: an [N x C x ...] Tensor of outputs.642        """643        assert (y is not None) == (644            self.num_classes is not None645        ), "must specify y if and only if the model is class-conditional"646 647        hs = []648        emb = self.time_embed(timestep_embedding(timesteps, self.model_channels))649 650        if self.num_classes is not None:651            assert y.shape == (x.shape[0],)652            emb = emb + self.label_emb(y)653 654        h = x.type(self.dtype)655        for module in self.input_blocks:656            h = module(h, emb)657            hs.append(h)658        h = self.middle_block(h, emb)659        for module in self.output_blocks:660            h = th.cat([h, hs.pop()], dim=1)661            h = module(h, emb)662        h = h.type(x.dtype)663        return self.out(h)664 665 666class SuperResModel(UNetModel):667    """668    A UNetModel that performs super-resolution.669 670    Expects an extra kwarg `low_res` to condition on a low-resolution image.671    """672 673    def __init__(self, image_size, in_channels, *args, **kwargs):674        super().__init__(image_size, in_channels * 2, *args, **kwargs)675 676    def forward(self, x, timesteps, low_res=None, **kwargs):677        _, _, new_height, new_width = x.shape678        upsampled = F.interpolate(low_res, (new_height, new_width), mode="bilinear")679        x = th.cat([x, upsampled], dim=1)680        return super().forward(x, timesteps, **kwargs)681 682 683class EncoderUNetModel(nn.Module):684    """685    The half UNet model with attention and timestep embedding.686 687    For usage, see UNet.688    """689 690    def __init__(691        self,692        image_size,693        in_channels,694        model_channels,695        out_channels,696        num_res_blocks,697        attention_resolutions,698        dropout=0,699        channel_mult=(1, 2, 4, 8),700        conv_resample=True,701        dims=2,702        use_checkpoint=False,703        use_fp16=False,704        num_heads=1,705        num_head_channels=-1,706        num_heads_upsample=-1,707        use_scale_shift_norm=False,708        resblock_updown=False,709        use_new_attention_order=False,710        pool="adaptive",711    ):712        super().__init__()713 714        if num_heads_upsample == -1:715            num_heads_upsample = num_heads716 717        self.in_channels = in_channels718        self.model_channels = model_channels719        self.out_channels = out_channels720        self.num_res_blocks = num_res_blocks721        self.attention_resolutions = attention_resolutions722        self.dropout = dropout723        self.channel_mult = channel_mult724        self.conv_resample = conv_resample725        self.use_checkpoint = use_checkpoint726        self.dtype = th.float16 if use_fp16 else th.float32727        self.num_heads = num_heads728        self.num_head_channels = num_head_channels729        self.num_heads_upsample = num_heads_upsample730 731        time_embed_dim = model_channels * 4732        self.time_embed = nn.Sequential(733            linear(model_channels, time_embed_dim),734            nn.SiLU(),735            linear(time_embed_dim, time_embed_dim),736        )737 738        ch = int(channel_mult[0] * model_channels)739        self.input_blocks = nn.ModuleList(740            [TimestepEmbedSequential(conv_nd(dims, in_channels, ch, 3, padding=1))]741        )742        self._feature_size = ch743        input_block_chans = [ch]744        ds = 1745        for level, mult in enumerate(channel_mult):746            for _ in range(num_res_blocks):747                layers = [748                    ResBlock(749                        ch,750                        time_embed_dim,751                        dropout,752                        out_channels=int(mult * model_channels),753                        dims=dims,754                        use_checkpoint=use_checkpoint,755                        use_scale_shift_norm=use_scale_shift_norm,756                    )757                ]758                ch = int(mult * model_channels)759                if ds in attention_resolutions:760                    layers.append(761                        AttentionBlock(762                            ch,763                            use_checkpoint=use_checkpoint,764                            num_heads=num_heads,765                            num_head_channels=num_head_channels,766                            use_new_attention_order=use_new_attention_order,767                        )768                    )769                self.input_blocks.append(TimestepEmbedSequential(*layers))770                self._feature_size += ch771                input_block_chans.append(ch)772            if level != len(channel_mult) - 1:773                out_ch = ch774                self.input_blocks.append(775                    TimestepEmbedSequential(776                        ResBlock(777                            ch,778                            time_embed_dim,779                            dropout,780                            out_channels=out_ch,781                            dims=dims,782                            use_checkpoint=use_checkpoint,783                            use_scale_shift_norm=use_scale_shift_norm,784                            down=True,785                        )786                        if resblock_updown787                        else Downsample(788                            ch, conv_resample, dims=dims, out_channels=out_ch789                        )790                    )791                )792                ch = out_ch793                input_block_chans.append(ch)794                ds *= 2795                self._feature_size += ch796 797        self.middle_block = TimestepEmbedSequential(798            ResBlock(799                ch,800                time_embed_dim,801                dropout,802                dims=dims,803                use_checkpoint=use_checkpoint,804                use_scale_shift_norm=use_scale_shift_norm,805            ),806            AttentionBlock(807                ch,808                use_checkpoint=use_checkpoint,809                num_heads=num_heads,810                num_head_channels=num_head_channels,811                use_new_attention_order=use_new_attention_order,812            ),813            ResBlock(814                ch,815                time_embed_dim,816                dropout,817                dims=dims,818                use_checkpoint=use_checkpoint,819                use_scale_shift_norm=use_scale_shift_norm,820            ),821        )822        self._feature_size += ch823        self.pool = pool824        if pool == "adaptive":825            self.out = nn.Sequential(826                normalization(ch),827                nn.SiLU(),828                nn.AdaptiveAvgPool2d((1, 1)),829                zero_module(conv_nd(dims, ch, out_channels, 1)),830                nn.Flatten(),831            )832        elif pool == "attention":833            assert num_head_channels != -1834            self.out = nn.Sequential(835                normalization(ch),836                nn.SiLU(),837                AttentionPool2d(838                    (image_size // ds), ch, num_head_channels, out_channels839                ),840            )841        elif pool == "spatial":842            self.out = nn.Sequential(843                nn.Linear(self._feature_size, 2048),844                nn.ReLU(),845                nn.Linear(2048, self.out_channels),846            )847        elif pool == "spatial_v2":848            self.out = nn.Sequential(849                nn.Linear(self._feature_size, 2048),850                normalization(2048),851                nn.SiLU(),852                nn.Linear(2048, self.out_channels),853            )854        else:855            raise NotImplementedError(f"Unexpected {pool} pooling")856 857    def convert_to_fp16(self):858        """859        Convert the torso of the model to float16.860        """861        self.input_blocks.apply(convert_module_to_f16)862        self.middle_block.apply(convert_module_to_f16)863 864    def convert_to_fp32(self):865        """866        Convert the torso of the model to float32.867        """868        self.input_blocks.apply(convert_module_to_f32)869        self.middle_block.apply(convert_module_to_f32)870 871    def forward(self, x, timesteps):872        """873        Apply the model to an input batch.874 875        :param x: an [N x C x ...] Tensor of inputs.876        :param timesteps: a 1-D batch of timesteps.877        :return: an [N x K] Tensor of outputs.878        """879        emb = self.time_embed(timestep_embedding(timesteps, self.model_channels))880 881        results = []882        h = x.type(self.dtype)883        for module in self.input_blocks:884            h = module(h, emb)885            if self.pool.startswith("spatial"):886                results.append(h.type(x.dtype).mean(dim=(2, 3)))887        h = self.middle_block(h, emb)888        if self.pool.startswith("spatial"):889            results.append(h.type(x.dtype).mean(dim=(2, 3)))890            h = th.cat(results, axis=-1)891            return self.out(h)892        else:893            h = h.type(x.dtype)894            return self.out(h)895