【问题标题】:How to reproduce the Bottleneck Blocks in Mobilenet V3 with Keras API?如何使用 Keras API 重现 Mobilenet V3 中的瓶颈块?
【发布时间】:2020-04-19 10:24:21
【问题描述】:

使用 Keras API,我正在尝试按照本文中的说明编写 MobilenetV3:https://arxiv.org/pdf/1905.02244.pdf,其架构如下图所述:

为此,我需要实现上一篇文章https://arxiv.org/pdf/1801.04381.pdf 中的bottloneck_blocks。架构见图片:

我设法将 Initial 和 final Conv 层粘合在一起:


from tensorflow.keras.layers import Input, Conv2D, Add, AvgPool2D, UpSampling2D


first_input = Input(shape=(256, 256, 3))
firt_conv   = Conv2D(16,3, strides=2, name="FirstConv2d", padding="same")(first_input)

bneck1  = add_bottleneck_block(firt_conv, 16, 16)
bneck2  = add_bottleneck_block(bneck1, 64, 24, strides=2)

#... Skiping all the other BottleNeck Blocks for simplicity 

lastBneck      = add_bottleneck_block(second2LastBneck, 960, 160, bneck_depth=5)
middleConv     = Conv2D(160, 1 , strides=1, name="MiddleConv", )(bneck3)
pool7          = AvgPool2D(7, strides=1, padding='same', name="7x7Pool")(middleConv)
SecondLastConv = Conv2D(1280, 1, strides=1, name="SecondLastConv")(pool7)
lastConv       = Conv2D(3,1, strides=1, name="lastConv1x1")(SecondLastConv)
upScale        = UpSampling2D(2)(lastConv) # This layer is application specific for my training.


v3 = tf.keras.models.Model(inputs=[first_input], outputs=upScale)

v3.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(),)
v3.summary()

bottleneck_block 在下一个 sn-p 代码中给出(修改自 https://towardsdatascience.com/mobilenetv2-inverted-residuals-and-linear-bottlenecks-8a4362f4ffd5

def bottleneck_block(x, expand=64, squeeze=16, strides=1, bneck_depth=3):
  """
  Bottleneck block with Activation and batch normalization commented since
  I don't believe this is the issue in my problem
  """
  m = tf.keras.layers.Conv2D(expand, (1,1), strides=1)(x)
  #m = tf.keras.layers.BatchNormalization()(m)
  #m = tf.keras.layers.Activation('relu6')(m)
  m = tf.keras.layers.DepthwiseConv2D(bneck_depth, padding='same', strides=strides)(m)
  #m = tf.keras.layers.BatchNormalization()(m)
  #m = Activation('relu6')(m)
  m = tf.keras.layers.Conv2D(squeeze, (1,1), strides=1)(m)
  #m = tf.keras.layers.BatchNormalization()(m)
  return tf.keras.layers.Add()([m, x])

但是,在bneck2 中,我收到以下错误:

ValueError: Operands could not be broadcast together with shapes (16, 16, 24) (128, 128, 16)

我知道这个错误意味着输入和输出的维度是关闭的,但我不知道如何修复它以将网络构建为 MobileNetV3。

我在这里缺少什么?

作为参考,这里是同一网络的 tensorflow repo 中的源代码:https://github.com/tensorflow/models/blob/a174bf5b1db0e2c1e04697ff5aae5182bd1c60e7/research/slim/nets/mobilenet/mobilenet_v3.py#L130

【问题讨论】:

    标签: python tensorflow machine-learning keras deep-learning


    【解决方案1】:

    在你的瓶颈层中,有 Add()。

    现在,Add 期望两个具有相同形状的张量。但是,由于您在运行此行时跳过了很多层,tf.keras.layers.Add()([m, x]) - m 和 x 具有不同的维度。

    因此,要么设计一个层数更少的小型网络,要么只实现所有中间层。

    【讨论】:

    • 是的,我知道 Add 会引发错误,但是 MobileNet 怎么做呢?
    • 网络在设计时考虑了所有内部形状,因此您必须遵循完整的架构或在形状一致的情况下自行设计。
    • 我明白这一点,但是如何像示例中那样保持瓶颈 1 和 2 之间的形状?如果我不应该使用 Add,那么我应该如何设计瓶颈块?
    【解决方案2】:

    解决方法是修改bottleneck_block,如V3 author's repo中所述:

    import tensorflow as tf
    def bottleneck_block(x, expand=64, squeeze=16, strides=1, bneck_depth=3, se=False):
      """
      se stands for squeeze_excite
      """
    
      m = tf.keras.layers.Conv2D(expand, (1,1), strides=1)(x)
      m = tf.keras.layers.BatchNormalization()(m)
      #m = tf.keras.layers.Activation('relu6')(m)
      m = tf.keras.layers.DepthwiseConv2D(bneck_depth, padding='same', strides=strides)(m)
      m = tf.keras.layers.BatchNormalization()(m)
      #m = Activation('relu6')(m)
      if se:
        m = squeeze_excite_block(m, ratio=4)
      m = tf.keras.layers.Conv2D(squeeze, (1,1), strides=1, padding='same')(m)
      m = tf.keras.layers.BatchNormalization()(m)
    
      if (
        # stride check enforces that we don't add residuals when spatial
        # dimensions are None
        strides == 1 and
        # Depth matches
        m.get_shape().as_list()[3] == x.get_shape().as_list()[3]
      ):
        m = tf.keras.layers.Add()([m, x])
    
      return m
    

    检查尺寸和步幅可以防止我在添加两个不匹配尺寸的网络时最初遇到的错误

    【讨论】:

      猜你喜欢
      • 2019-08-02
      • 1970-01-01
      • 1970-01-01
      • 2021-01-12
      • 2019-02-25
      • 1970-01-01
      • 2018-10-07
      • 2010-11-22
      • 1970-01-01
      相关资源
      最近更新 更多