RegNet架构复现--CVPR2020

简介: 在这项工作中,我们**提出了一种新的网络设计范式**。我们的目标是帮助促进对网络设计的理解,并发现跨环境通用的设计原则。我们不是专注于设计单个网络实例,而是设计参数化网络群体的网络设计空间。整个过程类似于经典的网络手动设计,但提升到了设计空间级别。使用我们的方法,我们探索了网络设计的结构方面,并**得出了一个由简单、规则的网络组成的低维设计空间,我们称之为** ==RegNet==。
参考论文:Designing Network Design Spaces

作者:Ilija Radosavovic, Raj Prateek Kosaraju, Ross Girshick, ==Kaiming He==, Piotr Dollár

我看了下,这个有两篇论文,一篇是Designing Network Design Spaces,另一篇是Fast and Accurate Model Scaling,这里只说第一篇论文里面的架构,第二篇等我看完论文再说。

1、摘要

  在这项工作中,我们提出了一种新的网络设计范式。我们的目标是帮助促进对网络设计的理解,并发现跨环境通用的设计原则。我们不是专注于设计单个网络实例,而是设计参数化网络群体的网络设计空间。整个过程类似于经典的网络手动设计,但提升到了设计空间级别。使用我们的方法,我们探索了网络设计的结构方面,并得出了一个由简单、规则的网络组成的低维设计空间,我们称之为 ==RegNet==。
   RegNet 参数化的核心见解非常简单:好的网络的宽度和深度可以用一个量化的线性函数来解释。我们分析了 RegNet 设计空间并得出了与当前网络设计实践不匹配的有趣发现。 RegNet 设计空间提供了简单而快速的网络,可以在各种翻牌制度中很好地工作。在可比较的训练设置和失败情况下,RegNet 模型优于流行的 EfficientNet 模型,同时在 GPU 上的速度提高了 5 倍

2、RegNet性能

image-20220904203036832

  这是一些移动网络模型的性能比较,可以看到,在top-1错误率上面,RegNet和MobileNet、ShuffleNet还是很有竞争力的。

  与ResNet和ResNext比较:

image-20220904203351168

   表3 RESNE(X)T 比较。 (a) 按激活分组,REGNETX 显示出可观的收益(请注意,对于每组 GPU 推理和训练时间是相似的)。 (b) REGNETX 模型在固定触发器下也优于 RESNE(X)T 模型。

  与EfficientNet比较:

image-20220904203505601

  在可比较的训练设置下,REGNETY 在大多数失败状态下的表现都优于 EFFICIENTNET。此外,REGNET 模型要快得多,例如,REGNETX-F8000 比 EFFICIENTNET-B5 快约 5 倍。

3、RegNet网络结构

3.1 General Network structure

image-20220904203711964

  图 3. 我们设计空间中模型的一般网络结构。

   (a) 每个网络由一个主干(stride-two 3×3 conv with w0 = 32 output channels),然后是执行大部分计算的网络主体,然后是一个头(平均池化,然后是一个全连接层)预测 n 个输出类别。

   (b) 网络主体由一系列阶段组成,这些阶段以逐渐降低的分辨率 $r_i$运行。

   (c) 每个阶段都由一系列相同的块组成,除了第一个块使用 stride-2 conv。虽然一般结构很简单,但可能的网络配置的总数是巨大的。

  其中stem就是一个普通的卷积层(后跟BN+ReLU),卷积核大小为3x3stride=2,卷积核个数为32。

image-20220904203954782

  其中body就是由4个stage堆叠组成,如图(b)所示。每经过一个stage都会将输入特征矩阵的height和width缩减为原来的一半

  而每个stage又是由一系列block堆叠组成,每个stage的第一个block中存在步距为2的组卷积(主分支上)和普通卷积(捷径分支上),剩下的block中的卷积步距都是1,和ResNet类似。

  其中head就是分类网络中常见的分类器,由一个全局平均池化层和全连接层构成

3.2 RegNet Block

  参考:RegNet网络结构与搭建

image-20220904204416032

  图 4. X 块基于具有组卷积的标准残差瓶颈块 [31]。

  (a) 每个 X 块由一个 1×1 卷积、一个 3×3 组卷积和一个最终的 1×1 卷积组成,其中 1×1 卷积会改变通道宽度。conv后跟BN+ReLU。该块有 3 个参数:宽度 wi、瓶颈比 bi 和组宽度 gi。

  (b) stride=2的版本。

  shortcut捷径分支上当stride=1时不做任何处理,当stride=2时通过一个1x1的卷积(包括bn)进行下采样。

  图中的r代表分辨率简单理解为特征矩阵的高、宽,当步距s等于1时,输入输出的r保持不变,当s等于2时,输出的r为输入的一半。

  w代表特征矩阵的channel(注意当s=2时,输入的是$w_{i-1}$,输出的是$w_i$即channel会发生变化。

  g代表分组卷积每个group的group width。

  b代表bottleneck ratio即输出特征矩阵的channel缩减为输入特征矩阵channel的$\frac{1}{b} $

  作者后来在实验中发现当b=1的时候效果最好。

  论文中有RegNetX和RegNetY,两者的区别仅在于RegNetY在block中的Group Conv后接了个SE(Squeeze-and-Excitation)模块。

3.3 SE注意力机制

  SENet架构-通道注意力机制

image-20220816114225350

  SENet的具体实现如下:

  • 对输入进来的特征层进行全局平均池化。
  • 然后进行两次全连接(这两个全连接可用1*1卷积代替),第一次全连接神经元个数较少,第二次全连接神经元个数和输入特征层个数相同。
  • 在完成两次全连接之后,再取一次sigmoid讲值固定到0-1之间,此时我们获得了输入特征层每一个通道的权值(0-1之间)。
  • 在获得这个权值之后,讲这个权值与原输入特征层相乘即可。

  在RegNet中,全连接层1(FC1)的节点个数是等于输入该block的特征矩阵channel的四分之一(不是Group Conv输出特征矩阵channel的四分之一),并且激活函数是ReLU全连接层2(FC2)的节点个数是等于Group Conv输出特征矩阵的channel,并且激活函数是Sigmoid。

4、RegNet代码复现:

  模型的命名如下:RegNet<block_type><flops>where block_type是其中之一(X, Y)flops表示亿次浮点运算。例如 RegNetY064 对应于具有 Y 块和 6.4 giga flop(64 亿次 flop)的 RegNet。
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Model

4.1 模型参数配置

MODEL_CONFIGS = {
    "x002": {
        "depths": [1, 1, 4, 7],
        "widths": [24, 56, 152, 368],
        "group_width": 8,
        "default_size": 224,
        "block_type": "X"
    },
    "x004": {
        "depths": [1, 2, 7, 12],
        "widths": [32, 64, 160, 384],
        "group_width": 16,
        "default_size": 224,
        "block_type": "X"
    },
    "x006": {
        "depths": [1, 3, 5, 7],
        "widths": [48, 96, 240, 528],
        "group_width": 24,
        "default_size": 224,
        "block_type": "X"
    },
    "x008": {
        "depths": [1, 3, 7, 5],
        "widths": [64, 128, 288, 672],
        "group_width": 16,
        "default_size": 224,
        "block_type": "X"
    },
    "x016": {
        "depths": [2, 4, 10, 2],
        "widths": [72, 168, 408, 912],
        "group_width": 24,
        "default_size": 224,
        "block_type": "X"
    },
    "x032": {
        "depths": [2, 6, 15, 2],
        "widths": [96, 192, 432, 1008],
        "group_width": 48,
        "default_size": 224,
        "block_type": "X"
    },
    "x040": {
        "depths": [2, 5, 14, 2],
        "widths": [80, 240, 560, 1360],
        "group_width": 40,
        "default_size": 224,
        "block_type": "X"
    },
    "x064": {
        "depths": [2, 4, 10, 1],
        "widths": [168, 392, 784, 1624],
        "group_width": 56,
        "default_size": 224,
        "block_type": "X"
    },
    "x080": {
        "depths": [2, 5, 15, 1],
        "widths": [80, 240, 720, 1920],
        "group_width": 120,
        "default_size": 224,
        "block_type": "X"
    },
    "x120": {
        "depths": [2, 5, 11, 1],
        "widths": [224, 448, 896, 2240],
        "group_width": 112,
        "default_size": 224,
        "block_type": "X"
    },
    "x160": {
        "depths": [2, 6, 13, 1],
        "widths": [256, 512, 896, 2048],
        "group_width": 128,
        "default_size": 224,
        "block_type": "X"
    },
    "x320": {
        "depths": [2, 7, 13, 1],
        "widths": [336, 672, 1344, 2520],
        "group_width": 168,
        "default_size": 224,
        "block_type": "X"
    },
    "y002": {
        "depths": [1, 1, 4, 7],
        "widths": [24, 56, 152, 368],
        "group_width": 8,
        "default_size": 224,
        "block_type": "Y"
    },
    "y004": {
        "depths": [1, 3, 6, 6],
        "widths": [48, 104, 208, 440],
        "group_width": 8,
        "default_size": 224,
        "block_type": "Y"
    },
    "y006": {
        "depths": [1, 3, 7, 4],
        "widths": [48, 112, 256, 608],
        "group_width": 16,
        "default_size": 224,
        "block_type": "Y"
    },
    "y008": {
        "depths": [1, 3, 8, 2],
        "widths": [64, 128, 320, 768],
        "group_width": 16,
        "default_size": 224,
        "block_type": "Y"
    },
    "y016": {
        "depths": [2, 6, 17, 2],
        "widths": [48, 120, 336, 888],
        "group_width": 24,
        "default_size": 224,
        "block_type": "Y"
    },
    "y032": {
        "depths": [2, 5, 13, 1],
        "widths": [72, 216, 576, 1512],
        "group_width": 24,
        "default_size": 224,
        "block_type": "Y"
    },
    "y040": {
        "depths": [2, 6, 12, 2],
        "widths": [128, 192, 512, 1088],
        "group_width": 64,
        "default_size": 224,
        "block_type": "Y"
    },
    "y064": {
        "depths": [2, 7, 14, 2],
        "widths": [144, 288, 576, 1296],
        "group_width": 72,
        "default_size": 224,
        "block_type": "Y"
    },
    "y080": {
        "depths": [2, 4, 10, 1],
        "widths": [168, 448, 896, 2016],
        "group_width": 56,
        "default_size": 224,
        "block_type": "Y"
    },
    "y120": {
        "depths": [2, 5, 11, 1],
        "widths": [224, 448, 896, 2240],
        "group_width": 112,
        "default_size": 224,
        "block_type": "Y"
    },
    "y160": {
        "depths": [2, 4, 11, 1],
        "widths": [224, 448, 1232, 3024],
        "group_width": 112,
        "default_size": 224,
        "block_type": "Y"
    },
    "y320": {
        "depths": [2, 5, 12, 1],
        "widths": [232, 696, 1392, 3712],
        "group_width": 232,
        "default_size": 224,
        "block_type": "Y"
    },
}
  这里只演示RegNetX002和RegNetY002。其他的无非就是改下参数而已。

4.2 PreStem预处理层

# 将输入重新缩放并归一化为[0,1]和ImageNet均值和std
def PreStem(x, name=None):
    x = layers.experimental.preprocessing.Rescaling(1. / 255.)(x)
    return x
   这里我的tensorflow版本太低,高版本直接使用layers.Rescaling()即可

4.3 Stem

   论文中的stem(stride=2 3x3卷积+w0 = 32 output channels)

  stem就是一个普通的卷积层(默认包含bn以及relu),卷积核大小为3x3,步距为2,卷积核个数为32。

def Stem(x, name=None):
    x = layers.Conv2D(32,
                      (3, 3),
                      strides=2,
                      use_bias=False,
                      padding='same',
                      kernel_initializer='he_normal',
                      name=name + '_stem_conv')(x)
    x = layers.BatchNormalization(
        momentum=0.9, epsilon=1e-5, name=name + "_stem_bn")(x)
    x = layers.ReLU(name=name + '_stem_relu')(x)
    return x

4.4 Se注意力机制模块

def SqueezeAndExciteBlock(inputs, filters_in, se_filters, name=None):
    # 获得通道数
    channel=inputs.shape[-1]
    x = layers.GlobalAveragePooling2D(name=name + '_squeeze_and_excite_gap')(inputs)

    x=layers.Reshape((1,1,channel))(x)

    # 两个全连接层(目前看到的所有源码都是使用两个1x1卷积层代替)
    x = layers.Conv2D(filters=se_filters,
                      kernel_size=(1, 1),
                      activation='relu',
                      kernel_initializer='he_normal',
                      name=name + '_squeeze_and_excite_squeeze')(x)

    x = layers.Conv2D(filters=filters_in,
                      kernel_size=(1, 1),
                      activation='sigmoid',
                      kernel_initializer='he_normal',
                      name=name + '_squeeze_and_excite')(x)
    x = layers.multiply([x, inputs])
    return x
  关于通道的缩放比在Block写着,ratio=0.25

4.5 XBlock实现

  XBlock实现:1x1卷积+3x3分组卷积+1x1卷积(conv后跟BN+ReLU)

def XBlock(inputs, filters_in, filters_out, group_width, stride=1, name=None):
    # declare layers
    groups = filters_out // group_width
    # 当stide=2的时候,残差边需要使用1x1卷积降维处理保持shape一致
    if stride != 1:
        skip = layers.Conv2D(
            filters_out,
            (1, 1),
            strides=stride,
            use_bias=False,
            kernel_initializer='he_normal',
            name=name + '_skip_1x1')(inputs)
        skip = layers.BatchNormalization(
            momentum=0.9, epsilon=1e-5, name=name + "_skip_bn")(skip)
    else:
        skip = inputs

    # build block
    # conv_1x1_1
    x = layers.Conv2D(
        filters_out,
        (1, 1),
        use_bias=False,
        kernel_initializer='he_normal',
        name=name + '_conv_1x1_1')(inputs)
    x = layers.BatchNormalization(
        momentum=0.9, epsilon=1e-5, name=name + "_conv_1x1_1_bn")(x)
    x = layers.ReLU(name=name + "_conv_1x1_1_relu")(x)

    # group conv_3x3
    x = layers.Conv2D(
        filters_out,
        (3, 3),
        use_bias=False,
        strides=stride,
        groups=groups,
        padding='same',
        kernel_initializer='he_normal',
        name=name + '_conv_3x3')(x)
    x = layers.BatchNormalization(momentum=0.9, epsilon=1e-5, name=name + "_conv_3x3_bn")(x)
    x = layers.ReLU(name=name + "_conv_3x3_relu")(x)

    # conv_1x1_2
    x = layers.Conv2D(
        filters_out, (1, 1),
        use_bias=False,
        kernel_initializer="he_normal",
        name=name + "_conv_1x1_2")(x)
    x = layers.BatchNormalization(momentum=0.9, epsilon=1e-5, name=name + "_conv_1x1_2_bn")(x)

    x = layers.ReLU(name=name + "_exit_relu")(x + skip)
    return x

4.6 YBlock实现

  YBlock实现:1x1卷积+3x3分组卷积+SE注意力机制+1x1卷积(conv后跟BN+ReLU)

def YBlock(inputs,
           filters_in,
           filters_out,
           group_width,
           stride=1,
           squeeze_excite_ratio=0.25,
           name=None):
    groups = filters_out // group_width
    se_filters = int(filters_in * squeeze_excite_ratio)

    if stride != 1:
        skip = layers.Conv2D(filters_out,
                             (1, 1),
                             strides=stride,
                             use_bias=False,
                             kernel_initializer="he_normal",
                             name=name + "_skip_1x1")(inputs)
        skip = layers.BatchNormalization(momentum=0.9, epsilon=1e-5, name=name + "_skip_bn")(skip)
    else:
        skip = inputs

    # Build Block
    # conv_1x1_1
    x = layers.Conv2D(filters_out, (1, 1),
                      use_bias=False,
                      kernel_initializer="he_normal",
                      name=name + "_conv_1x1_1")(inputs)
    x = layers.BatchNormalization(momentum=0.9, epsilon=1e-5, name=name + "_conv_1x1_1_bn")(x)
    x = layers.ReLU(name=name + "_conv_1x1_1_relu")(x)

    # conv_3x3
    x = layers.Conv2D(
        filters_out, (3, 3),
        use_bias=False,
        strides=stride,
        groups=groups,
        padding="same",
        kernel_initializer="he_normal",
        name=name + "_conv_3x3")(x)
    x = layers.BatchNormalization(momentum=0.9, epsilon=1e-5, name=name + "_conv_3x3_bn")(x)
    x = layers.ReLU(name=name + "_conv_3x3_relu")(x)

    # SE注意力机制模块
    x = SqueezeAndExciteBlock(x, filters_out, se_filters, name=name)

    # conv_1x1_2
    x = layers.Conv2D(filters_out,
                      (1, 1),
                      use_bias=False,
                      kernel_initializer="he_normal",
                      name=name + "_conv_1x1_2")(x)
    x = layers.BatchNormalization(momentum=0.9, epsilon=1e-5, name=name + "_conv_1x1_2_bn")(x)
    x = layers.ReLU(name=name + "_exit_relu")(x + skip)
    return x

4.7 Block块的堆叠

def Stage(inputs,
          block_type,  # 必须是X、Y、Z之一
          depth,  # stage深度,要使用的块数
          group_width,  # 本stage所有块的group宽度
          filters_in,  #
          filters_out,
          name=None):  # 名称前缀
    x = inputs
    if block_type == "X":
        # 论文原话:Stage的第一个block的步长为2
        x = XBlock(
            x,
            filters_in,
            filters_out,
            group_width,
            stride=2,
            name=f"{name}_XBlock_0")
        for i in range(1, depth):
            x = XBlock(x, filters_out, filters_out, group_width, name=f"{name}_XBlock_{i}")
    elif block_type== "Y":
        x=YBlock(x,filters_in,filters_out,group_width,stride=2,name=name+'_YBlock_0')
        for i in range(1,depth):
            x=YBlock(x,filters_out,filters_out,group_width,name=f"{name}_YBlock_{i}")
    # TODO ZBlock

    return x
  这里还有一个ZBlock没有实现,那个是另一篇论文的,我看完再发。

  注意:每个Stage的第一个Block的stride=2

4.8 分类头部分(Head)

def Head(x, num_classes=1000, name=None):
    x = layers.GlobalAveragePooling2D(name=name + '_head_gap')(x)
    x = layers.Dense(num_classes, name=name + 'head_dense')(x)
    return x

4.9 RegNet骨干搭建

def RegNet(depths,  # 每个stage的深度
           widths,  # 块宽度(输出通道数)
           group_width,  # 每组中要使用的通道数
           block_type,  # "X","Y","Z"之一
           default_size,  # 默认输入图像大小
           model_name='regnet',  # 模型的可选名称
           include_preprocessing=True,  # 是否包含预处理
           include_top=True,  # 是否包含分类头
           weights='imagenet',
           input_tensor=None,
           input_shape=None,
           pooling=None,
           classes=1000,  # 可选的类数量
           classifier_activation='softmax'):  # 分类器激活
    img_input = layers.Input(shape=input_shape)
    inputs = img_input

    x = inputs

    if include_preprocessing:
        x = PreStem(x, name=model_name)
    x = Stem(x, name=model_name)

    in_channels = 32  # Output from Stem

    for num_stage in range(4):
        depth = depths[num_stage]
        out_channels = widths[num_stage]

        x = Stage(x,
                  block_type,
                  depth,
                  group_width,
                  in_channels,
                  out_channels,
                  name=model_name + '_Stage_' + str(num_stage))
        in_channels = out_channels

    if include_top:
        x = Head(x, num_classes=classes, name='head')
    else:
        if pooling == 'avg':
            x = layers.GlobalAveragePooling2D()(x)
        elif pooling == 'max':
            x = layers.GlobalMaxPooling2D()(x)
    model = Model(inputs=inputs, outputs=x, name=model_name)

    return model
   for num_stage in range(4),这里之所以遍历四次,是因为原论文中body部分只有4个stage,看原论文图3你就明白了。

4.10 RegNetX002模型

def RegNetX002(model_name='regnetx002',
               include_top=True,
               include_preprocessing=True,
               weights='imagenet',
               input_tensor=None,
               input_shape=None,
               pooling=None,
               classes=1000,
               classifier_activation='softmax'):
    return RegNet(
        MODEL_CONFIGS['x002']['depths'],
        MODEL_CONFIGS['x002']['widths'],
        MODEL_CONFIGS['x002']['group_width'],
        MODEL_CONFIGS['x002']['block_type'],
        MODEL_CONFIGS['x002']['default_size'],
        model_name=model_name,
        include_top=include_top,
        include_preprocessing=include_preprocessing,
        weights=weights,
        input_tensor=input_tensor,
        input_shape=input_shape,
        pooling=pooling,
        classes=classes,
        classifier_activation=classifier_activation
    )
if __name__ == '__main__':
    model = RegNetX002(input_shape=(224, 224, 3))
    model.summary()

image-20220904214420198

  图太长了,只能截一部份

4.11 RegNetY002模型

def RegNetY002(model_name="regnety002",
               include_top=True,
               include_preprocessing=True,
               weights="imagenet",
               input_tensor=None,
               input_shape=None,
               pooling=None,
               classes=1000,
               classifier_activation="softmax"):
  return RegNet(
      MODEL_CONFIGS["y002"]["depths"],
      MODEL_CONFIGS["y002"]["widths"],
      MODEL_CONFIGS["y002"]["group_width"],
      MODEL_CONFIGS["y002"]["block_type"],
      MODEL_CONFIGS["y002"]["default_size"],
      model_name=model_name,
      include_top=include_top,
      include_preprocessing=include_preprocessing,
      weights=weights,
      input_tensor=input_tensor,
      input_shape=input_shape,
      pooling=pooling,
      classes=classes,
      classifier_activation=classifier_activation)

image-20220904214528342

  到此,RegNetX与RegNetY模型就搭建完了。

Reference

Designing Network Design Spaces

SENet架构-通道注意力机制

https://www.tensorflow.org/api_docs/python/tf/keras/applications/regnet/RegNetX002

https://github.com/keras-team/keras/blob/v2.9.0/keras/applications/regnet.py#L1245-L1270

RegNet网络结构与搭建

目录
相关文章
|
机器学习/深度学习 编解码 TensorFlow
MobileNetV3架构解析与代码复现
MobileNet模型基于深度可分离卷积,这是一种分解卷积的形式,将标准卷积分解为深度卷积和`1*1`的点卷积。对于MobileNet,深度卷积将单个滤波器应用于每个输入通道,然后,逐点卷积应用`1*1`卷积将输出与深度卷积相结合。
1058 0
MobileNetV3架构解析与代码复现
|
机器学习/深度学习 编解码 TensorFlow
MnasNet架构解析与复现-神经架构搜索
为移动设备设计卷积神经网络 (CNN) 具有挑战性,因为移动模型需要小而快,但仍要准确。尽管在所有维度上都致力于设计和改进移动 CNN,但当需要考虑如此多的架构可能性时,很难手动平衡这些权衡。在本文中,我们提出了一种**自动移动神经架构搜索 (MNAS) 方法**,该方法明确地将模型延迟纳入主要目标,以便搜索可以识别出在准确性和延迟之间取得良好折衷的模型。与之前的工作不同,延迟是通过另一个通常不准确的代理(例如 FLOPS)来考虑的,我们的方法通过在手机上执行模型来直接测量现实世界的推理延迟。为了进一步在灵活性和搜索空间大小之间取得适当的平衡,我们**提出了一种新颖的分解层次搜索空间,它鼓励整
541 0
MnasNet架构解析与复现-神经架构搜索
|
机器学习/深度学习 TensorFlow API
EffiecientNetV2架构复现--CVPR2021
这篇文章介绍了EfficientNetV2,与以前的模型相比,它具有更快的训练速度和更好的参数效率。为了开发这些模型,我们结合使用训练感知神经架构搜索和缩放,共同优化训练速度和参数效率。这些模型是从富含新操作(如 Fused-MBConv)的搜索空间中搜索的。我们的实验表明,EfficientNetV2 模型的训练速度比最先进的模型快得多,同时体积缩小了 6.8 倍。
516 0
EffiecientNetV2架构复现--CVPR2021
|
机器学习/深度学习 TensorFlow 算法框架/工具
GhostNet架构复现--CVPR2020
由于内存和计算资源有限,在嵌入式设备上部署卷积神经网络 (CNN) 很困难。特征图中的冗余是那些成功的 CNN 的一个重要特征,但在神经架构设计中很少被研究。**本文提出了一种新颖的 Ghost 模块,可以从廉价的操作中生成更多的特征图。基于一组内在特征图,我们应用一系列成本低廉的线性变换来生成许多ghost特征图,这些特征图可以充分揭示内在特征的信息。所提出的 Ghost 模块可以作为一个即插即用的组件来升级现有的卷积神经网络。 Ghost 瓶颈旨在堆叠 Ghost 模块,然后可以轻松建立轻量级的 GhostNet。**
224 0
GhostNet架构复现--CVPR2020
|
编解码 数据挖掘 算法框架/工具
ResNet-RS架构复现--CVPR2021
我们的工作重新审视了规范的 ResNet (He et al., 2015),并研究了这三个方面,以试图解开它们。也许令人惊讶的是,我们发现训练和扩展策略可能比架构变化更重要,而且由此产生的 ResNet 与最近最先进的模型相匹配。**我们展示了表现最佳的缩放策略取决于训练方案,并提供了两种新的缩放策略:(1)在可能发生过度拟合的情况下缩放模型深度(否则宽度缩放更可取); (2) 提高图像分辨率的速度比之前推荐的要慢(Tan & Le,2019)**。使用改进的训练和扩展策略,我们设计了一系列 ResNet 架构 **ResNet-RS**,它比 TPU 上的 EfficientNets 快
478 0
ResNet-RS架构复现--CVPR2021
|
8天前
|
弹性计算 Kubernetes Cloud Native
云原生架构下的微服务设计原则与实践####
本文深入探讨了在云原生环境中,微服务架构的设计原则、关键技术及实践案例。通过剖析传统单体架构面临的挑战,引出微服务作为解决方案的优势,并详细阐述了微服务设计的几大核心原则:单一职责、独立部署、弹性伸缩和服务自治。文章还介绍了容器化技术、Kubernetes等云原生工具如何助力微服务的高效实施,并通过一个实际项目案例,展示了从服务拆分到持续集成/持续部署(CI/CD)流程的完整实现路径,为读者提供了宝贵的实践经验和启发。 ####
|
5天前
|
监控 安全 应用服务中间件
微服务架构下的API网关设计策略与实践####
本文深入探讨了在微服务架构下,API网关作为系统统一入口点的设计策略、实现细节及其在实际应用中的最佳实践。不同于传统的摘要概述,本部分将直接以一段精简的代码示例作为引子,展示一个基于NGINX的简单API网关配置片段,随后引出文章的核心内容,旨在通过具体实例激发读者兴趣,快速理解API网关在微服务架构中的关键作用及实现方式。 ```nginx server { listen 80; server_name api.example.com; location / { proxy_pass http://backend_service:5000;
|
7天前
|
缓存 监控 API
探索微服务架构中的API网关模式
随着微服务架构的兴起,API网关成为管理和服务间交互的关键组件。本文通过在线零售公司的案例,探讨了API网关在路由管理、认证授权、限流缓存、日志监控和协议转换等方面的优势,并详细介绍了使用Kong实现API网关的具体步骤。
24 3
|
8天前
|
运维 NoSQL Java
后端架构演进:微服务架构的优缺点与实战案例分析
【10月更文挑战第28天】本文探讨了微服务架构与单体架构的优缺点,并通过实战案例分析了微服务架构在实际应用中的表现。微服务架构具有高内聚、低耦合、独立部署等优势,但也面临分布式系统的复杂性和较高的运维成本。通过某电商平台的实际案例,展示了微服务架构在提升系统性能和团队协作效率方面的显著效果,同时也指出了其带来的挑战。
44 4
|
7天前
|
存储 缓存 监控
探索微服务架构中的API网关模式
探索微服务架构中的API网关模式
24 2
下一篇
无影云桌面