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`卷积将输出与深度卷积相结合。
1137 0
MobileNetV3架构解析与代码复现
|
机器学习/深度学习 编解码 TensorFlow
MnasNet架构解析与复现-神经架构搜索
为移动设备设计卷积神经网络 (CNN) 具有挑战性,因为移动模型需要小而快,但仍要准确。尽管在所有维度上都致力于设计和改进移动 CNN,但当需要考虑如此多的架构可能性时,很难手动平衡这些权衡。在本文中,我们提出了一种**自动移动神经架构搜索 (MNAS) 方法**,该方法明确地将模型延迟纳入主要目标,以便搜索可以识别出在准确性和延迟之间取得良好折衷的模型。与之前的工作不同,延迟是通过另一个通常不准确的代理(例如 FLOPS)来考虑的,我们的方法通过在手机上执行模型来直接测量现实世界的推理延迟。为了进一步在灵活性和搜索空间大小之间取得适当的平衡,我们**提出了一种新颖的分解层次搜索空间,它鼓励整
568 0
MnasNet架构解析与复现-神经架构搜索
|
机器学习/深度学习 TensorFlow API
EffiecientNetV2架构复现--CVPR2021
这篇文章介绍了EfficientNetV2,与以前的模型相比,它具有更快的训练速度和更好的参数效率。为了开发这些模型,我们结合使用训练感知神经架构搜索和缩放,共同优化训练速度和参数效率。这些模型是从富含新操作(如 Fused-MBConv)的搜索空间中搜索的。我们的实验表明,EfficientNetV2 模型的训练速度比最先进的模型快得多,同时体积缩小了 6.8 倍。
528 0
EffiecientNetV2架构复现--CVPR2021
|
机器学习/深度学习 TensorFlow 算法框架/工具
GhostNet架构复现--CVPR2020
由于内存和计算资源有限,在嵌入式设备上部署卷积神经网络 (CNN) 很困难。特征图中的冗余是那些成功的 CNN 的一个重要特征,但在神经架构设计中很少被研究。**本文提出了一种新颖的 Ghost 模块,可以从廉价的操作中生成更多的特征图。基于一组内在特征图,我们应用一系列成本低廉的线性变换来生成许多ghost特征图,这些特征图可以充分揭示内在特征的信息。所提出的 Ghost 模块可以作为一个即插即用的组件来升级现有的卷积神经网络。 Ghost 瓶颈旨在堆叠 Ghost 模块,然后可以轻松建立轻量级的 GhostNet。**
238 0
GhostNet架构复现--CVPR2020
|
编解码 数据挖掘 算法框架/工具
ResNet-RS架构复现--CVPR2021
我们的工作重新审视了规范的 ResNet (He et al., 2015),并研究了这三个方面,以试图解开它们。也许令人惊讶的是,我们发现训练和扩展策略可能比架构变化更重要,而且由此产生的 ResNet 与最近最先进的模型相匹配。**我们展示了表现最佳的缩放策略取决于训练方案,并提供了两种新的缩放策略:(1)在可能发生过度拟合的情况下缩放模型深度(否则宽度缩放更可取); (2) 提高图像分辨率的速度比之前推荐的要慢(Tan & Le,2019)**。使用改进的训练和扩展策略,我们设计了一系列 ResNet 架构 **ResNet-RS**,它比 TPU 上的 EfficientNets 快
502 0
ResNet-RS架构复现--CVPR2021
|
25天前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
1月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
44 3
|
1月前
|
Cloud Native 安全 数据安全/隐私保护
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####
|
24天前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
144 68
从单体到微服务:如何借助 Spring Cloud 实现架构转型
|
26天前
|
设计模式 负载均衡 监控
探索微服务架构下的API网关设计
在微服务的大潮中,API网关如同一座桥梁,连接着服务的提供者与消费者。本文将深入探讨API网关的核心功能、设计原则及实现策略,旨在为读者揭示如何构建一个高效、可靠的API网关。通过分析API网关在微服务架构中的作用和挑战,我们将了解到,一个优秀的API网关不仅要处理服务路由、负载均衡、认证授权等基础问题,还需考虑如何提升系统的可扩展性、安全性和可维护性。文章最后将提供实用的代码示例,帮助读者更好地理解和应用API网关的设计概念。
58 8

热门文章

最新文章