目录
了解 MobileNet V1网络结构
- 轻量级卷积神经网络
- 更少的参数、更小的计算量,却拥有不俗的性能
- 深度可分离卷积
深度可分离卷积
我们先来看看正常的卷积:
输入为:12 × 12 × 3,卷积核为:5 × 5 × 3,我们得到一个 8 × 8 × 1 的输出。
而在空间可分离卷积中,卷积分成两步骤:深度卷积 和 逐点卷积。
深度卷积:
逐点卷积:
不难发现,不管是正常的卷积,还是空间可分离卷积,最后得到的结果都是一个 8 × 8 × 1 的输出。
为什么使用深度可分离卷积可以减少参数计算量呢?
基于TensorFlow实现 MobileNet V1
复现的操作对着上图写即可。
import tensorflow as tf
import numpy as np
import cv2
#标准卷积块
def conv_block(
inputs,
filters,
kernel_size=(3,3),
strides=(1,1)
):
x = tf.keras.layers.Conv2D(filters, kernel_size=kernel_size, strides=strides, padding='same', use_bias=False)(inputs)
x = tf.keras.layers.BatchNormalization()(x)
return tf.keras.layers.ReLU(6.0)(x)
##深度可分离卷积块
def depthwise_conv_block(
inputs,
pointwise_conv_filters,
strides=(1,1)
):
x = tf.keras.layers.DepthwiseConv2D((3, 3), padding='same', strides=strides, use_bias=False)(inputs)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.ReLU(6.0)(x)
###深度卷积到此结束
###下面是逐点卷积
x = tf.keras.layers.Conv2D(pointwise_conv_filters, kernel_size=(1,1), padding='same', use_bias=False)(x)
x = tf.keras.layers.BatchNormalization()(x)
return tf.keras.layers.ReLU(6.0)(x)
#mobile_net
def mobilenet_v1(
inputs,
classes
):
##特征提取层
x = conv_block(inputs, 32, strides=(2,2))
x = depthwise_conv_block(x, 64)
x = depthwise_conv_block(x, 128, strides=(2,2))
x = depthwise_conv_block(x, 128)
x = depthwise_conv_block(x, 256, strides=(2,2))
x = depthwise_conv_block(x, 256)
x = depthwise_conv_block(x, 512, strides=(2,2))
x = depthwise_conv_block(x, 512)
x = depthwise_conv_block(x, 512)
x = depthwise_conv_block(x, 512)
x = depthwise_conv_block(x, 512)
x = depthwise_conv_block(x, 512)
x = depthwise_conv_block(x, 1024, strides=(2,2))
x = depthwise_conv_block(x, 1024)
##全局池化
x = tf.keras.layers.GlobalAveragePooling2D()(x)
##全连接层
pred = tf.keras.layers.Dense(classes, activation='softmax')(x)
return pred
##模型实例化
inputs = tf.keras.Input(shape=(32,32,3))
model = tf.keras.Model(inputs=inputs, outputs=mobilenet_v1(inputs, 10))
基于 CIFAR-10数据训练网络
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_train.shape
##标签数据变成one_hot矩阵
x_train = x_train / 255.0
y_train = tf.keras.utils.to_categorical(y_train, 10)
model.compile(
loss='categorical_crossentropy',
optimizer='adam',
metrics=['categorical_crossentropy','Recall', 'AUC']
)
#训练
model.fit(x_train, y_train, batch_size=10, epochs=1)
#保存
model.save('mobilenet_v1_cifar.h5')
使用训练好的模型进行预测
model = tf.keras.models.load_model('mobilenet_v1_cifar.h5')
model.summary()
##路径中要放入一张ship图像测试
img = cv2.imread('ship.png', 1) / 255.0
img = np.expand.dims(image, 0)
##预测
pred = model.predict(img)
pred