MobileNet V1 网络结构的原理与 Tensorflow2.0 实现

MobileNet 网络结构

介绍 MobileNet 之前,我们需要先了解一下它的重要组件——深度级可分离卷积(Depthwise separable convolution)网络,这种网络可以被进一步分解成两个部分:对输入的每个通道使用单通道卷积核进行卷积(depthwise convolution)、使用 1x1 卷积核将输入通道数转变成输出通道数(pointwise convolution)。举例如下图所示:
在这里插入图片描述
在第一部分中,深度级卷积和普通卷积不同,对于标准卷积其卷积核是用在所有的输入通道上的,而深度级可分离卷积针对每个输入通道采用不同的卷积核,即一个卷积核对应一个输入通道,所以我们说这个操作是发生在深度级上的。

在第二部分中,pointwise convolution 其实就和普通卷积操作相同,只不过使用的卷积核尺寸是 1x1 的。

深度级可分离卷积和一个普通卷积的整体效果差不多,但前者会大大减少计算量和模型参数量,具体可参考卷积、可分离卷积的参数量与计算量的对比

在 MobileNet 网络结构中,有 13 个深度级可分离卷积网络被使用。

代码实现

用函数实现

import tensorflow as tf

def conv_block(inputs, filters, kernel_size = (3,3), strides=(1,1)):
    x = tf.keras.layers.Conv2D(filters=filters, kernel_size=kernel_size, strides=strides,     
                               padding='SAME', use_bias=False)(inputs)
    x = tf.keras.layers.BatchNormalization()(x)
    out = tf.keras.layers.Activation('relu')(x)
 
    return out

def depthwise_conv_block(inputs,
                         pointwise_conv_filters,
                         strides=(1,1)):
    x = tf.keras.layers.DepthwiseConv2D(kernel_size=(3,3), strides=strides, padding='SAME',
                                        use_bias=False)(inputs)
    x = tf.keras.layers.BatchNormalization()(x)
    x = tf.keras.layers.Activation('relu')(x)
 
    x = tf.keras.layers.Conv2D(filters=pointwise_conv_filters, kernel_size=(1,1), 
                               padding='SAME', use_bias=False)(x)
    x = tf.keras.layers.BatchNormalization()(x)
    out = tf.keras.layers.Activation('relu')(x)
    return out

def mobilenet_v1(inputs,
                 classes):
    # [32, 32, 3] => [16, 16, 32]
    x = conv_block(inputs, 32, strides=(2,2))
    # [16, 16, 32] => [16, 16, 64]
    x = depthwise_conv_block(x, 64)
    # [16, 16, 64] => [8, 8, 128]
    x = depthwise_conv_block(x, 128, strides=(2,2))
    # [8, 8, 128] => [8, 8, 128]
    x = depthwise_conv_block(x, 128)
    # [8, 8, 128] => [4, 4, 256]
    x = depthwise_conv_block(x, 256, strides=(2, 2))
    # [4, 4, 256] => [4, 4, 256]
    x = depthwise_conv_block(x, 256)
    # [4, 4, 256] => [2, 2, 512]
    x = depthwise_conv_block(x, 512, strides=(2, 2))
    # [2, 2, 512] => [2, 2, 512]
    x = depthwise_conv_block(x, 512)
    # [2, 2, 512] => [2, 2, 512]
    x = depthwise_conv_block(x, 512)
    # [2, 2, 512] => [2, 2, 512]
    x = depthwise_conv_block(x, 512)
    # [2, 2, 512] => [2, 2, 512]
    x = depthwise_conv_block(x, 512)
    # [2, 2, 512] => [2, 2, 512]
    x = depthwise_conv_block(x, 512)
    # [2, 2, 512] => [1, 1, 1024]
    x = depthwise_conv_block(x, 1024, strides=(2,2))
    # [1, 1, 1024] => [1, 1, 1024]
    x = depthwise_conv_block(x, 1024)
    
    # [1, 1, 1024] => (1024,)
    x = tf.keras.layers.GlobalAveragePooling2D()(x)
    # (1024,) => (classes,)
    pred = tf.keras.layers.Dense(classes, activation='softmax')(x)
 
    return pred

inputs = np.zeros((10, 32, 32, 3), dtype=np.float32)
classes = 10
output = mobilenet_v1(inputs, classes)

output.shape
TensorShape([10, 10])

用类实现

import tensorflow as tf

class conv_block(tf.keras.Model):
    def __init__(self, filters, kernel_size = (3,3), strides=(1,1)):
        super().__init__()
        self.listLayers = []
        self.listLayers.append(tf.keras.layers.Conv2D(filters=filters, kernel_size=kernel_size, strides=strides,     
                              padding='SAME', use_bias=False))
        self.listLayers.append(tf.keras.layers.BatchNormalization())
        self.listLayers.append(tf.keras.layers.Activation('relu'))
        
    def call(self, x):
        for layer in self.listLayers.layers:
            x = layer(x)
        return x

class depthwise_conv_block(tf.keras.Model):
    def __init__(self, pointwise_conv_filters, strides=(1,1)):
        super().__init__()
        self.listLayers = []
        self.listLayers.append(tf.keras.layers.DepthwiseConv2D(kernel_size=(3,3), strides=strides, padding='SAME',
                                        use_bias=False))
        self.listLayers.append(tf.keras.layers.BatchNormalization())
        self.listLayers.append(tf.keras.layers.Activation('relu'))
        self.listLayers.append(tf.keras.layers.Conv2D(filters=pointwise_conv_filters, kernel_size=(1,1), 
                               padding='SAME', use_bias=False))
        self.listLayers.append(tf.keras.layers.BatchNormalization())
        self.listLayers.append(tf.keras.layers.Activation('relu'))
        
    def call(self, x):
        for layer in self.listLayers.layers:
            x = layer(x)
        return x

class mobilenet_v1(tf.keras.Model):
    def __init__(self, classes):
        super().__init__()
        self.listLayers = []
        self.listLayers.append(conv_block(32, strides=(2,2)))
        self.listLayers.append(depthwise_conv_block(64))
        self.listLayers.append(depthwise_conv_block(128, strides=(2,2)))
        self.listLayers.append(depthwise_conv_block(128))
        self.listLayers.append(depthwise_conv_block(256, strides=(2, 2)))
        self.listLayers.append(depthwise_conv_block(256))
        self.listLayers.append(depthwise_conv_block(512, strides=(2, 2)))
        self.listLayers.append(depthwise_conv_block(512))
        self.listLayers.append(depthwise_conv_block(512))
        self.listLayers.append(depthwise_conv_block(512))
        self.listLayers.append(depthwise_conv_block(512))
        self.listLayers.append(depthwise_conv_block(512))
        self.listLayers.append(depthwise_conv_block(1024, strides=(2,2)))
        self.listLayers.append(depthwise_conv_block(1024))
        self.listLayers.append(tf.keras.layers.GlobalAveragePooling2D())
        self.listLayers.append(tf.keras.layers.Dense(classes, activation='softmax'))
        
    def call(self, x):
        for layer in self.listLayers.layers:
            x = layer(x)
        return x

inputs = np.zeros((10, 32, 32, 3), dtype=np.float32)
model = mobilenet_v1(10)
model(inputs).shape
TensorShape([10, 10])
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 很抱歉,TensorFlow 2.0 中已经删除了 `tensorflow.contrib` 模块,因此不能直接导入 `tensorflow.contrib.learn`。不过,您可以使用 `TensorFlow 2.0` 中内置的 `tf.keras` 模块,或者使用 `TensorFlow Hub` 中的预训练模型。 ### 回答2: 要导入tensorflow.contrib.learn,您需要使用tensorflow 2.0的兼容性模块tf.compat.v1。在TensorFlow 2.0中,tf.contrib模块已被移除。然而,通过tf.compat.v1模块,您仍然可以使用一些tensorflow.contrib模块中的功能。 您可以按照以下步骤来导入tensorflow.contrib.learn: 1. 导入所需的模块: ```python import tensorflow.compat.v1 as tf from tensorflow.compat.v1 import contrib ``` 2. 启用兼容性模式: ```python tf.disable_v2_behavior() ``` 3. 现在您可以使用tf.contrib.learn及其功能: ```python contrib.learn.Estimator(...) ``` 注意:虽然这种方法使您能够导入tensorflow.contrib.learn,但由于tf.compat.v1模块是为了向后兼容而设计的,因此它可能在将来的版本中被删除。因此,最好尽量使用tensorflow 2.0的原生API。如果您使用tensorflow.contrib.learn的功能非常重要,您可以考虑使用旧版本的tensorflow(如tensorflow 1.15)来支持它。 ### 回答3: 在TensorFlow 2.0中,已经不再支持`tensorflow.contrib.learn`这个模块。`tensorflow.contrib`是一个容纳实验性、不太稳定或较少使用的功能和功能组件的命名空间,而且在TensorFlow 1.X版本中是存在的。在TensorFlow 2.0中,TensorFlow团队已经将这些组件整合到了其他模块中,或者将它们作为独立的项目进行维护。因此,如果你想在TensorFlow 2.0中使用`tensorflow.contrib.learn`,你将无法直接导入它。 如果你仍然想使用类似于`tensorflow.contrib.learn`的某些功能,可以考虑以下方法: 1. 使用TensorFlow 2.0官方文档中提供的迁移指南,查找替代`tensorflow.contrib.learn`的功能或模块。官方文档通常会提供有关如何将旧版本的代码迁移到TensorFlow 2.0的详细说明。 2. 如果你只是需要用到一些机器学习算法,你可以考虑使用`scikit-learn`这个Python库。它是一个专门用于机器学习的库,提供了丰富的算法和工具,可以与TensorFlow 2.0进行结合使用。 总之,在TensorFlow 2.0中,将不再直接支持导入`tensorflow.contrib.learn`。如果你有特定的需求,需要找到替代的方法来实现你的目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cofisher

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值