CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
modeling_poolformer.py381 linesDownload Raw Back to poolformer
1# coding=utf-82# Copyright 2022 Sea AI Lab and The HuggingFace Inc. team. All rights reserved.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.15"""PyTorch PoolFormer model."""16 17import collections.abc18from typing import Optional, Union19 20import torch21from torch import nn22 23from ...activations import ACT2FN24from ...modeling_outputs import BaseModelOutputWithNoAttention, ImageClassifierOutputWithNoAttention25from ...modeling_utils import PreTrainedModel26from ...utils import auto_docstring, logging27from .configuration_poolformer import PoolFormerConfig28 29 30logger = logging.get_logger(__name__)31 32 33# Copied from transformers.models.beit.modeling_beit.drop_path34def drop_path(input: torch.Tensor, drop_prob: float = 0.0, training: bool = False) -> torch.Tensor:35    """36    Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).37 38    Comment by Ross Wightman: This is the same as the DropConnect impl I created for EfficientNet, etc networks,39    however, the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper...40    See discussion: https://github.com/tensorflow/tpu/issues/494#issuecomment-532968956 ... I've opted for changing the41    layer and argument names to 'drop path' rather than mix DropConnect as a layer name and use 'survival rate' as the42    argument.43    """44    if drop_prob == 0.0 or not training:45        return input46    keep_prob = 1 - drop_prob47    shape = (input.shape[0],) + (1,) * (input.ndim - 1)  # work with diff dim tensors, not just 2D ConvNets48    random_tensor = keep_prob + torch.rand(shape, dtype=input.dtype, device=input.device)49    random_tensor.floor_()  # binarize50    output = input.div(keep_prob) * random_tensor51    return output52 53 54# Copied from transformers.models.beit.modeling_beit.BeitDropPath with Beit->PoolFormer55class PoolFormerDropPath(nn.Module):56    """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks)."""57 58    def __init__(self, drop_prob: Optional[float] = None) -> None:59        super().__init__()60        self.drop_prob = drop_prob61 62    def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:63        return drop_path(hidden_states, self.drop_prob, self.training)64 65    def extra_repr(self) -> str:66        return f"p={self.drop_prob}"67 68 69class PoolFormerEmbeddings(nn.Module):70    """71    Construct Patch Embeddings.72    """73 74    def __init__(self, hidden_size, num_channels, patch_size, stride, padding, norm_layer=None):75        super().__init__()76        patch_size = patch_size if isinstance(patch_size, collections.abc.Iterable) else (patch_size, patch_size)77        stride = stride if isinstance(stride, collections.abc.Iterable) else (stride, stride)78        padding = padding if isinstance(padding, collections.abc.Iterable) else (padding, padding)79 80        self.projection = nn.Conv2d(num_channels, hidden_size, kernel_size=patch_size, stride=stride, padding=padding)81        self.norm = norm_layer(hidden_size) if norm_layer else nn.Identity()82 83    def forward(self, pixel_values):84        embeddings = self.projection(pixel_values)85        embeddings = self.norm(embeddings)86        return embeddings87 88 89class PoolFormerGroupNorm(nn.GroupNorm):90    """91    Group Normalization with 1 group. Input: tensor in shape [B, C, H, W]92    """93 94    def __init__(self, num_channels, **kwargs):95        super().__init__(1, num_channels, **kwargs)96 97 98class PoolFormerPooling(nn.Module):99    def __init__(self, pool_size):100        super().__init__()101        self.pool = nn.AvgPool2d(pool_size, stride=1, padding=pool_size // 2, count_include_pad=False)102 103    def forward(self, hidden_states):104        return self.pool(hidden_states) - hidden_states105 106 107class PoolFormerOutput(nn.Module):108    def __init__(self, config, dropout_prob, hidden_size, intermediate_size):109        super().__init__()110        self.conv1 = nn.Conv2d(hidden_size, intermediate_size, 1)111        self.conv2 = nn.Conv2d(intermediate_size, hidden_size, 1)112        self.drop = PoolFormerDropPath(dropout_prob)113        if isinstance(config.hidden_act, str):114            self.act_fn = ACT2FN[config.hidden_act]115        else:116            self.act_fn = config.hidden_act117 118    def forward(self, hidden_states):119        hidden_states = self.conv1(hidden_states)120        hidden_states = self.act_fn(hidden_states)121        hidden_states = self.drop(hidden_states)122        hidden_states = self.conv2(hidden_states)123        hidden_states = self.drop(hidden_states)124 125        return hidden_states126 127 128class PoolFormerLayer(nn.Module):129    """This corresponds to the 'PoolFormerBlock' class in the original implementation."""130 131    def __init__(self, config, num_channels, pool_size, hidden_size, intermediate_size, drop_path):132        super().__init__()133        self.pooling = PoolFormerPooling(pool_size)134        self.output = PoolFormerOutput(config, drop_path, hidden_size, intermediate_size)135        self.before_norm = PoolFormerGroupNorm(num_channels)136        self.after_norm = PoolFormerGroupNorm(num_channels)137 138        # Useful for training neural nets139        self.drop_path = PoolFormerDropPath(drop_path) if drop_path > 0.0 else nn.Identity()140        self.use_layer_scale = config.use_layer_scale141        if config.use_layer_scale:142            self.layer_scale_1 = nn.Parameter(143                config.layer_scale_init_value * torch.ones(num_channels), requires_grad=True144            )145            self.layer_scale_2 = nn.Parameter(146                config.layer_scale_init_value * torch.ones(num_channels), requires_grad=True147            )148 149    def forward(self, hidden_states):150        if self.use_layer_scale:151            pooling_output = self.pooling(self.before_norm(hidden_states))152            scaled_op = self.layer_scale_1.unsqueeze(-1).unsqueeze(-1) * pooling_output153            # First residual connection154            hidden_states = hidden_states + self.drop_path(scaled_op)155            outputs = ()156 157            layer_output = self.output(self.after_norm(hidden_states))158            scaled_op = self.layer_scale_2.unsqueeze(-1).unsqueeze(-1) * layer_output159            # Second residual connection160            output = hidden_states + self.drop_path(scaled_op)161 162            outputs = (output,) + outputs163            return outputs164 165        else:166            pooling_output = self.drop_path(self.pooling(self.before_norm(hidden_states)))167            # First residual connection168            hidden_states = pooling_output + hidden_states169            outputs = ()170 171            # Second residual connection inside the PoolFormerOutput block172            layer_output = self.drop_path(self.output(self.after_norm(hidden_states)))173            output = hidden_states + layer_output174 175            outputs = (output,) + outputs176            return outputs177 178 179class PoolFormerEncoder(nn.Module):180    def __init__(self, config):181        super().__init__()182        self.config = config183        # stochastic depth decay rule184        dpr = [x.item() for x in torch.linspace(0, config.drop_path_rate, sum(config.depths), device="cpu")]185 186        # patch embeddings187        embeddings = []188        for i in range(config.num_encoder_blocks):189            embeddings.append(190                PoolFormerEmbeddings(191                    patch_size=config.patch_sizes[i],192                    stride=config.strides[i],193                    padding=config.padding[i],194                    num_channels=config.num_channels if i == 0 else config.hidden_sizes[i - 1],195                    hidden_size=config.hidden_sizes[i],196                )197            )198        self.patch_embeddings = nn.ModuleList(embeddings)199 200        # Transformer blocks201        blocks = []202        cur = 0203        for i in range(config.num_encoder_blocks):204            # each block consists of layers205            layers = []206            if i != 0:207                cur += config.depths[i - 1]208            for j in range(config.depths[i]):209                layers.append(210                    PoolFormerLayer(211                        config,212                        num_channels=config.hidden_sizes[i],213                        pool_size=config.pool_size,214                        hidden_size=config.hidden_sizes[i],215                        intermediate_size=int(config.hidden_sizes[i] * config.mlp_ratio),216                        drop_path=dpr[cur + j],217                    )218                )219            blocks.append(nn.ModuleList(layers))220 221        self.block = nn.ModuleList(blocks)222 223    def forward(self, pixel_values, output_hidden_states=False, return_dict=True):224        all_hidden_states = () if output_hidden_states else None225 226        hidden_states = pixel_values227        for idx, layers in enumerate(zip(self.patch_embeddings, self.block)):228            embedding_layer, block_layer = layers229            # Get patch embeddings from hidden_states230            hidden_states = embedding_layer(hidden_states)231            # Send the embeddings through the blocks232            for _, blk in enumerate(block_layer):233                layer_outputs = blk(hidden_states)234                hidden_states = layer_outputs[0]235 236            if output_hidden_states:237                all_hidden_states = all_hidden_states + (hidden_states,)238 239        if not return_dict:240            return tuple(v for v in [hidden_states, all_hidden_states] if v is not None)241 242        return BaseModelOutputWithNoAttention(last_hidden_state=hidden_states, hidden_states=all_hidden_states)243 244 245@auto_docstring246class PoolFormerPreTrainedModel(PreTrainedModel):247    config: PoolFormerConfig248    base_model_prefix = "poolformer"249    main_input_name = "pixel_values"250    _no_split_modules = ["PoolFormerLayer"]251 252    def _init_weights(self, module):253        """Initialize the weights"""254        if isinstance(module, (nn.Linear, nn.Conv2d)):255            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)256            if module.bias is not None:257                module.bias.data.zero_()258        elif isinstance(module, nn.GroupNorm):259            module.bias.data.zero_()260            module.weight.data.fill_(1.0)261        elif isinstance(module, PoolFormerLayer):262            if hasattr(module, "layer_scale_1"):263                module.layer_scale_1.data.fill_(self.config.layer_scale_init_value)264                module.layer_scale_2.data.fill_(self.config.layer_scale_init_value)265 266 267@auto_docstring268class PoolFormerModel(PoolFormerPreTrainedModel):269    def __init__(self, config):270        super().__init__(config)271        self.config = config272 273        self.encoder = PoolFormerEncoder(config)274 275        # Initialize weights and apply final processing276        self.post_init()277 278    def get_input_embeddings(self):279        return self.embeddings.patch_embeddings280 281    @auto_docstring282    def forward(283        self,284        pixel_values: Optional[torch.FloatTensor] = None,285        output_hidden_states: Optional[bool] = None,286        return_dict: Optional[bool] = None,287    ) -> Union[tuple, BaseModelOutputWithNoAttention]:288        output_hidden_states = (289            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states290        )291        return_dict = return_dict if return_dict is not None else self.config.use_return_dict292 293        if pixel_values is None:294            raise ValueError("You have to specify pixel_values")295 296        encoder_outputs = self.encoder(297            pixel_values,298            output_hidden_states=output_hidden_states,299            return_dict=return_dict,300        )301        sequence_output = encoder_outputs[0]302 303        if not return_dict:304            return (sequence_output, None) + encoder_outputs[1:]305 306        return BaseModelOutputWithNoAttention(307            last_hidden_state=sequence_output,308            hidden_states=encoder_outputs.hidden_states,309        )310 311 312class PoolFormerFinalPooler(nn.Module):313    def __init__(self, config):314        super().__init__()315        self.dense = nn.Linear(config.hidden_size, config.hidden_size)316 317    def forward(self, hidden_states):318        output = self.dense(hidden_states)319        return output320 321 322@auto_docstring(323    custom_intro="""324    PoolFormer Model transformer with an image classification head on top325    """326)327class PoolFormerForImageClassification(PoolFormerPreTrainedModel):328    def __init__(self, config):329        super().__init__(config)330        self.num_labels = config.num_labels331        self.poolformer = PoolFormerModel(config)332 333        # Final norm334        self.norm = PoolFormerGroupNorm(config.hidden_sizes[-1])335        # Classifier head336        self.classifier = (337            nn.Linear(config.hidden_sizes[-1], config.num_labels) if config.num_labels > 0 else nn.Identity()338        )339 340        # Initialize weights and apply final processing341        self.post_init()342 343    @auto_docstring344    def forward(345        self,346        pixel_values: Optional[torch.FloatTensor] = None,347        labels: Optional[torch.LongTensor] = None,348        output_hidden_states: Optional[bool] = None,349        return_dict: Optional[bool] = None,350    ) -> Union[tuple, ImageClassifierOutputWithNoAttention]:351        r"""352        labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):353            Labels for computing the image classification/regression loss. Indices should be in `[0, ...,354            config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If355            `config.num_labels > 1` a classification loss is computed (Cross-Entropy).356        """357        return_dict = return_dict if return_dict is not None else self.config.use_return_dict358 359        outputs = self.poolformer(360            pixel_values,361            output_hidden_states=output_hidden_states,362            return_dict=return_dict,363        )364 365        sequence_output = outputs[0]366 367        logits = self.classifier(self.norm(sequence_output).mean([-2, -1]))368 369        loss = None370        if labels is not None:371            loss = self.loss_function(labels, logits, self.config)372 373        if not return_dict:374            output = (logits,) + outputs[2:]375            return ((loss,) + output) if loss is not None else output376 377        return ImageClassifierOutputWithNoAttention(loss=loss, logits=logits, hidden_states=outputs.hidden_states)378 379 380__all__ = ["PoolFormerForImageClassification", "PoolFormerModel", "PoolFormerPreTrainedModel"]381 
Aluode/PerceptionLabPortable · CoolFace