论文复现——MOAT: Alternating Mobile Convolution and Attention Brings Strong Vision Models

这篇具有很好参考价值的文章主要介绍了论文复现——MOAT: Alternating Mobile Convolution and Attention Brings Strong Vision Models。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本次复现的论文是前几天谷歌团队开发出来的MOAT,目前还没有开源,我复现的代码可以在ImageNet或自己的数据集上训练,支持apex混合精度,各种图像增强技术等。
原论文:https://arxiv.org/pdf/2210.01820.pdf
复现的代码:https://github.com/RooKichenn/pytorch-MOAT

一、MOAT整体结构

MOAT Block:
moat:alternating,论文复现,深度学习,人工智能,神经网络,计算机视觉,pytorch
MOAT-1的整体架构
moat:alternating,论文复现,深度学习,人工智能,神经网络,计算机视觉,pytorch

  MOATMBconv代替了它的MLP,把MBconv放在self-attention前,去掉了MLPMBconv不仅可以增强网络的特征表达能力,而且还能带来更好的下采样能力。由于MBconv在像素之间(从而跨窗口)有效地交换局部信息,因此MOAT不需要额外的window-shifting,并且原论文说明了并没有使用窗口注意力机制,也就是说不像Swing Transformer那样使用复杂的位移窗口机制来让每个窗口之间进行交互,但是不使用窗口注意力机制会增大计算量和训练速度,我认为这里是一个可以改进的点。作者在文中也说出了他们的期望:We hope our study will inspire future research on seamless integration of convolution and self-attention.(我们希望我们的研究能够启发未来关于卷积和自注意力无缝集成的研究) ,所以后续可以在MOAT的基础进行一些改进,水篇论文还是可以的(手动狗头)。

作者对MBConvself-attention中的MPL进行了深度分析,提出了MOAT
  首先,Transformer中的MLP模块类似于MBConv,都采用了倒瓶颈设计。然而,MBConv是一种更强大的操作,通过使用额外的3×3深度卷积(以编码像素之间的局部交互),并且在卷积之间使用更多的激活和归一化。
  其次,为了使用Transformer block提取多尺度特征,可以将AvgPool(步长为2)应用于自我关注层之前的输入特征。然而,AvgPool操作降低了self-attention的表征能力。
  基于上述现象,提出了MOAT block,首先将MLP替换为MBConv,然后颠倒self-attentionMBConv的顺序。用MBConv替换MLP为网络带来了更多的特征表示能力,并且颠倒顺序(MBConv先于self-attention)将下采样任务交给MBConv内的depthwise,从而学习更好的下采样核。通过这种方式,MOAT不需要像 CoAtNet 中的平均池化这样的额外下采样层,也不需要 Swin TransformerConvNeXt 中的patch-embedding layers
  关于文中的MBConvself-attntion就不再做过多的解释了,下面主要说一下自己实现每个模块的思路。

二、MBConv结构

MOAT中有两种MBConv结构,一种是带SE模块的纯MBConv和一种不带SE模块的MOAT结构,这里首先给出纯MBConv的实现代码:

导入需要的库

from typing import Type, Callable, Tuple, Optional, Set, List, Union

import torch
import torch.nn as nn

from timm.models.efficientnet_blocks import SqueezeExcite, DepthwiseSeparableConv
from timm.models.layers import drop_path, trunc_normal_, Mlp, 

纯MBConv结构

class MBConvBlock(nn.Module):
    """
        Args:
        in_channels (int): Number of input channels.
        out_channels (int): Number of output channels.
        downscale (bool, optional): If true downscale by a factor of two is performed. Default: False
        act_layer (Type[nn.Module], optional): Type of activation layer to be utilized. Default: nn.GELU
        norm_layer (Type[nn.Module], optional): Type of normalization layer to be utilized. Default: nn.BatchNorm2d
        drop_path (float, optional): Dropout rate to be applied during training. Default 0.
    """

    def __init__(
            self,
            in_channels: int,
            out_channels: int,
            downscale: bool = False,
            act_layer: Type[nn.Module] = nn.GELU,
            norm_layer: Type[nn.Module] = nn.BatchNorm2d,
            drop_path: float = 0.,
            expand_ratio: int = 4.,
            use_se=False,
    ) -> None:
        """ Constructor method """
        # Call super constructor
        super(MBConvBlock, self).__init__()
        # Save parameter
        self.drop_path_rate: float = drop_path
        if not downscale:
            assert in_channels == out_channels, "If downscaling is utilized input and output channels must be equal."
        if act_layer == nn.GELU:
            act_layer = _gelu_ignore_parameters
        # Make main path
        self.main_path = nn.Sequential(
            norm_layer(in_channels),
            DepthwiseSeparableConv(in_chs=in_channels,
                                   out_chs=int(out_channels * expand_ratio // 2) if downscale else int(
                                       out_channels * expand_ratio),
                                   stride=2 if downscale else 1,
                                   act_layer=act_layer, norm_layer=norm_layer, drop_path_rate=drop_path),
            SqueezeExcite(
                in_chs=int(out_channels * expand_ratio // 2) if downscale else int(out_channels * expand_ratio),
                rd_ratio=0.25) if use_se else nn.Identity(),
            nn.Conv2d(
                in_channels=int(out_channels * expand_ratio // 2) if downscale else int(out_channels * expand_ratio),
                out_channels=out_channels, kernel_size=(1, 1))
        )
        # Make skip path
        self.skip_path = nn.Sequential(
            nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2)),
            nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=(1, 1))
        ) if downscale else nn.Identity()

    def forward(
            self,
            input: torch.Tensor
    ) -> torch.Tensor:
        """ Forward pass.
        Args:
            input (torch.Tensor): Input tensor of the shape [B, C_in, H, W].
        Returns:
            output (torch.Tensor): Output tensor of the shape [B, C_out, H (// 2), W (// 2)] (downscaling is optional).
        """
        output = self.main_path(input)
        if self.drop_path_rate > 0.:
            output = drop_path(output, self.drop_path_rate, self.training)
        output = output + self.skip_path(input)
        return output

这里我直接使用了timm库中封装好的MBConv组件,没什么特别的地方。

MOAT中的MBConv

SqueezeExcite(
                in_chs=int(out_channels * expand_ratio // 2) if downscale else int(out_channels * expand_ratio),
                rd_ratio=0.25) if use_se else nn.Identity(),

在MBConv中我加入了use_se来判断是否需要SE模块。

三、MOAT中的attention结构

class MOATAttnetion(nn.Module):
    def __init__(
            self,
            in_channels: int,
            partition_function: Callable,
            reverse_function: Callable,
            img_size: Tuple[int, int] = (224, 224),
            num_heads: int = 32,
            window_size: Tuple[int, int] = (7, 7),
            use_window: bool = False,
            attn_drop: float = 0.,
            drop: float = 0.,
            drop_path: float = 0.,
            norm_layer: Type[nn.Module] = nn.LayerNorm,
    ) -> None:
        """ Constructor method """
        super(MOATAttnetion, self).__init__()
        # Save parameters
        self.use_window = use_window
        self.partition_function: Callable = partition_function
        self.reverse_function: Callable = reverse_function
        if self.use_window:
            self.window_size: Tuple[int, int] = window_size
        else:
            self.window_size: Tuple[int, int] = img_size
        # Init layers
        self.norm_1 = norm_layer(in_channels)
        self.attention = RelativeSelfAttention(
            in_channels=in_channels,
            num_heads=num_heads,
            window_size=self.window_size,
            attn_drop=attn_drop,
            drop=drop
        )
        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()

    def forward(self, input: torch.Tensor) -> torch.Tensor:
        """ Forward pass.
        Args:
            input (torch.Tensor): Input tensor of the shape [B, C_in, H, W].
        Returns:
            output (torch.Tensor): Output tensor of the shape [B, C_out, H, W].
        """
        # Save original shape
        B, C, H, W = input.shape
        if self.use_window:
            # Perform partition
            input_partitioned = self.partition_function(input, self.window_size)
            input_partitioned = input_partitioned.view(-1, self.window_size[0] * self.window_size[1], C)
            # Perform normalization, attention, and dropout
            output = input_partitioned + self.drop_path(self.attention(self.norm_1(input_partitioned)))
            # Reverse partition
            output = self.reverse_function(output, (H, W), self.window_size)
        else:
            # flatten: [B, C, H, W] -> [B, C, HW]
            # transpose: [B, C, HW] -> [B, HW, C]
            input_partitioned = input.flatten(2).transpose(1, 2).contiguous()
            output = input_partitioned + self.drop_path(self.attention(self.norm_1(input_partitioned)))
            output = output.transpose(1, 2).contiguous().view(B, C, H, W)
        return 

我在自注意力机制中加入了use_window来判断是否需要窗口注意力机制(原论文中为使用窗口注意力机制)

if self.use_window:
            self.window_size: Tuple[int, int] = window_size
        else:
            self.window_size: Tuple[int, int] = img_size

MOAT中使用的是加了相对位置编码的注意力机制,具体可以去看看原论文给出的文献。

#四、训练策略
  由于代码是纯复现,github中给出的参数都是我自己调的,可能不是最优参数,欢迎大家进行调参,给出最优参数。
论文中使用的总batch是4096,咱也没这条件,最大的总batch我用的是512,学习率是8e-4,训练300轮,具体参数可以去参考我复现的代码:https://github.com/RooKichenn/pytorch-MOAT,欢迎star!文章来源地址https://www.toymoban.com/news/detail-568884.html

到了这里,关于论文复现——MOAT: Alternating Mobile Convolution and Attention Brings Strong Vision Models的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Convolution operation and Grouped Convolution

    filter is not the kernel,but the kernels.that\\\'s mean a filter include one or two or more kernels.that\\\'s depend the input feature map and the output feature maps. for example, if we have an image, the shape of image is (32,32), has 3 channels,that\\\'s RGB.so the input feature maps is (1,3,32,32).the format of input feature maps is (batch_size,in_channels,H_in

    2024年02月14日
    浏览(23)
  • 【风格迁移-论文笔记12.20】Arbitrary style transfer based on Attention and Covariance-Matching

    任意风格迁移(Arbitrary style transfer)具有广阔的应用前景和重要的研究价值,是计算机视觉领域的研究热点。许多研究表明,任意风格迁移取得了显着的成功。 然而,现有的方法可能会产生伪影(artifacts),有时会导致内容结构的失真(distortion)。 为此,本文提出一种新颖

    2024年02月03日
    浏览(32)
  • Deep learning of free boundary and Stefan problems论文阅读复现

    在这项工作中,作者提出了一个基于物理信息神经网络的多网络模型,来解决一类一般的正和逆自由边界问题,称为Stefan问题。具体地说,用两个深度神经网络来近似未知解以及任何移动边界。作者提供了三个案例研究(一维一相Stefan问题,一维二相Stefan问题,二维一相Ste

    2024年02月08日
    浏览(34)
  • 【论文笔记】Triplet attention and dual-pool contrastive learning for clinic-driven multi-label medical...

    多标签分类Multi-label classification (MLC)可在单张图像上附加多个标签,在医学图像上取得了可喜的成果。但现有的多标签分类方法在实际应用中仍面临着严峻的临床现实挑战,例如: 错误分类带来的医疗风险, 不同疾病之间的样本不平衡问题 无法对未预先定义的疾病(未见疾

    2024年02月03日
    浏览(35)
  • 【论文复现】AB3DMOT: A Baseline for 3D Multi-Object Tracking and New Evaluation Metrics

    AB3MOT是经典的3D多目标跟踪框架,将2D卡尔曼推广到了3D,并将2D IOU匹配推广到了3D。由于论文的原理基本上与2D相同所以作者在文中没有叙述很多细节,要理解具体实现细节,只能看代码。 项目代码 论文地址 anaconda 官网下载 KITTI数据集 KITTI这是会发现很大如果简单测试可以先

    2024年02月03日
    浏览(33)
  • 【论文笔记】动态蛇卷积(Dynamic Snake Convolution)

    精确分割拓扑管状结构例如血管和道路,对医疗各个领域至关重要,可确保下游任务的准确性和效率。然而许多因素使分割任务变得复杂,包括细小脆弱的局部结构和复杂多变的全局形态。针对这个问题,作者提出了动态蛇卷积,该结构在管状分割任务上获得了极好的性能。

    2024年02月03日
    浏览(28)
  • 【论文笔记】ODConv:OMNI-DIMENSIONAL DYNAMIC CONVOLUTION

    本篇介绍一下动态卷积:ODConv,该方法通过并行策略采用多维注意力机制沿核空间的四个维度学习互补性注意力。作为一种“即插即用”的操作,它可以轻易的嵌入到现有CNN网络中。并且实验结果表明它可提升大模型的性能,又可提升轻量型模型的性能,实乃万金油是也!

    2024年02月11日
    浏览(30)
  • 【论文笔记合集】卷积神经网络之深度可分离卷积(Depthwise Separable Convolution)

    本文作者: slience_me 我看的论文地址:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications 假设输入为D F ×D F ×M,输出为输入为D F ×D F ×N,卷积核为D K ×D K ×M,共有N个卷积核进行卷积操作 下图为标准的卷积过程,每个卷积核对输入的向量进行卷积操作,得到一个

    2024年01月16日
    浏览(29)
  • 深度学习 - 51.推荐场景下的 Attention And Multi-Head Attention 简单实现 By Keras

    目录 一.引言 二.计算流程 1.Attention 结构 2.Multi-Head Attention 结构 三.计算实现 1.Item、序列样本生成 2.OwnAttention Layer 实现 2.1 init 初始化 2.2 build 参数构建 2.3 call 逻辑调用 3.OwnAttention Layer 测试 四.总结 Attention And Multi-Head Attention 一文中我们简单介绍了 Attention 与 Multi-Head Attenti

    2024年02月07日
    浏览(39)
  • 深度学习论文: RepViT: Revisiting Mobile CNN From ViT Perspective及其PyTorch实现

    深度学习论文: RepViT: Revisiting Mobile CNN From ViT Perspective及其PyTorch实现 RepViT: Revisiting Mobile CNN From ViT Perspective PDF: https://arxiv.org/pdf/2307.09283.pdf PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: https://github.com/shanglianlm0525/PyTorch-Networks 本文通过引入轻量级 ViT 的架构选择,重

    2024年02月14日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包