精华内容
下载资源
问答
  • 衡量神经网络的常见参数 FLOPs与参数数量计算方法总结
    千次阅读
    2020-05-12 16:23:37

    FLOPs衡量神将网络中前向传播的运算次数,FLOPs越小,则计算速度越快。
    参数数量衡量神经网络中所包含参数的数量,参数数量越小,模型体积越小,更容易部署,二者计算方法如下所示:

    参数数量更容易计算,只需要衡量,神经网络中有多少个待定参数即可,以卷积神经网络为例,假设卷积核大小为k × k,输入通道为 i,输出通道为o,输出图像尺寸为t ×t,则:
    每进行一次卷积操作,或一个卷积层,需要的参数数量为:
    k×k×i×o + o 后面的加是加上bias,可看下图conv1为例:
    注意 conv1的卷积核大小为11×11,可自行计算出相同结果
    在这里插入图片描述
    在考虑FLOPs时,同样以卷积计算为例,可参考下述代码计算过程:

    input_shape = (3,300,300) # Format:(channels, rows,cols)
    conv_filter = (64,3,3,3)  # Format: (num_filters, channels, rows, cols)
    stride = 1
    padding = 1
    activation = 'relu'
    
    n = conv_filter[1] * conv_filter[2] * conv_filter[3]  # vector_length
    flops_per_instance = n + (n-1)    # general defination for number of flops (n: multiplications and n-1: additions)
    
    num_instances_per_filter = (( input_shape[1] - conv_filter[2] + 2*padding) / stride ) + 1  # for rows
    num_instances_per_filter *= (( input_shape[1] - conv_filter[2] + 2*padding) / stride ) + 1 # multiplying with cols
    
    flops_per_filter = num_instances_per_filter * flops_per_instance
    total_flops_per_layer = flops_per_filter * conv_filter[0]    # multiply with number of filters
    
    if activation == 'relu':
        # Here one can add number of flops required
        # Relu takes 1 comparison and 1 multiplication
        # Assuming for Relu: number of flops equal to length of input vector
        total_flops_per_layer += conv_filter[0]*input_shape[1]*input_shape[2]
    
    
    print(total_flops_per_layer)
    

    上式中,与下列计算结果等效:
    即,没进行一次卷积,计算量大小如下:
    k×k×i×t×t×o + (k×k×i-1)×t×t×o

    更多相关内容
  • 深度学习之图像分类(十五)EfficientNetV1 网络结构 目录深度学习之图像分类(十五)EfficientNetV1 网络结构1. 前言2. 宽度,深度以及分辨率3. EfficientNetV1 网络结构4. 代码 本节学习 EfficientNetV1 网络结构...

    深度学习之图像分类(十五)EfficientNetV1 网络结构

    本节学习 EfficientNetV1 网络结构。学习视频源于 Bilibili。参考博客太阳花的小绿豆: EfficientNet网络详解.

    请添加图片描述

    1. 前言

    EfficientNetV1 是由Google团队在 2019 年提出的,其原始论文为 EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks。所提出的 EfficientNet-B7 在 Imagenet top-1 上达到了当年最高准确率 84.3%,与之前准确率最高的 GPipe 相比,参数量仅仅为其 1/8.4,推理速度提升了 6.1 倍。本文的核心在于同时探索输入分辨率、网络深度、宽度的影响。下图给出了当时 EfficientNet 以及其他网络的 Top-1 准确率和参数量。我们可以发现,EfficientNet 不仅在参数数量上比很多主流模型小之外,准确率也更高。

    请添加图片描述

    下图给出了模型的结构图。图 a 是传统的卷积神经网络,图 b 在 a 的基础上增大了网络的宽度(即特征矩阵的channel个数),图 c 在 a 的基础上增加了网络的深度(层的个数),图 d 在 a 的基础上增大了输入分辨率(即输入高和宽,这会使得之后所有特征矩阵的高和宽都会相应增加),图 e 即本文考虑的同时增加网络的宽度、深度、以及网络的输入分辨率。

    请添加图片描述

    为了提升网络的准确率,一般会考虑增加网络的宽度、深度以及输入图像的分辨率。那么这三个因素是如何影响网络性能的呢?愿论文的部分叙述如下。

    增加网络的深度能够得到更佳丰富、复杂的特征(高级语义),并且能很好的应用到其他任务中去。但是网络的深度过深会面临梯度消失,训练困难等问题。The intuition is that deeper ConvNet can capture richer and more complex features, and generalize well on new tasks. However, deeper networks are also more difficult to train due to the vanishing gradient problem.

    增加网络的宽度能够获得更高细粒度的特征,并且也更容易训练。但是对于宽度很大,深度较浅额度网络往往很难学习到更深层次的特征。例如我就只有一个 3 × 3 3 \times 3 3×3 的卷积,但是输出通道为 10000,也没办法得到更为抽象的高级语义。wider networks tend to be able to capture more fine-grained features and are easier to train. However, extremely wide but shallow networks tend to have difficulties in capturing higher level features.

    增加输入网络的图像分辨率,能够潜在获得更高细粒度的特征模版,图像分辨率越高能看到的细节就越多,能提升分辨能力。但是对于非常高的输入分辨率,准确率的增益也会减少。且大分辨率图像会增加网络的计算量(注意不是参数量)。With higher resolution input images, ConvNets can potentially capture more fine-grained patterns. but the accuracy gain diminishes for very high resolutions.

    从实验结果可见,分别增加三者在准确率达到 80% 之后就近乎趋于饱和了。我们看,同时调整三者当准确率达到 80% 之后并没有达到饱和,甚至还有更大的提升。这就说明了同时考虑网络的宽度、深度以及输入图像的分辨率,我们可以得到更好的结果。此外我们能看到,当 FLOPs 相同的时候,即理论计算量相同的时候,同时增加这三者,得到的效果也会更好(这其实也就是同时小幅度增加这三个,比单单增加其中一个增加得非常狠要好)。那究竟该如何同时去增加这三者呢?

    请添加图片描述

    作者还做了实验,即采用不同网络深度 d 和输入分辨率 r 的组合,不断调整网络的宽度 w 得到了如下结果,可以分析出在相同的 FLOPs 的情况下,同时增加网络深度 d 和输入分辨率 r 效果最好。

    请添加图片描述

    2. 宽度,深度以及分辨率

    为什么 ImageNet 训练测试图像要设置为 224?有人说可能是为了和前人对比网络本身的性能要控制变量吧。那第一个跑 ImageNet 的人为什么用 224 呢?可能别人就会说,工程经验。在本文中,EfficientNetV1 使用 NAS(Neural Architecture Search)技术来搜索网络的图像输入分辨率 r,网络的深度 depth 以及 channel 的宽度 width 三个参数的合理化配置。在之前的一些论文中,基本都是通过改变上述3个参数中的一个来提升网络的性能,而这篇论文就是同时来探索这三个参数的影响。

    为了探究三者与网络性能之间的关系,作者先在论文中对整个网络的运算进行抽象:
    N ( d , w , r ) = ⨀ i = 1 … s F i L i ( X ⟨ H i , W i , C i ⟩ ) N(d, w, r)=\bigodot_{i=1 \ldots s} F_{i}^{L_{i}}\left(X_{\left\langle H_{i}, W_{i}, C_{i}\right\rangle}\right) N(d,w,r)=i=1sFiLi(XHi,Wi,Ci)
    其中:

    • ⨀ i = 1 … s \bigodot_{i=1 \ldots s} i=1s 表示连乘运算
    • F i F_i Fi 表示一个运算操作,例如后面讲的 MBConv, F i L i F_i^{L_i} FiLi 表示在 Stage i 中 F i F_i Fi 运算被重复执行
    • X X X 表示输入 Stage 的特征矩阵
    • ⟨ H i , W i , C i ⟩ \left\langle H_{i}, W_{i}, C_{i}\right\rangle Hi,Wi,Ci 表示特征矩阵 X X X 的高度,宽度,以及通道数

    随后,为了探究 rdw 这三个因子对最终准确率的影响,则将 rdw 加入到公式中,我们可以得到抽象化后的优化问题(在指定资源限制下):

    Our target is to maximize the model accuracy for any given resource constraints, which can be formulated as an optimization problem:

    请添加图片描述

    其中:

    • d 用来缩放网络的深度 L ^ i \widehat{L}_i L i
    • r 用来缩放特征矩阵的 H ^ i , W ^ i \widehat{H}_i, \widehat{W}_i H i,W i
    • w 用来缩放特征矩阵的 C ^ i \widehat{C}_i C i
    • target_memory 为内存限制
    • target_flops 为 FLOPs 限制

    需要指出的是:

    • FLOPs 与d 的关系是:当 d 翻倍,FLOPs 也翻倍。
    • FLOPs 与w 的关系是:当 w 翻倍,FLOPs 会翻 4 倍,因为卷积层的 FLOPs 约等于 f e a t u r e w × f e a t u r e h × f e a t u r e c × k e r n e l w × k e r n e l h × k e r n e l n u m b e r feature_w \times feature_h \times feature_c \times kernel_w \times kernel_h \times kernel_{number} featurew×featureh×featurec×kernelw×kernelh×kernelnumber,假设输入输出特征矩阵的高宽不变,当 width 翻倍,输入特征矩阵的 channels (即 f e a r u r e c fearure_c fearurec)和输出特征矩阵的 channels(即卷积核的个数, k e r n e l n u m b e r kernel_{number} kernelnumber)都会翻倍,所以 FLOPs 会翻 4 倍
    • FLOPs与 r 的关系是:当 r 翻倍,FLOPs 会翻4倍,和上面类似,因为特征矩阵的宽度 f e a t u r e w feature_w featurew 和特征矩阵的高度 f e a t u r e h feature_h featureh 都会翻倍,所以 FLOPs 会翻 4 倍

    所以总的 FLOPs 倍率可以用近似用 ( α × β 2 × γ 2 ) ϕ (\alpha \times \beta^2 \times \gamma^2)^{\phi} (α×β2×γ2)ϕ 来表示,当限制 α × β 2 × γ 2 ≈ 2 \alpha \times \beta^2 \times \gamma^2 \approx 2 α×β2×γ22 时,对于任意一个 ϕ \phi ϕ 而言 FLOPs 相当增加了 2 ϕ 2^{\phi} 2ϕ 倍。为此,作者提出了一个混合缩放方法 ( compound scaling method) ,在这个方法中使用了一个混合因子 ϕ \phi ϕ 去统一的缩放 rdw 这三个因子,具体的计算公式如下:

    请添加图片描述

    接下来作者在基准网络 EfficientNetB-0(下一小节会讲)上使用 NAS 来搜索 α , β , γ \alpha, \beta, \gamma α,β,γ 这三个参数:

    • (step1)首先固定 ϕ = 1 \phi=1 ϕ=1,并基于上面给出的公式 (2) 和 (3) 进行搜索,作者发现对于 EfficientNetB-0 最佳参数为 α = 1.2 , β = 1.1 , γ = 1.15 \alpha = 1.2 , \beta = 1.1 , \gamma = 1.15 α=1.2,β=1.1,γ=1.15 ,此时 α × β 2 × γ 2 ≈ 1.9203 \alpha \times \beta^2 \times \gamma^2 \approx 1.9203 α×β2×γ21.9203
    • (step2)固定 α = 1.2 , β = 1.1 , γ = 1.15 \alpha = 1.2 , \beta = 1.1 , \gamma = 1.15 α=1.2,β=1.1,γ=1.15 ,在 EfficientNetB-0 的基础上使用不同的 ϕ \phi ϕ 分别得到 EfficientNetB-1至 EfficientNetB-7。当 ϕ \phi ϕ = 1 的时候,由公式 (3) 可以得到三者相对于 EfficientNetB-0 的倍率为 d = 1.2 , w = 1.1 , r = 1.15 d = 1.2 , w = 1.1 , r = 1.15 d=1.2,w=1.1,r=1.15 ,对应的就是 EfficientNetB-2。EfficientNetB-1 则是对应于当 ϕ \phi ϕ = 0.5 的情况。

    原论文指出:对于不同的基准网络搜索出的 α , β , γ \alpha, \beta, \gamma α,β,γ 这三个参数不定相同。作者也说了,如果直接在大模型上去搜索 α , β , γ \alpha, \beta, \gamma α,β,γ 这三个参数可能获得更好的结果,但是在较大的模型中搜索成本太大,所以这篇文章就在比较小的 EfficientNetB-0 模型上进行搜索的。Google 这种大厂都说计算量大,那就是真的大

    Notably, it is possible to achieve even better performance by searching for α, β, γ directly around a large model, but the search cost becomes prohibitively more expensive on larger models. Our method solves this issue by only doing search once on the small baseline network (step 1), and then use the same scaling coefficients for all other models (step 2).

    3. EfficientNetV1 网络结构

    EfficientNet-B0 baseline 网络的结构配置如下图所示,这个网络也是作者通过网络搜索技术得到的。后续讲的 EfficientNet-B1 到 B7 都是在这个网络的基础上进行简单调整的。在 B0 中一共分为 9 个 stage,表中的卷积层后默认都跟有 BN 以及 Swish 激活函数。stage 1 就是一个 3 × 3 3 \times 3 3×3 的卷积层。对于 stage 2 到 stage 8 就是在重复堆叠 MBConv。stage 9 由三部分组成,首先是一个 1 × 1 1 \times 1 1×1 的卷积,然后是平均池化,最后是一个全连接层。表中 Resolution 是每个输入特征矩阵的高度和宽度,Channels 是输出特征矩阵的通道数。Layers 则是将 Operator 重复多少次。stride 参数则是仅针对每个 stage 的第一个 block,之后的 stride 都是 1。

    请添加图片描述

    紧接着我们来看看 MBConv 模块。论文中说了他和 MobileNetV3 使用的 block 是一样的(那其实单看网络结构没什么contribution,贡献主要在第二节的研究以及推广的model上)。对于主分支而言,首先是一个 1 × 1 1 \times 1 1×1 卷积用于升维,其输出特征矩阵通道是输入 channel 的 n 倍。紧接着通过一个 DW 卷积(这里 DW 卷积的卷积核可能是 3 × 3 3 \times 3 3×3 或者 5 × 5 5 \times 5 5×5,在上面那个表格中有的,stride 可能等于 1 也可能等于 2)。然后通过一个 SE 模块,使用注意力机制调整特征矩阵。然后再通过 1 × 1 1 \times 1 1×1 卷积进行降维。注意这里只有 BN,没有 swish 激活函数(其实就是对应线性激活函数)。仅当输入 MBConv 结构的特征矩阵与输出的特征矩阵 shape 存在时才有 short-cut 连接,并且在源码中只有使用到 short-cut 连接的 MBConv 模块才有 Dropout 层。同样的,在 stage2 的第一个 MBConv 中,第一个 1 × 1 1 \times 1 1×1 卷积没有升维,所以在实现中没有这个卷积层。

    请添加图片描述

    SE 模块在之前 MobileNetV3 的讲解中讲过了,这里再回顾一下。首先对输入矩阵的每个 channel 进行平均池化,然后经过两个全连接层,第一个是 Swish 激活函数,第二个是 Sigmoid 激活函数。第一个全连接层的节点个数等于输入 MBConv 模块的特征矩阵 channel 个数的 1/4(在 MobileNetV3 中是输入 SE 模块的特征矩阵 channel 的 1/4,都是源码中的细节),第二个全连接层的节点个数等于输入 SE 模块的特征矩阵 channel 个数。第二个全连接层的输出其实就是输入 SE 模块的特征矩阵每个 channel 的注意力权重,值越大越重要,越越小越不重要。将权重按通道乘回原特征矩阵就可以了。

    请添加图片描述

    接下来我们看看 EfficientNet-B1 到 B7 是怎么构建出来的。下表分别给出了针对网络宽度,深度的倍率因子,以及对于输入尺寸上的变化。注意,dropout_connect_rate 就是对应上述讲的 MBConv 中的 Dropout 结构的随机失活比率。dropout_rate 对应的是最后一个全连接层前 Dropout 的随机失活比率。

    请添加图片描述

    性能对比能发现,EfficientNet 就是准确率最高,参数量最小,理论上计算量最低。然而使用中发现,EfficientNet 非常占 GPU 的显存。因为他们输入图像分辨率特别大。速度直接给 FLOPs 就有点耍流氓了,真实运行速度和 FLOPs 不是直接正比的,ShuffleNetV2 就指出,这样做是万万不行滴。

    请添加图片描述

    4. 代码

    EfficientNetV1 实现代码如下所示,代码出处

    import math
    import copy
    from functools import partial
    from collections import OrderedDict
    from typing import Optional, Callable
    
    import torch
    import torch.nn as nn
    from torch import Tensor
    from torch.nn import functional as F
    
    
    def _make_divisible(ch, divisor=8, min_ch=None):
        """
        This function is taken from the original tf repo.
        It ensures that all layers have a channel number that is divisible by 8
        It can be seen here:
        https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
        """
        if min_ch is None:
            min_ch = divisor
        new_ch = max(min_ch, int(ch + divisor / 2) // divisor * divisor)
        # Make sure that round down does not go down by more than 10%.
        if new_ch < 0.9 * ch:
            new_ch += divisor
        return new_ch
    
    
    def drop_path(x, drop_prob: float = 0., training: bool = False):
        """
        Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).
        "Deep Networks with Stochastic Depth", https://arxiv.org/pdf/1603.09382.pdf
    
        This function is taken from the rwightman.
        It can be seen here:
        https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/layers/drop.py#L140
        """
        if drop_prob == 0. or not training:
            return x
        keep_prob = 1 - drop_prob
        shape = (x.shape[0],) + (1,) * (x.ndim - 1)  # work with diff dim tensors, not just 2D ConvNets
        random_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)
        random_tensor.floor_()  # binarize
        output = x.div(keep_prob) * random_tensor
        return output
    
    
    class DropPath(nn.Module):
        """
        Drop paths (Stochastic Depth) per sample  (when applied in main path of residual blocks).
        "Deep Networks with Stochastic Depth", https://arxiv.org/pdf/1603.09382.pdf
        """
        def __init__(self, drop_prob=None):
            super(DropPath, self).__init__()
            self.drop_prob = drop_prob
    
        def forward(self, x):
            return drop_path(x, self.drop_prob, self.training)
    
    
    class ConvBNActivation(nn.Sequential):
        def __init__(self,
                     in_planes: int,
                     out_planes: int,
                     kernel_size: int = 3,
                     stride: int = 1,
                     groups: int = 1,
                     norm_layer: Optional[Callable[..., nn.Module]] = None,
                     activation_layer: Optional[Callable[..., nn.Module]] = None):
            padding = (kernel_size - 1) // 2
            if norm_layer is None:
                norm_layer = nn.BatchNorm2d
            if activation_layer is None:
                activation_layer = nn.SiLU  # alias Swish  (torch>=1.7)
    
            super(ConvBNActivation, self).__init__(nn.Conv2d(in_channels=in_planes,
                                                             out_channels=out_planes,
                                                             kernel_size=kernel_size,
                                                             stride=stride,
                                                             padding=padding,
                                                             groups=groups,
                                                             bias=False),
                                                   norm_layer(out_planes),
                                                   activation_layer())
    
    
    class SqueezeExcitation(nn.Module):
        def __init__(self,
                     input_c: int,   # block input channel
                     expand_c: int,  # block expand channel
                     squeeze_factor: int = 4):
            super(SqueezeExcitation, self).__init__()
            squeeze_c = input_c // squeeze_factor
            self.fc1 = nn.Conv2d(expand_c, squeeze_c, 1)
            self.ac1 = nn.SiLU()  # alias Swish
            self.fc2 = nn.Conv2d(squeeze_c, expand_c, 1)
            self.ac2 = nn.Sigmoid()
    
        def forward(self, x: Tensor) -> Tensor:
            scale = F.adaptive_avg_pool2d(x, output_size=(1, 1))
            scale = self.fc1(scale)
            scale = self.ac1(scale)
            scale = self.fc2(scale)
            scale = self.ac2(scale)
            return scale * x
    
    
    class InvertedResidualConfig:
        # kernel_size, in_channel, out_channel, exp_ratio, strides, use_SE, drop_connect_rate
        def __init__(self,
                     kernel: int,          # 3 or 5
                     input_c: int,
                     out_c: int,
                     expanded_ratio: int,  # 1 or 6
                     stride: int,          # 1 or 2
                     use_se: bool,         # True
                     drop_rate: float,
                     index: str,           # 1a, 2a, 2b, ...
                     width_coefficient: float):
            self.input_c = self.adjust_channels(input_c, width_coefficient)
            self.kernel = kernel
            self.expanded_c = self.input_c * expanded_ratio
            self.out_c = self.adjust_channels(out_c, width_coefficient)
            self.use_se = use_se
            self.stride = stride
            self.drop_rate = drop_rate
            self.index = index
    
        @staticmethod
        def adjust_channels(channels: int, width_coefficient: float):
            return _make_divisible(channels * width_coefficient, 8)
    
    
    class InvertedResidual(nn.Module):
        def __init__(self,
                     cnf: InvertedResidualConfig,
                     norm_layer: Callable[..., nn.Module]):
            super(InvertedResidual, self).__init__()
    
            if cnf.stride not in [1, 2]:
                raise ValueError("illegal stride value.")
    
            self.use_res_connect = (cnf.stride == 1 and cnf.input_c == cnf.out_c)
    
            layers = OrderedDict()
            activation_layer = nn.SiLU  # alias Swish
    
            # expand
            if cnf.expanded_c != cnf.input_c:
                layers.update({"expand_conv": ConvBNActivation(cnf.input_c,
                                                               cnf.expanded_c,
                                                               kernel_size=1,
                                                               norm_layer=norm_layer,
                                                               activation_layer=activation_layer)})
    
            # depthwise
            layers.update({"dwconv": ConvBNActivation(cnf.expanded_c,
                                                      cnf.expanded_c,
                                                      kernel_size=cnf.kernel,
                                                      stride=cnf.stride,
                                                      groups=cnf.expanded_c,
                                                      norm_layer=norm_layer,
                                                      activation_layer=activation_layer)})
    
            if cnf.use_se:
                layers.update({"se": SqueezeExcitation(cnf.input_c,
                                                       cnf.expanded_c)})
    
            # project
            layers.update({"project_conv": ConvBNActivation(cnf.expanded_c,
                                                            cnf.out_c,
                                                            kernel_size=1,
                                                            norm_layer=norm_layer,
                                                            activation_layer=nn.Identity)})
    
            self.block = nn.Sequential(layers)
            self.out_channels = cnf.out_c
            self.is_strided = cnf.stride > 1
    
            # 只有在使用shortcut连接时才使用dropout层
            if self.use_res_connect and cnf.drop_rate > 0:
                self.dropout = DropPath(cnf.drop_rate)
            else:
                self.dropout = nn.Identity()
    
        def forward(self, x: Tensor) -> Tensor:
            result = self.block(x)
            result = self.dropout(result)
            if self.use_res_connect:
                result += x
    
            return result
    
    
    class EfficientNet(nn.Module):
        def __init__(self,
                     width_coefficient: float,
                     depth_coefficient: float,
                     num_classes: int = 1000,
                     dropout_rate: float = 0.2,
                     drop_connect_rate: float = 0.2,
                     block: Optional[Callable[..., nn.Module]] = None,
                     norm_layer: Optional[Callable[..., nn.Module]] = None
                     ):
            super(EfficientNet, self).__init__()
    
            # kernel_size, in_channel, out_channel, exp_ratio, strides, use_SE, drop_connect_rate, repeats
            default_cnf = [[3, 32, 16, 1, 1, True, drop_connect_rate, 1],
                           [3, 16, 24, 6, 2, True, drop_connect_rate, 2],
                           [5, 24, 40, 6, 2, True, drop_connect_rate, 2],
                           [3, 40, 80, 6, 2, True, drop_connect_rate, 3],
                           [5, 80, 112, 6, 1, True, drop_connect_rate, 3],
                           [5, 112, 192, 6, 2, True, drop_connect_rate, 4],
                           [3, 192, 320, 6, 1, True, drop_connect_rate, 1]]
    
            def round_repeats(repeats):
                """Round number of repeats based on depth multiplier."""
                return int(math.ceil(depth_coefficient * repeats))
    
            if block is None:
                block = InvertedResidual
    
            if norm_layer is None:
                norm_layer = partial(nn.BatchNorm2d, eps=1e-3, momentum=0.1)
    
            adjust_channels = partial(InvertedResidualConfig.adjust_channels,
                                      width_coefficient=width_coefficient)
    
            # build inverted_residual_setting
            bneck_conf = partial(InvertedResidualConfig,
                                 width_coefficient=width_coefficient)
    
            b = 0
            num_blocks = float(sum(round_repeats(i[-1]) for i in default_cnf))
            inverted_residual_setting = []
            for stage, args in enumerate(default_cnf):
                cnf = copy.copy(args)
                for i in range(round_repeats(cnf.pop(-1))):
                    if i > 0:
                        # strides equal 1 except first cnf
                        cnf[-3] = 1  # strides
                        cnf[1] = cnf[2]  # input_channel equal output_channel
    
                    cnf[-1] = args[-2] * b / num_blocks  # update dropout ratio
                    index = str(stage + 1) + chr(i + 97)  # 1a, 2a, 2b, ...
                    inverted_residual_setting.append(bneck_conf(*cnf, index))
                    b += 1
    
            # create layers
            layers = OrderedDict()
    
            # first conv
            layers.update({"stem_conv": ConvBNActivation(in_planes=3,
                                                         out_planes=adjust_channels(32),
                                                         kernel_size=3,
                                                         stride=2,
                                                         norm_layer=norm_layer)})
    
            # building inverted residual blocks
            for cnf in inverted_residual_setting:
                layers.update({cnf.index: block(cnf, norm_layer)})
    
            # build top
            last_conv_input_c = inverted_residual_setting[-1].out_c
            last_conv_output_c = adjust_channels(1280)
            layers.update({"top": ConvBNActivation(in_planes=last_conv_input_c,
                                                   out_planes=last_conv_output_c,
                                                   kernel_size=1,
                                                   norm_layer=norm_layer)})
    
            self.features = nn.Sequential(layers)
            self.avgpool = nn.AdaptiveAvgPool2d(1)
    
            classifier = []
            if dropout_rate > 0:
                classifier.append(nn.Dropout(p=dropout_rate, inplace=True))
            classifier.append(nn.Linear(last_conv_output_c, num_classes))
            self.classifier = nn.Sequential(*classifier)
    
            # initial weights
            for m in self.modules():
                if isinstance(m, nn.Conv2d):
                    nn.init.kaiming_normal_(m.weight, mode="fan_out")
                    if m.bias is not None:
                        nn.init.zeros_(m.bias)
                elif isinstance(m, nn.BatchNorm2d):
                    nn.init.ones_(m.weight)
                    nn.init.zeros_(m.bias)
                elif isinstance(m, nn.Linear):
                    nn.init.normal_(m.weight, 0, 0.01)
                    nn.init.zeros_(m.bias)
    
        def _forward_impl(self, x: Tensor) -> Tensor:
            x = self.features(x)
            x = self.avgpool(x)
            x = torch.flatten(x, 1)
            x = self.classifier(x)
    
            return x
    
        def forward(self, x: Tensor) -> Tensor:
            return self._forward_impl(x)
    
    
    def efficientnet_b0(num_classes=1000):
        # input image size 224x224
        return EfficientNet(width_coefficient=1.0,
                            depth_coefficient=1.0,
                            dropout_rate=0.2,
                            num_classes=num_classes)
    
    
    def efficientnet_b1(num_classes=1000):
        # input image size 240x240
        return EfficientNet(width_coefficient=1.0,
                            depth_coefficient=1.1,
                            dropout_rate=0.2,
                            num_classes=num_classes)
    
    
    def efficientnet_b2(num_classes=1000):
        # input image size 260x260
        return EfficientNet(width_coefficient=1.1,
                            depth_coefficient=1.2,
                            dropout_rate=0.3,
                            num_classes=num_classes)
    
    
    def efficientnet_b3(num_classes=1000):
        # input image size 300x300
        return EfficientNet(width_coefficient=1.2,
                            depth_coefficient=1.4,
                            dropout_rate=0.3,
                            num_classes=num_classes)
    
    
    def efficientnet_b4(num_classes=1000):
        # input image size 380x380
        return EfficientNet(width_coefficient=1.4,
                            depth_coefficient=1.8,
                            dropout_rate=0.4,
                            num_classes=num_classes)
    
    
    def efficientnet_b5(num_classes=1000):
        # input image size 456x456
        return EfficientNet(width_coefficient=1.6,
                            depth_coefficient=2.2,
                            dropout_rate=0.4,
                            num_classes=num_classes)
    
    
    def efficientnet_b6(num_classes=1000):
        # input image size 528x528
        return EfficientNet(width_coefficient=1.8,
                            depth_coefficient=2.6,
                            dropout_rate=0.5,
                            num_classes=num_classes)
    
    
    def efficientnet_b7(num_classes=1000):
        # input image size 600x600
        return EfficientNet(width_coefficient=2.0,
                            depth_coefficient=3.1,
                            dropout_rate=0.5,
                            num_classes=num_classes)
    
    
    展开全文
  • 接上一篇VGG当网络层数超过20的时候其训练效果并不会提高的哪去,这篇论文就是在解决这个问题 核心观念:深层次表征的信息是很多视觉任务的核心点 基于这些问题, 本论文提出了残差学习(Residual learning)作为对应的...

    该篇论文的由来:
    接上一篇VGG当网络层数超过20的时候其训练效果并不会提高的哪去,这篇论文就是在解决这个问题

    核心观念:深层次表征的信息是很多视觉任务的核心点

    基于这些问题,
    本论文提出了残差学习(Residual learning)作为对应的解决方法
    残差函数(residual function)
    容易优化
    随着深度的提升,准确率提升显著
    很好地学习了深度特征表示即通俗理解地高级语义信息

    摘要翻译
    更深的神经网络更难训练,我们现有的残差学习框架比我们以前使用的更加容易去充分地训练深层神经网络。作为代替学习非参考函数的手段,我们参考了残差学习函数。明白地再现了输入层。我们提供了广泛的完全凭着经验来的证据表明这些残差网络是更容易去优化,以及能够从被认为更深的网络获取准确率,在 imagenet数据集中,我们用多达152层–比8XVGG更深的残差网络衡量了残差网络,但仍然有着更低的复杂度,在imagenet数据集中,一个整体的残差网络达到了3.57%的错误率这个结果获得了ILSVRC2015分类任务第一的成绩,我们也在CIFAR-10中提出了100和1000层的神经网络

    深层的特征表达式很多视觉识别任务的中心,仅仅因为特别深的表达,我们在COCO项目中获得了28%的有关改进。深度残差网络是我们在ILSVRC,COCO2015中竞赛的基础,我们也在imgagenet数据集中的目标检测,目标定位,coco检测,coco分割等比赛中获得了第一名。

    介绍-翻译
    在这里插入图片描述

    深度的卷积神经网络[22,21在图像分类[21,50,40]任务中已经获得了一系列的突破,深度网络自然地集成了低中高水平的特征[50],以及一个在端对端的多层的时髦的分类器,以及层数的特征可以被大量的深度/层数丰富,最近的证据显示,神经网络的深度是非常重要的,同时也是用一个16到30层的神经网络做imagenet数据集任务也是非常有挑战性的,很多其他的非平凡的识别任务也是有着非常伟大的优势(非常深的模型)

    在深度的意义的驱使下,一个问题出现了,更好的神经网络意味着堆叠更多的层数吗,一个干扰这个问题的回答就是臭名昭彰的从开始就妨碍(函数)收敛的梯度消失/爆炸问题,通过初始化归一化和中间层的初始化(能够让神经网络使用十几层去反向传播使用随机梯度下降(SGD)),这个问题已经极大地解决

    当更加深层的神经网络能够去开始转换,一个更加堕落的问题被暴露了出来,当神经网络层数/深度增加时,准确率变得饱和(可能变得不那么让人惊奇)以及迅速地退化。出人意料的是,这样的退化并不是过拟合造成的,并且,一个模型适当的层数(深度)的增加会导致更高的训练错误率,就像报告[11,42]中所讲的那样,彻底核实
    我们的实验之后。图1示表现了典型示例。

    在这里插入图片描述

    训练时正确率的下降表明不是所有的系统都非常容易去操作,让我们考虑一个浅显的结构,和它的更深的副产物即增加更多的层数进去。那里存在着更深的模型结构:增加的层数是恒等映射的,以及其他的层数是从更浅的模型那里抄过来的。这个结构解决方案的存在表明相比于更浅的对应的模型,更深的模型应该产生更高的训练误差,但是实验表明我们现在在手边的解决手段是不能去找到更好的结构作为解决方案的

    在这篇文章里,我们通过介绍一个深的残差学习框架提出那个降级的问题,作为希望每个少数的直接训练的映射下的堆叠层的替代,我们明确地让这些层训练一个残差的映射。用学术的话来说,就是指示我们需要的映射下的结果作为H(X),我们让那个堆叠的非线性的层训练其他的映射F(X )=H(x) - x,最初的映射是重铸进F(X)+X,我们假定它是比控制最初的非表现得映射更容易去控制残差映射。极端地讲,如果一个确定的映射是可操控的,通过堆叠一个确定的非线性层,他会比训练一个确定的映射变得更加容易去推动残差到0

    通过前向传播神经网络的处理,F(X) +X的系统化的阐述能被认为是切短的连接。切短的连接是这些跳过的一个或者多个层,像我们这种情况,那个被切短的连接仅仅是完成了确定的映射并且他们的输出是被加入到堆叠层中的,确定的切短的连接层既不加入额外的参数,也不增加计算的复杂性。一般的使用者,使用常见的函数库通过反向传播与SGD随机梯度下降法,完整的神经网络可以被端对端地训练,并且被容易地执行

    我们在ImageNet上进行了综合实验,[36]展示退化问题并评估我们的方法。我们证明:1)我们的极深的残差网络很容易优化,但是对应的“普通”网络(即当深度增加;2)我们的深的残差网络可以很容易地享受自深度大大增加,精度得到提高,产生的结果大大优于以前的网络的结果。

    相似的现象也出现在CIFAR-10数据集中,这种情况暗示了我们这样操作的困难,并且我们方法的结果不只是能运用到类似的特别的数据集。使用了超过100层以及探索了超过1000层的模型之后,我们提出了在这个数据集里成功地训练的模型。

    在imagenet分类数据集中,通过使用特别深的残差网络,我们获得了优异的成绩,当仍然有着比VGG更低的复杂性的同时,我们152层的残差网络是目前在imagenet数据集中最深的。在imagenet数据集的测试集中我们总体有3.75%的top-5误差。并且在ILSVRC2015分类任务比赛中赢得了第一名。那个特别深的特征表达同时在其他识别任务中,也有着优异的一般化表现并且在: ImageNet detection, ImageNet localization,COCO detection, and COCO segmentation in ILSVRC &COCO 2015 这些比赛中让我们更进一步获得了第一名。这些强有力的证据表明残差学习原则是具有普适性的,并且在其他的视觉和非视觉任务中我们希望那是个能接受的结果

    2释放工作
    残差表达。在图像识别中,VLAD[18]是一种被残差向量希望用字典编码的表达,并且费舍尔向量能够像一个概率的版本一样被按配方制造。对于图像的修复与分类他们都是非常强有力的浅层的表达。对于向量分层,编码残差向量已显示是比编码原始向量更有效的

    在低水平的版本和电脑图形中,对于局部的不同的方程式,被广泛使用的多重网格的方法[3在多尺度(对于残差解决方案来说,在粗糙的和更出色的缩放之间,每个子问题是有原因的)]再现成像子问题一样的系统。一个可以替代的多重网格的是分层的偏置表现训练(依靠可变的在两个缩放之间表现的残差向量),那以及被显示在[3,45,46]这些求解程序收敛比标准求解程序快很多的未知的残差性质的解决方案中。这些方法暗示道一个好的再现或者预处理可以简化操作

    对于切短的连接来说,实践与理论已经被研究很久了一个早期的多层感知器的训练实践被加入到一个连接自网络从输入到输出的线性层。为了解决提出的梯度下降问题,在一个直接连接到辅助的分类器少数中间的层。那篇论文提出的方法[39,38,31,47],对于中间层的响应,梯度和传播误差都是被切短的连接执行的。在一个最初的构成切短的分支还有几个更深的分支

    与我们的工作同时,“高速公路网”[42,43],显示具有选通功能的快捷方式连接[15],这些门依赖于数据,并且具有参数,例如与我们的无参数身份快捷方式形成对比,当选通快捷方式“关闭”(接近零)时公路网中的层表示非残差函数。相反,我们的公式总是学习,剩余函数;我们的身份捷径永远不会关闭,所有的信息都是传递的,还有其他的残差函数需要学习。此外,高速公路网络还没有显示出精度的提高
    深度极大增加(例如,超过100层)。

    让我们考虑H(X)作为一个用几层堆叠层(对于整个网络来说不是必要的)训练的潜在的映射,通过X指示输入到这几个层中的第一个。如果一个假定是多层的非线性网络能够渐渐地接近复杂的函数,然后它等价于假定的它们能够渐进的残差函数,所以,比我们期待的堆叠层更深地去接近H(X),我们明确地让这些层接近一个残差函数,F(X) = H(X) -X最初地函数因此变成了F(X)+X,尽管这些形式应该被用于渐进地接近我们期望地函数(作为假设),这些学习地易用性可能是不同的

    这个被违反直觉的关于降级问题的现象的再现是积极的。就像我们在介绍中讨论的部分,如果层数/深度的增加能够建造成一个确定的映射,一个更深的模型应该有不比它浅的模型的副产物训练误差大。通过多个非线性层那个梯度问题(梯度消失)预示着求解程序可能在接近一个渐进的确定的映射函数方面有困难。通过残差学习的方式再现之后,如果确定的映射是可操控的,那么,在从0到确定的映射中,对应的求解程序可能只是仅仅作为多层线性层的驱动。

    在真实的情况中,那不像一个确定的映射是可操作的那样,但是那是我们的再现可能有助于这个问题的解决的前提下.如果那个操作函数是比一个0映射更加非常接近一个确定映射的函数,那就应该变得更加容易去使用求解程序去找到一个被确定的参考确定映射值扰乱,以至于这个函数像新的一样。我们的实验显示那个学习残差函数一般有着小的回应,这暗示着确定的映射能提供合理的预处理

    我们使用差学习的方式到每个由几个堆叠的堆叠层中,一个构建的区块已经被显示在图2,学术地讲,在这个论文里,我们认为构建一个区块会被定义为这样:
    在这里插入图片描述

    这里的X和Y是被作为输入层和输出层的向量来考虑的,函数F(X,{Wi})代表对应的被学习的残差映射,例如,图2那里有两层,F = W2σ(W1x),σ表示relu函数并且偏置值是省略简化了符号,F+x的操作是被切短的连接的对应的映射执行的以及元素方式的增加。在加入进去之后,我们采取第二种非线性的特征.

    式(1)中的快捷连接既不引入extra参数,也不增加计算的复杂性。这不仅仅在,实践中很有吸引力,在我们的比较中也很重要,在普通网络和残差网络之间。我们可以比较同时具有相同数量的参数、深度、宽度和计算成本(可忽略的元素添加除外)

    在等式中,X与F的维度必须是相等的,如果不是符号这种情况(当改变输入与输出的颜色通道),我们能够通过切短连接来适应维度以便执行一个线性项目:
    在这里插入图片描述

    在等式中,我们也使用方形矩阵Ws。为了经济地解决提出的梯度消失问题,我们会将它以实验的形式充分的表达出指定的确定的映射,因此ws只是在匹配维度的时候进行运用.

    残差函数F的学习形式是很灵活的,当更多的层数是可能的的时候,在这篇论文的实验中,包含的函数F是有着2到3个层的(见图五),但是如果函数F只是单层的,有着我们没有观察到的公式,等式1是非常相似的线性层:Y = w1x+x

    为了简化,我们也注意到尽管所有的符号是关于充分地连接层,他们是能够用于卷积层的。函数F(X,{Wi})能够表达多层卷积层,在通道之间,元素方式的增加表现在两个特征映射。

    3.3. 网络体系结构
    测试了各种普通网络网/残差网络之后,我们观察到了一致的现象。为了提供讨论的实例,我们描述了ImageNet数据集的两个模型,如下所示。

    普通网络。我们的简单基线(图3,中间)主要是受到了VGG网络架构的启发[41](图3,左)。卷积层主要有3×3滤波器和遵循两个简单的设计规则:(i)对于相同的输出,特征映射大小,层具有相同数量的过滤器;以及(ii)如果特征映射大小减半,则过滤器的数量加倍,以保持每层的时间复杂性。我们直接通过步长为2的卷积层。网络是以一个全局平均池层和一个1000路径结束与softmax完全连接的层。总数,图3(中间)中的加权层为34。值得注意的是,我们的模型具有较少的过滤器和复杂性低于VGG网络[41](图3,左)。我们的34-层基线有36亿次浮点运算(乘法加法),这仅为VGG-19的18%(196亿次失败)。

    在这里插入图片描述
    图三以神经网络在imagenet数据集中的架构为例,左边是VGG19的模型,中间是一般的有着34个参数层的普通神经网络,右边,是一个有着34层的残差网络,是一个切短的增长的维度。表一显示了更多的细节与其他的变种。

    残差网络
    基于普通神经网络,我们插入了切短的连接层,就变成了残差网络的副产物。那个特定的切短的能够被直接使用在输入和输出都是同一个维度的情况(就是图三中被切短的固定的线)。随着维度的增加(有附加点的线被切短),我们考虑到了两种选择:A,被切短的仍然表现为确定的映射。使用额外0整个填充到增加的维度中,这样的操作采用了没有额外的参数的方式B那个在公式中被切短的投影被用于匹配维度,为了这些选择,当被切短的到特征映射去之后变成两个尺寸,它们表现为步长为2.

    3.4. 执行

    我们对ImageNet数据集的实现遵循以下原则:
    在[21,41]中。图像的大小调整为其较短的边运行,并在[256,480]中进行域采样,以进行放大[41]。
    从图像或其中随机抽取224×224作物,水平翻转,每像素平均值减去[21]。这个使用[21]中的标准增色。我们采用批量每卷积后的归一化(BN)[16]和激活前,请遵循[16]。我们初始化权重
    如[13]所示,从零开始训练所有平网/剩余网。我们使用SGD,最小批量大小为256。学习率
    从0.1开始,当误差平台时除以10,模型的培训范围为60×104迭代。我们使用0.0001的重量衰减和0.9的动量。我们按照[16]中的实践,请勿使用辍学[14]。在测试中,为了进行比较研究,我们采用了标准
    10作物试验[21]。为了获得最佳结果,我们采用[41,13]中的完全卷积形式,并平均得分,在多个比例(图像的大小调整为更短侧位于{224、256、384、480、640})。

    4实验

    4.1. ImageNet数据集分类
    我们在由1000个类组成的ImageNet 2012分类数据集[36]上评估了我们的方法。模型对128万张训练图像进行训练,并对50k验证图像进行评估。我们还获得了一个决赛测试服务器报告的100k测试图像的结果。我们评估了前1名和前5名的错误率。普通网络。我们首先评估18层和34层普通网。34层平网如图3(中)。这个18层的平网也是类似的形式。详细架构见表1。表2中的结果表明,较深的34层平原
    net比浅层18层具有更高的验证误差普通神经网络。为了揭示原因,在图4(左)中,我们比较了他们在培训过程中的培训/验证错误。我们已经观察到了退化问题——即

    在这里插入图片描述
    表1。ImageNet的体系结构。构建块显示在括号中(另请参见图5),其中包含堆叠的块数。向下采样由conv3 1、conv4 1和conv5 1执行,步长为2。

    大概结构
    在这里插入图片描述

    总体结构
    在这里插入图片描述

    在这里插入图片描述
    图4。ImageNet的训练。细曲线表示训练误差,粗曲线表示中心作物的验证误差。左:普通
    18层和34层网络。右图:18层和34层的resnet。在这个图中,残差网络没有额外的参数相比
    他们平淡无奇的对手。

    在这里插入图片描述

    表2。ImageNet验证中的前1个错误(%,10个作物测试)。这里resnet与普通resnet相比没有额外的参数。相对应的。图4显示了训练过程。

    34层平网在整个训练过程中具有较高的训练误差,整个训练过程,即使解区域,18层平面网络的子空间是18层平面网络的子空间,34第一层。,我们认为这种优化困难不大可能解决,这是由消失的梯度引起的。这些普通网络用BN[16]训练,确保向前传播,信号具有非零方差。我们还验证了,反向传播的梯度表现出良好的的规范,国阵。所以向前和向后的信号都不会消失。事实上,34层平面网仍然能够达到相当的精度(表3),这表明求解器是有效的,在某种程度上。我们推测深平原网可能,具有指数级的低收敛速度,这会影响,减少培训错误3,这种优化困难的原因将在将来研究。

    残差网络
    接着我们衡量了一个18层和34层的残差网络。基线结构是像包括普通神经网络,期待里面有一个切短的被加入了每个3*3的像图中(右边)的滤波器的连接层一样。在第一个对照(表二和表四右边)我们使用了确定的映射给了所有的切短和用0填充的增加的维度(按A方案进行操作)所以相比于一般神经网络的副产物,它们没有额外的参数

    我们从表2和表2得到了三个主要的观察结果图4。首先,用残差学习来扭转这种局面——34层ResNet比18层ResNet好(2.8%)。更重要的是,34层ResNet展示了大大降低了训练误差,并可推广到验证数据集中。这表明退化问题在这种情况下得到了很好的解决,我们设法获得增加深度可提高精度。

    在这里插入图片描述
    表3。ImageNet验证的错误率(%,10作物测试)。VGG-16是基于我们的测试。ResNet-50/101/152属于方案B只使用投影来增加尺寸。

    在这里插入图片描述

    表4。ImageNet上单个模型结果的错误率(%)
    验证集(除†在测试集上报告)。
    在这里插入图片描述
    表5。集合的错误率(%)。前5个错误出现在ImageNet的测试集,并由测试服务器报告。

    其次,比较了他普通神经网络的副本之后,那个34层的残差网络在top-1错误率为3.5%(表二),从成功地减少训练误差的结果表明,这种对照地多样性是残差学习在特别深的系统中获得的结果

    最后,我们也注意到了18层的残差网络收敛地更快(图四左边与右边),当该网络(层数)没有那么深地时候(18层),通用的随机梯度下降的解决程序仍然能够在普通的神经网络中找到一个好的解决方案.在这种情况下,在早期阶段,残差网络能轻松被更快地收敛操控

    特征与投影的切短
    在这里插入图片描述
    图5。ImageNet的一个较深的残差函数F。左:a构建块(在56×56特征图上)如图3所示,用于ResNet 34。右:ResNet-50/101/152的“瓶颈”构建块。

    无参数,身份快捷方式有助于培训。下一个我们研究投影快捷方式(Eqn.(2))。在表3中,我们
    比较三个选项:(A)使用零填充快捷方式,为了增加尺寸,所有快捷方式都是参数自由(与表2和图4右侧相同);(B)projec快捷方式用于增加尺寸,以及其他快捷方式是标识;(C)所有快捷方式都是投影。表3显示,这三种选项都比普通的期权要大得多。B比A稍好一点。我们
    认为这是因为在确实没有剩余的学习的情况下。C略好于B、 我们把它归结为引入的额外参数
    通过许多(十三)个投影快捷方式。但是,A/B/C之间的小dif引用表明投影快捷方式是
    对于解决退化问题不重要。所以我们在本文的其余部分中不要使用选项C,以减少mem/时间复杂性和模型大小。标识快捷方式为不增加。
    下面介绍的瓶颈体系结构。更深层的瓶颈架构。接下来我们描述我们的
    ImageNet的更深的网络。由于我们对火车的时间有顾虑,我们可以负担得起,我们修改了建筑块
    作为瓶颈设计4对于每个剩余函数F,我们使用3层而不是2层的堆栈(图5)。三层
    分别为1×1、3×3和1×1卷积,其中1×1层负责减少和增加(恢复)
    尺寸,使3×3层成为瓶颈输入/输出尺寸。图5示出了示例,其中这两种设计都具有相似的时间复杂性。
    无参数标识快捷方式对于瓶颈体系结构来说尤其重要。如果图5(右)中的标识短被投影替换,则可以
    显示时间复杂度和模型大小都翻了一番,因为快捷方式连接到二维
    末端。所以身份快捷方式可以导致更高效的模型为瓶颈设计。
    50层ResNet:我们替换中的每个2层块
    34层网与此3层瓶颈块,构成50层ResNet(表1)。我们使用选项B来增加
    尺寸。这个模型有38亿次失败。101层和152层resnet:我们构造101-通过使用更多的3层块来实现分层和152层重网(表1)。值得注意的是,尽管深度增加,152层ResNet(113亿次失败)仍然
    比VGG-16/19网络的复杂度低(15.3/19.6 bil lion FLOPs)。
    50/101/152层resnet比在34层中有相当大的差距(表3和表4)。
    我们没有观察到退化问题,因此,从显著增加的数据中获得了显著的精度提高
    深度。所有评估都见证了深度的好处指标(表3和表4)。
    与最新方法的比较。在表4中我们与以前最好的单模型结果进行了比较。我们的基线34层resnet已经达到了非常有竞争力的精度。我们的152层ResNet只有一个模型前5名验证误差为4.49%。这个单一模型的结果优于所有以前的集成结果(表5)。我们将六个不同深度的模型组合成一个整体
    (提交时只有两个152层)。这导致测试集的前5名误差为3.57%(表5)。该作品获得了2015年ILSVRC的第一名。

    展开全文
  • 这篇文章提出了一个能够基于局部像素对的组合关系自适应确定聚合权值的图像特征提取方法,称作局部关系层。使用这种关系方法,它可以以一种更有效的方式将可视化元素组合到更高级的实体中,这有利于语义推理。在像...

    Local Relation Networks for Image Recognation ICCV 2019

    摘要

      多年来,卷积层一直是计算机视觉领域中主要的特征提取方法。 然而,卷积中的空间聚合基本上是一个模式匹配过程,它使用固定的滤波器,在建模不同空间分布的视觉元素时效率很低。这篇文章提出了一个能够基于局部像素对的组合关系自适应确定聚合权值的图像特征提取方法,称作局部关系层。使用这种关系方法,它可以以一种更有效的方式将可视化元素组合到更高级的实体中,这有利于语义推理。在像ImageNet分类这样的大规模识别任务中,采用局部关系层构建的网络(Local Relation network, LR-Net)比常规卷积构建的网络具有更大的建模能力。

    Introduction

      人类有非凡的能力“用有限的手段看无限的世界”。通过感知有限的一组低级视觉原语,它们可以有效地构成无限的高级视觉概念,从而形成对所看到的场景的理解。

      在计算机视觉中,这种合成行为可以通过在卷积神经网络中构建层次表示来近似,在卷积神经网络中,不同层代表不同层次的视觉元素。在较低的层中,提取边缘等基本元素。这些在中间层组合成对象的部分,最后在更高的层,整个对象被表示出来。

      尽管一系列卷积层可以构建层次表示,但其将低级元素组合到高级实体的机制在概念推理方面可能是非常低效的。卷积层不是识别元素如何有意义地结合在一起,而是充当模板,根据卷积过滤权值在空间上聚合输入特征。为了有效地组成特征,需要学习和应用合适的过滤器。当试图推断具有显著空间可变性的视觉概念时,如图1所示的几何变形,这个要求是有问题的,因为过滤学习可能面临不同有效组合可能性的组合爆炸。本文提出了一种新的计算网络层,称为局部关系层,该层可以自适应地推断局部区域中视觉元素之间的有意义的组成结构。 

      不同于卷积层对空间相邻的输入特征采用固定的聚合权值,我们的新层基于局部像素对的可组合性调整聚合权值。这种嵌入可能还可以解释几何先验,这在视觉识别任务中已经证明是有用的、通过学习如何在局部区域内自适应地组合像素,可以建立更有效和高效的组合层次结构。

      在深度网络中,局部关系层可以作为卷积层的直接替代,增加的开销很少。利用这些层,我们开发了一种称为局部关系网络(Local Relation network, LR-Net)的网络架构,该架构遵循了ResNet中对残余块进行叠加的做法,以实现对非常深的网络的优化。在相同的计算预算下,具有26层和瓶颈残块的LR-Net在ImageNet图像分类任务的Top  1精度上比常规的26层ResNet高出绝对3%。改进的精度也实现了基本残差块和更深的网络(50和101层)。

      除了较强的图像分类性能外,本文还展示了局部关系网络的一些良好特性。其中之一是与常规卷积网络相比,它们在利用大型核邻域方面更有效。常规的ConvNets主要使用3×3的核,因为在更大的尺寸下饱和,而LR-Net被发现受益于7×7甚至更大的核。我们还表明,该网络对于对抗性攻击更健壮,这可能是由于它在空间域的组成能力。

      我们注意到,虽然深度神经网络都形成了自底向上的图像特征层次,但它们通常是基于静态卷积权值来聚合特征的,可以看作是一种自顶向下的方式。相比之下,我们的组合方法基于局部像素对的可组合性自适应计算权值,称为自底向上的方式。最近也有一些方法可以这样做,但它们要么不适用于大规模的识别任务,要么只是作为常规卷积的补充作用,而不是替代。此外,这些方法对整个输入特征图进行空间聚合,而没有考虑像素之间的几何关系,而我们的网络显示了位置和几何先验的重要性。研究结果表明,自底向上确定特征聚合权值的方法是可行和有效的。

    2 Related Works

    卷积层和扩展:它最近的流行始于AlexNet[17]在ImageNet[7]上对对象进行分类的出色表现。从那时起,卷积层几乎被专门用于提取基本的视觉特征。

      已经提出了正则卷积层的扩展。在一个方向上,通过限制聚集输入通道的范围,可以获得更好的精度-效率。代表性的著作有组卷积[17,31]和深度卷积[5,11]。另一个方向是修改聚合的空间范围。这样做是为了扩大接受域,例如通过atrous/ extended卷积[4,33],并通过主动[14]和变形卷积增强几何变形建模的能力[6,36]。

      有些工作放宽了跨位置共享聚合权重/范围的要求。局部连接层[25]采用一种简单的方法,它学习不同位置的独立聚合权值。由于正则卷积失去了一些重要的性质,包括平移不变性和知识迁移,它的应用受到了限制。在该方向的其他工作中,提出了生成位置自适应聚合权值[15]或自适应聚合范围的卷积层。

      我们注意到,正则卷积和上述扩展都以自顶向下的方式操作,根据图像外观或接受域内的空间位置决定它们的卷积行为。相比之下,本文提出的层基于局部像素对的可组合性以自下而上的方式确定聚合权值,我们认为这种方式提供了视觉世界中更有效的空间组合编码。同时,该层遵循并适应了来自这些卷积变体的一些有利的设计原则,如局部性、几何先验的使用、以及跨位置的权/元权共享,这些原则已经被发现是有效提取视觉特征的关键。

    胶囊网络:为了解决卷积层的一些缺点,最近的研究是基于像素对的可组合性,以自底向上的方式确定聚合权值。一个代表性的工作是胶囊网络[24,10],其中可组合性是通过迭代路由过程计算的。在路由的每一步中,如果聚合前后的向量距离较近,则聚合权值增大;反之,聚合权值减小。胶囊网络中的这种自我强化过程类似于过滤气泡的过程。过滤气泡是社交网络中普遍存在的一种现象,利益相同的agent之间的连接变得更强,而利益不同的agent之间的连接变得更弱。

      虽然该路由方法很有启发性,但其计算量与现有的学习基础设施如反向传播和多层网络不太匹配。而局部关系层中像素对的可组合性是通过学习到的嵌入参数在嵌入空间中像素对的相似度来计算的,这更有利于当前的学习基础设施。局部关系层与胶囊网络的区别还在于其聚合计算过程,包括其空间范围(localvs.global)和几何先验(有无)。基于这些差异,局部关系网络明显比现有的基于自底向上聚合的方法更具有实用性。

    自注意力/图网络:所提出的局部关系层还与自然语言处理中使用的自注意模型[26]以及应用于非网格数据的图网络有关。这些作品共享一个类似于一般关系建模[1]的基本结构,这自然地在网络中引入了组合性。

      由于其强大的组合建模能力,这些方法已成为各自领域的主导方法。然而,在计算机视觉中,在其网络架构中涉及这种组合性的工作很少[12,28,32,19,29,13,30]。在[12]中,对象提议之间的关系被建模,这导致了提高精度以及第一个完全端到端对象检测器。该工作中的关系建模应用于非网格数据。在[28]中,像素之间的关系被建模,就像在我们的工作中一样。然而,目标是不同的。[28]提取长程上下文作为卷积层的补充,我们追求一种基本的图像特征提取器,比卷积层具有更强的空间构成表示能力。[13]中探索了通道注意,[30]进一步整合了通道注意和空间注意。

      从这个意义上说,我们的工作连接了将组合引入表示的一般哲学,这种哲学已被证明在处理顺序和非网格数据方面是有效的,并可作为计算机视觉的基本特征提取器。这样一个目标不是微不足道的,需要双方都做出调整。

    3 A General Formulation

      在本节中,我们描述了基本图像特征提取的一般公式,并在此基础上提出了局部关系层。用x\in \mathbb{R}^{C \times H \times W}y\in \mathbb{R}^{C^{'} \times H^{'} \times W^{'}}表示一个层的输入和输出。C,C^{'}表示输入/输出通道的特征。H,W,H^{'},W^{'}表示输入/输出的空间分辨率。现有的基本图像提取层一般是通过对输入特征的加权聚合产生输出特征。

      c,c^{'},p=(h,w),p^{'}=(h^{'},w^{'})表示输入和输出通道,和特征图的位置。\Omega _{c^{'}},\Omega_{p^{'}}表示分别在通道c^{'}和位置p{'}处产生输出特征值时,输入特征的通道和空间聚合范围。\omega(c,c^{'},p,p^{'})表示从c,pc^{'},p^{'}的聚合权重。现有的基本图像特征提取层主要从参数化方法、聚合范围和聚合权值三个方面进行区分。

    参数化方法:定义要学习的模型权重。最常用的参数化方法是直接学习聚合权重ω[18]。还有一些方法可以通过学习元网络{θ}的输入特征来生成自适应聚合权值[15]或跨空间位置[6]的自适应聚合范围,或者学习关于空间聚合范围的固定先验(Ω)[14]。通常,参数化是跨空间位置共享的,以实现平移不变性。

    聚合范围:定义聚合计算中涉及的通道和空间位置的范围。对于通道范围,正则卷积在计算每个通道输出时包括所有输入通道。为了提高效率,有些方法在产生一个输出特征通道时只考虑一个或一组输入通道[17,5]。最近,已经出现了多个或所有输出通道共享相同聚合权的方法[28,24]。对于空间范围,大多数方法限制了局部区域内的聚集计算。将聚合限制在局部区域不仅可以显著减少计算量,还有助于引入信息瓶颈,从而促进视觉模式的学习。然而,最近的非卷积方法[28,24]多采用全空间范围进行聚合计算。

    聚合权重:通常作为网络参数学习或从中计算。几乎所有卷积的变体都以自顶向下的方式获得它们的聚合权值,它们要么是跨位置固定的,要么是由一个元网络决定的,在该位置的输入特征。还有一些非卷积方法[28,24]采用自下而上的方式计算聚合权值,权值由像素对的可组合性确定。与聚合权值严重依赖几何先验的卷积变式不同,这种先验在最近的非卷积方法中很少使用。表1总结了现有的基本图像特征提取器。

    表1.基本图像特征提取方法综述。“参数化”列表示要学习的模型权重。符号ω,{θ},Ωdenote聚合权值,元网络权值,空间采样点权值。" share "指示参数化的权值是否跨位置共享。聚合作用域包括通道域和空间域。“聚合权值”列包括三个方面:如何从参数化权值计算聚合权值(“计算”子列);包含几何先验(“geo。“sub-column);计算类型(“类型”子列)。 

    4 Local Relation Layer

      在本节中,我们将介绍局部关系层。用一般公式Eqn.1表示。它的聚合权重定义如下:

    \Phi ()一项是测量目标像素点p^{'}和位置范围内像素点p之间的可组合性的指标,基于在它们经过f_{\theta_{q}},f_{\theta_{k}}变换后的外观,最近的工作是关系建模[1]。f_{\theta_{g}}(p-p^{'})项定义了基于几何先验的像素对(p,p ')的可组合性。几何项采用相对位置作为输入,具有平移不变性。

      如表1所示,这个新层属于自底向上方法类,因为它根据两个可视元素的属性确定可组合性。在下面,我们介绍它的设计,并讨论它与现有的自下而上方法的区别。这些差异导致在图像识别基准上显著更高的精度。它的性能也可以媲美或超越最先进的自顶向下卷积方法。

    局部性:自下而上的方法通常从整个图像中聚合输入特征。而局部关系层则将聚合计算限制在一个局部区域内,例如一个7×7的neighborhood。我们发现,在视觉识别中,将聚合范围限制在局部邻域是特征学习的关键(见表3)。与将聚合计算限制在空间邻域的卷积变式相比,局部关系层在利用更大的核时更有效。虽然卷积变量通常在邻域大于3×3时表现出性能饱和,但当邻域大小从3×3增加到7×7时,局部关系层的精度稳步提高(见表3)。这种差异可能是由于卷积层的表示能力被固定滤波器的数量所限制,因此不能从较大的核中获益。相比之下,局部关系层以一种灵活的自底向上的方式组成局部像素对,使其能够有效地建模大小和复杂性不断增加的视觉模式。我们默认使用7×7核大小。

     外观可组合性:我们采用关系建模[1]的一般方法来计算外观组合性\Phi (f_{\theta_{q}}(x_{p^{'}}),f_{\theta_{k}}(x_{p})),其中x_{p^{'}},x_{p} 分别被投影到一个查询query(通过通道变换层f_{\theta_{q}})和键key(通过通道变换层f_{\theta_{k}})嵌入空间。在之前的工作中,查询和键都是向量,而在局部关系层中,我们使用标量来表示它们,使得计算和表示都是轻量级的。我们发现标量也能很好地工作,并且与向量相比有更好的速度-精度权衡(见表4)。

      我们考虑如下函数Φ的实例化,稍后我们将展示它的类似工作(参见表6):

      a)平方差异:

      b) 绝对值差异:

      c)乘法

     

     默认情况下,我们使用Eqn(3)

    几何先验:区分局部关系层与其他自底向上方法的另一个重要方面是包含几何先验

      几何先验由一个小网络在pp^{'}的相对位置上进行编码。该小网络由双通道变换层组成,中间有一个ReLU激活。我们发现,使用小网络计算几何先验值比直接学习要好,特别是当邻域规模较大时(见表3)。这是因为相对位置上的小网络将相对位置视为度量空间中的向量,而直接法将不同的相对位置视为独立的恒等式。注意,使用小网络的推理过程与直接学习几何先验的过程是相同的。事实上,在推理过程中,固定的学习权重\theta_{g}会对相对位置\Delta p产生固定的几何先验值f_{\theta_{g}}(\Delta p)。我们使用这些固定的几何先验值来代替原始模型权重\theta_{g},以方便推断。  

    表3.不同空间聚合范围和不同几何先验项的体系结构对ImageNet分类的识别性能。报告前1名和前5名的准确率(%)。“NG”表示没有几何先验项的局部关系网络。“G*”表示第4节中描述的直接学习几何先验值的方法。为了公平比较,我们通过调整瓶颈比率α,将所有架构设置为与常规的ResNet-26模型具有相似的FLOPs。对于ResNet-(DW)-26网络,由于实现困难,我们省略了“完整图像”一栏。 

    权重归一化: 我们在空间范围Ω上使用SoftMax规范化来计算最终的聚合权重。这种归一化在平衡外观可组合性和几何先验项的贡献方面是至关重要的(见表6)。

    通道共享: 根据[24],局部关系层在聚合计算中使用信道共享,多个信道共享相同的聚合权值通道共享一般可以减少模型大小,便于GPU内存调度,实现高效。在CUDA内核实现中,当多达8个通道(默认)共享同一个聚合(见表5)时,我们观察到准确率没有下降,而与每个聚合1个通道相比,CUDA内核实现实现了3×actual以上的加速。

    表5.在通道共享上进行的消融实验(top-1 acc%) 

    复杂度和实现:局部关系层如图2所示。给定H×W输入特征图、k×k空间邻域、C个通道和每次聚合计算的m个通道,计算具有跨度的局部关系层的总计算复杂度(以FLOPs计算)

      在我们的实验中,使用了一个CUDA内核的朴素实现,它比使用相同的FLOPs4的常规卷积慢几倍。请注意,卷积有一个高度优化的实现和仔细的内存调度。局部关系层的内存调度优化将是我们未来工作的重点。 

    5 Local Relation Networks

      在深度神经网络中,局部关系层可以代替空间卷积层。在本节中,我们描述ResNet架构[9]中的层替换,其中具有相同拓扑的残余块被堆叠起来。图3展示了瓶颈/基本残留块中的3×3卷积层和ResNet中的第一个7×7卷积层的替换。对于剩余块,我们采用被替换层的膨胀比(α)来保持FLOPs不变。对于第一个7×7卷积层,我们通过通道转换层将3×H×W输入转换为64×H×W的特征映射,然后再转换为7×7本地关系层。替换7×7卷积层消耗了类似的FLOPs,在ImageNet识别上具有相当的精度。在实验中,我们将主要去除在残块中替换3×3卷积层的影响。在替换了ResNet中所有的卷积层之后,我们得到了一个我们称之为Local Relation network (LR-Net)的网络。表2显示了ResNet-50和LR-Net-50的比较(默认超参数为7×7内核大小,每个聚合m= 8个通道)。LR-Net-50使用类似的FLOPs,但由于其通道共享聚合,模型尺寸略小。 

    图3.在ResNet架构中替换第一个7×7卷积层(a)和瓶颈/基本残留块(b)(c)的说明。“CT”为通道变换层,“LR”为局部关系层。“7×7(8), 64”表示7×7的内核大小,m= 8的通道共享,输出通道为64。“s=2”表示步长为2。所有层后面都是批处理正则化层和ReLU激活层。

    6 实验

      我们对ImageNet-1K图像分类任务进行了消融研究。在GPU资源有限的情况下,为了便于研究,我们使用LR-Net26进行研究。LR-Net26是基于ResNet-26的26层局部关系网络。网络有8个瓶颈残差块,分别为res2,res3,res4,res5使用{2,2,2,2}块。我们还报告了由基本残差块(LR-Net-18)堆叠的网络(LR-Net-50, LR-Net-101)的结果。本文还研究了LRNets对对抗性攻击的鲁棒性。我们的实验设置和超参数大多遵循[31]。详情请见附录。

     6.1 消融实验

    空间范围的影响:表3给出了不同聚合空间范围对所提出的局部关系网络的影响,以及规则的ResNet-26网络及其变体resnet-DW-26[21],其中规则卷积层被深度卷积取代。我们有以下观察。

    a)局部的重要性

      现有的自底向上的方法通常计算整个输入特征图的空间聚集[28,24]。首先,我们将所提出的局部关系网络(在空间聚合范围内施加局域性约束)与没有该约束的等效方法(表3中的“完整图像”列)进行了比较5。在不编码任何几何先验(表中称为“NG”)的情况下,我们观察到一个巨大的改进,即将聚合计算从使用整个输入特征图改为仅使用7×7邻域(从50.7到71.9)。令人惊讶的是,虽然卷积网络的有效性归因于几何先验的显式建模,但我们仅通过对无几何聚集方法应用局部约束获得了ImageNet分类的竞争性精度(71.9 vs. 72.8),证明了局部约束的有效性。对于编码第4节中描述的几何先验项的LR-Net-26模型,我们也观察到显著的精度提高,从68.4提高到75.7。注意到几何先验也可以作为限制聚合范围的一种方法(几何先验值较小的位置对最终的聚合计算贡献很小),局域约束进一步约束了聚合范围。局部性约束也可以为网络提供一个信息瓶颈,这有助于表示学习。 

    b)LR-Net受益于大核

      正则ResNet-26模型与3×3和5×5核具有相似的精度,但当核大小大于5×5时,精度下降。对于ResNet-DW-26模型,从3×3移动到9×9时,精度几乎没有变化。相比之下,两个LR-Net-26变体(之前有/没有几何计算)获得稳步改善准确性当内核大小增长从3×3 - 7×7:70.8→71.5→71.9 LR-Net-26 (NG)没有几何术语之前,和73.6→74.9→75.7 LR-Net-26之前包括外观可组合性和几何条件。结果表明,提出的LR-Net在利用大核方面具有优越性。 

    几何先验的效果:在表3的最后三行中,对几何先验的编码进行了消融实验。几何先验嵌入方法优于空间范围上不使用几何先验的方法,证明它们在视觉特征学习中的有用性。

      对比两种几何先验编码方法,在相对位置(最后一行)上应用小网络比直接学习独立的几何先验值效果更好。当kernel size越大时,它们之间的差距就越大(3×3是0.4,9×9是3.1),这表明额外考虑相对位置非常重要,特别是当邻域较大时。

      图4显示了在LR-Net-26的四个阶段中,通过softmax学习到的7×7几何先验值。一般来说,对于较低的层,先验更清晰,这表明在学习外观组合性时偏好更强的约束。对于更高的层,先验更平滑,表明更大的自由偏好。 

    我们的设计:

    我们也消融了各种设计元素。

    a)query/key的维度

      表4消融key/query的维度。我们发现,随着键/查询维度的增加,精度会降低,这表明了标量相对于通常使用的向量的优势,以及更好的速度-精度权衡。

    b) 信道共享的效果

    表5通过改变每次聚合的共享通道数量(m)来进行消融。当m为8时,LR-Net-26的准确性保持不变。

    c)可组合性的术语

    表6给出了不同的外观组合项:Eqn3,Eqn4和Eqn5.人们发现它们的效果相当好。图5展示了使用缺省条件Eqn学习到的键和查询映射的典型示例。(3),表明学习到语义视觉元素之间的可组合性(女孩和狗,网球和球拍)。

    d) Softmax归一化

    table6显示在Eqn中包含了Softmax归一化。(2)精度提高了0.9,说明了规范化在平衡两项中的重要性。

    与其他自下而上方法的比较:

    表7比较了LR-Net与其他自下而上的方法,即非局部神经网络[28]。通过将ResNet-26模型中的3×3卷积层直接替换为非局部模块,该模型(NL-26)的准确率为47.7,远低于常规模型。在每个残差块后应用非局部模,得到top-1精度为73.4,比常规模高0.6,计算量约为2×more。局部关系层被设计用来代替卷积层,以获得更好的表示能力。在类似的计算负载下,它比常规的ResNet对手获得了2.9的增益。我们注意到,非局部模块是局部关系网络的补充,当应用于每个局部关系块后(见最后一行)带来0.3的增益。

    在不同的/更深层次的网络

    在表8中,我们评估了不同/更深层次网络架构的LR-Net,包括由8个基本残留块组成的ResNet-18和使用相同类型的瓶颈残留块但有更多层(50和101层)的ResNet-50/101。提出的网络在这些体系结构上也是有效的。

    7 Conclusion and Future Works

      本文提出了一种基本的图像特征提取方法——局部关系层。由这一新的层组成的深度网络在ImageNet分类上显示了良好的结果,显著扩展了自底向上方法的实用性,长期以来,自底向上方法被认为比自顶向下方法(如卷积)在表示方面更基础。我们注意到,对这一新层的研究仍处于早期阶段。未来的发展方向包括:1)更好的GPU内存调度,更快的实现;2)更好的设计,以超越先进的卷积方法,如变形卷积[6,36];3)探索其他性质及对其他视觉任务的适用性。

     

     

     

      

    展开全文
  • 深度学习之图像分类(二十九)Sparse-MLP网络详解 目录深度学习之图像分类(二十九)Sparse-MLP网络详解1. 前言2. sMLPNet2.1 整体网络结构2.2 Token-mixing MLP2.3 计算复杂度3. 消融实验4. 反思与总结5. 代码 本文...
  • 图像分类经典论文翻译汇总:[翻译汇总] 翻译pdf文件下载:[下载地址] 此版为纯中文版,中英文对照版请稳步:[ResNet纯中文版] Deep Residual Learning for Image Recognition 深度残差学习的图像识别 ...
  • 图像分类经典论文翻译汇总:[翻译汇总] 翻译pdf文件下载:[下载地址] 此版为纯中文版,中英文对照版请稳步:[ResNet中英文对照版] Deep Residual Learning for Image Recognition 深度残差学习的图像识别...
  • 一、 定义与分类超分辨率复原技术的基本思想是釆用信号处理的方法,在改善图像质量的同时,重建成像系统截止频率之外的信息,从而在不改变硬件设备的前提下,获取高于成像系统分辨率的图像。超分辨率复原的概念广义...
  • 首发于极市平台微信号:图像分类:常用分类网络结构(附论文下载) 作者:TeddyZhang 如有兴趣可以**点击加入极市CV专业微信群**,获取更多高质量干货 本文整理了一般常用的图像特征提取网络,下图是笔者整理的近年...
  • 大家好,我是红色石头!第一个典型的CNN是LeNet5网络,而第一个大放异彩的CNN却是AlexNet。2012年在全球知名的图像识别竞赛 ILSVRC 中,AlexNet 横空出世,直接...
  • 越深的神经网络训练训练起来越困难。本文展示了一个残差学习框架(residual learning framework)能够简化那些比之前更深的训练神经网络。该框架使得输入层来学习残差函数而非原始函数。本文提供了全面的依据说明,...
  • Resnet残差网络学习

    2021-11-05 13:37:05
    动机:深度学习过程中,网络层数增加面临三个问题——计算资源的消耗,梯度消失/爆炸,网络退化。计算资源的消耗问题可以通过GPU集群来解决,梯度消失和爆炸的问题很大程度上已经被标准初始化/中间层正规方法控制了...
  • 主要分类网络性能和参数比较

    千次阅读 2020-10-05 09:29:36
    本文主要比较一些图像分类网络的性能和参数 一、resnet 二、使用步骤 1.引入库 代码如下(示例): import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import ...
  • 深度学习图像分类(十):ResNeXt,ResNest… 文章目录深度学习图像分类(十):ResNeXt,ResNest...前言一、ResNeXt1. Motivation2. Model Architecture3. Why it works?二、ResNeSt1. SKNet2. ResNet 与 ResNeSt...
  • 基于零参考深度曲线估计的暗光图像增强

    千次阅读 热门讨论 2021-11-11 17:35:25
    通常情况下,配对数据是通过自动降光、在数据捕获过程中更改相机设置或通过图像修饰合成数据来彻底收集的。例如,LL-NET和MBLLEN在模拟随机伽马校正的数据上进行训练;在图像采集过程中,通过改变曝光时间和ISO,...
  • 目录SqueezeNet: Squeeze and ExpandFire ModuleSqueezeNetSqueezeNet ...SqueezeNet 的主要模块为 Fire Module,它主要从网络结构优化的角度出发,使用了如下 3 点策略来减少网络参数,提升网络性能: (1) 使用 1×
  • 关于复现的细节作者在论文2.1节中说的很清楚,包括数据预处理的方式和顺序,网络层的初始化方法,迭代次数,学习率变化策略等等。 下面的Table2展示了作者复现的ResNet-50,Inception-V3,MobileNet三个BaseLine。 ...
  • 来源:Tong He Zhi Zhang Hang Zhang Zhongyue Zhang Junyuan Xie Mu L Amazon Web Services fhtong,zhiz,hzaws,zhongyue,junyuanx,mlig@amazon.com ... 摘要 最近在图像分类研究方面取得的许多...
  • 现主要对流行的CNN(卷积神经网络)进行梳理和介绍,涉及到网络的提出背景、如何改进的、网络结构的具体明细以及网络效果等。 本篇是CNN系列之一。 关键词:CNN,LeNet-5,AlexNet,GoogLeNet,VGGNet,BNInception...
  • 图像处理:图像分类算法优化技巧

    千次阅读 2018-12-27 20:02:22
    那么首先要有一个baseline,这个baseline就是作者复现相关算法的结果,这个baseline的复现细节可以参考论文2.1节内容,包括数据预处理的方式和顺序、网络层参数初始化方式、迭代次数、学习率变化策略等,这里不再...
  • 图像 识别算法 分类算法FixEfficientNet is a technique combining two existing techniques: The FixRes from the Facebook AI Team[2] and the EfficientNet [3] first presented from the Google AI Research ...
  • VGG11-19 网络学习笔记

    千次阅读 2020-07-02 19:51:36
    VGG 网络在借鉴前人的基础上,研究了卷积网络深度和精度的关系,使用了3*3 小卷积核进行了实验,使用了16-19 层的卷积网络,并在ILSVRC 2014 比赛中获得定位冠军和分类亚军,并且开源了模型。 ...
  • 倒数第2个层 很多网络架构在倒数第2层有一个输出通道尺寸较大的卷积层。这是为了防止最终分类器的表征瓶颈,但是倒数第2层仍然受到这个问题的困扰。于是作者扩大了倒数第2层的输入通道大小,并替换了ReLU6。 ...
  • 首先看了网络结构、网络组件,对应代码models\common.py。然后看了激活函数,对应代码utils\activations.py。 目录 【1】python 把if 写在一行的两种方式 【2】Python isinstance() 函数 【3】python - 理解...
  • 这篇论文发表于机器学习国际顶级会议ICML2019,作者通过系统地研究发现,仔细平衡网络的深度、宽度和分辨率可以带来更好的性能。因此提出了一种新的缩放方法,即使用简单而高效的**复合系数**来均匀缩放深度、宽度和...
  • 论文提出RepVGG,它仅由3×3卷积和ReLU组成,非常适用于GPU或者专用于推断的...在结构化再参数方法的作用下,该简单的卷积网络在ImageNet上的top-1准确率超过了80%,并且相比SOTA模型,在精度和速度上取得更好权衡。
  • 网络结构搜索之强化学习

    千次阅读 2019-07-30 14:36:26
    设计搜索空间(称之为“NASNet 搜索空间”)使得架构的复杂性与网络的深度和输入图像的大小无关。 引入一种称为 ScheduledDropPath 的新正则化技术,显着改善了 NASNet 模型的泛化能力。 NASNet 搜索空间...
  • [译]基于深度残差学习的图像识别

    万次阅读 多人点赞 2016-09-07 01:21:39
    [译]基于深度残差学习的图像识别(Deep Residual Learning for Image Recognition) 摘要:神经网络的训练因其层次加深而变得愈加困难。我们所提出的残差学习框架可以更轻松的对比前人所提深很多的网络进行训练。相...
  • 直观来讲,如果图像尺寸变大,复合的缩放方法会很有意义,因为当图像尺寸变大意味着网络需要更多层来增加接受野,同时需要更多的通道来捕捉更大图像上更多细粒度的模式信息。事实上,以前的理论和实证结果两者表明...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 762
精华内容 304
关键字:

图像尺寸改变网络的flops怎么变化