主頁 >  其他 > 深度學習之影像分類(十五)-- EfficientNetV1 網路結構

深度學習之影像分類(十五)-- EfficientNetV1 網路結構

2021-09-06 09:37:28 其他

深度學習之影像分類(十五)EfficientNetV1 網路結構

目錄

    • 深度學習之影像分類(十五)EfficientNetV1 網路結構
      • 1. 前言
      • 2. 寬度,深度以及解析度
      • 3. EfficientNetV1 網路結構
      • 4. 代碼

本節學習 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=1s??FiLi??(X?Hi?,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)

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/297937.html

標籤:其他

上一篇:學習Opencv+Python之檔案矯OCR

下一篇:使用手機攝像頭做網路ip攝像頭用opencv中打開

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more