各位同学大家好,今天和大家分享一下TensorFlow2.0中如何搭载Mobilenet_v1神经网络。

1. 模型简介

MobileNet系列是轻量级网络的一个系列,是针对移动端以及嵌入式视觉的应用提出的一类有效的模型。详细见:MobileNet_v1详解 - 灰信网(软件开发博客聚合) (freesion.com)

MobileNet是一种基于深度可分离卷积的模型,深度可分离卷积是一种将标准卷积分解成深度卷积以及一个1x1的卷积。对于MobileNet而言,深度卷积针对每个单个输入通道应用单个滤波器进行滤波,然后逐点卷积应用1x1的卷积操作来结合所有深度卷积得到的输出。而标准卷积一步即对所有的输入进行结合得到新的一系列输出。深度可分离卷积将其分成了两步,针对每个单独层进行滤波然后下一步即结合。这种分解能够有效的大量减少计算量以及模型的大小。

深度可分离卷积和标准卷积的区别在于:标准卷积是将每个卷积核应用在所有通道上,而深度可分离卷积针对输入中的每个通道应用不同的卷积核。假设输入有M个通道,从下图可以看到,标准卷积层有N个卷积核,每个卷积核尺寸为Dk * Dk,通道数为M;深度可分离卷积有M个卷积核,每个卷积核的通道数都是1

但是深度可分离卷积的输入和输出维度都是一样的,那怎么改变维度呢?这时候就轮到逐点卷积出场,其本质为1*1的标准卷积,主要作用就是对输入进行升维和降维。


2. 数据加载

导入cifar10图像数据,由于导入的标签值y是二维的,需要将的shape=1的轴挤压掉。使用tf.squeeze(),指定轴为axis=1,使用.map()对数据集中的所有数据采用函数中的方法预处理,原始图像中每个像素值在[0,255]之间,归一化处理将其映射到[0,1]之间。指定.batch(128),即每次迭代从数据集中取出128组样本用于训练。

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers, Model, datasets# (1)数据获取
(x,y), (x_test,y_test) = datasets.cifar10.load_data()# 查看数据
print('x.shape:',x.shape,'y.shape:',y.shape)
# x.shape: (50000, 32, 32, 3) y.shape: (50000, 1)
print('y[:5]:', y[:5])#(2)预处理
# 预处理函数类型转换
def processing(x,y):x = tf.cast(x, dtype=tf.float32) / 255.0  y = tf.cast(y, dtype=tf.int32)return x,y# 创建训练集数据集
y = tf.squeeze(y, axis=1) # 把目标值y维度为1的轴挤压掉
train_db = tf.data.Dataset.from_tensor_slices((x,y))
train_db = train_db.map(processing).shuffle(10000).batch(128)# 创建测试集数据集
y_test = tf.squeeze(y_test, axis=1)
test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test))
test_db = test_db.map(processing).batch(128)# 构造一个迭代器,检查数据
sample = next(iter(train_db))
print('x_batch:', sample[0].shape,'y_batch', sample[1].shape)

为了能直观地了解我们要预测的图像,将图像可视化。

#(2)显示图像
import matplotlib.pyplot as plt
for i in range(15):plt.subplot(3,5,i+1)plt.imshow(sample[0][i]) # sample[0]代表取出的一个batch的所有图像信息plt.xticks([]) # 不显示xy轴坐标刻度plt.yticks([])
plt.show()


3. 模型构建

网络结构模型如下:


超参数:depth_multiplier 和 alpha

所有层的 通道数 乘以 alpha 参数(四舍五入),模型大小近似下降到原来的 alpha^2 倍,计算量下降到原来的 alpha^2 倍,用于降低模型的宽度。

输入层分辨率 乘以 depth_multiplier 参数 (四舍五入),等价于所有层的分辨率乘 depth_multiplier,模型大小不变,计算量下降到原来的 depth_multiplier^2 倍,用于降低输入图像的分辨率。


3.1 标准卷积

# 卷积+BN+激活函数
def conv_block(x, filter1, alpha, kernel, stride):# 宽度缩放因子filter1 = int(filter1 * alpha) # 卷积核--通道数# 卷积x = layers.Conv2D(filter1, kernel, stride, padding='same', use_bias=False)(x)# 标准化x = layers.BatchNormalization()(x)# 激活函数,使用relu6激活函数,保证移动端的精度x = layers.Activation('relu6')(x)return x

如果卷积层之后跟了BatchNormalization层,可以不用再加偏置了use_bias=False,对模型不起作用,还会占用内存。详情见下文偏置(bias)在什么情况下可以要,可以不要?

下图是激活函数relu6和relu之间的关系;主要是为了在移动端float16的低精度的时候,也能有很好的数值分辨率,如果对reLu的输出值不加限制,那么输出范围就是0到正无穷,而低精度的float16无法精确描述其数值,带来精度损失。


3.2 深度分离卷积

# 深度可分离卷积块代替普通的3*3卷积,减少参数提高网络检测效果
def depth_conv_block(x, filter1, alpha, stride, depth_multiplier):# 宽度缩放因子filter1 = int(filter1 * alpha)# 深度可分离卷积,输入层的 分辨率 乘以 depth_multiplier 参数 x = layers.DepthwiseConv2D(kernel_size=(3,3), strides=stride, padding='same', depth_multiplier=depth_multiplier,use_bias=False)(x)# 标准化x = layers.BatchNormalization()(x)# 激活函数x = layers.Activation('relu6')(x)# 1*1普通卷积+BN+激活,调整通道数。注,卷积后有BN层没必要加偏置,占用内存x = layers.Conv2D(filter1, kernel_size=(1,1), strides=(1,1), padding='same', use_bias=False)(x)x = layers.BatchNormalization()(x)x = layers.Activation('relu6')(x)return x

3.3 网络主体

根据上面的网络结构图,一步一步堆叠下来

# 网络主体部分
def mobilenet(classes=1000, input_shape=[224,224,3], alpha=1.0, depth_multiplier=1):# 输入层input_tensor = keras.Input(shape=input_shape)# 普通卷积  [224,224,3]==>[112,112,32]x = conv_block(input_tensor, 32, alpha, kernel=(3,3), stride=(2,2))# 深度可分离卷积块# [112,112,32] ==> [112,112,64]x = depth_conv_block(x, 64, alpha, (1,1), depth_multiplier) # [112,112,64] ==> [56,56,128]x = depth_conv_block(x, 128, alpha, (2,2), depth_multiplier) # [56,56,128]x = depth_conv_block(x, 128, alpha, (1,1), depth_multiplier) # [56,56,128]# [56,56,128] ==> [28,28,256]x = depth_conv_block(x, 256, alpha, (2,2), depth_multiplier) # [28,28,256]x = depth_conv_block(x, 256, alpha, (1,1), depth_multiplier) # [28,28,256]# [28,28,256] ==> [14,14,512]x = depth_conv_block(x, 512, alpha, (2,2), depth_multiplier) # [14,14,512]x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   # [14,14,512] ==> [7,7,1024]x = depth_conv_block(x, 1024, alpha, (2,2), depth_multiplier) # [7,7,1024]x = depth_conv_block(x, 1024, alpha, (1,1), depth_multiplier) # [7,7,1024]   # 全局平均池化层# [7, 7, 1024] -> [None, 1024]x = layers.GlobalAveragePooling2D()(x)shape = (1, 1, int(1024 * alpha)) #[1,1,1024]x = layers.Reshape(shape)(x) #[1,1,1024]x = layers.Dropout(0.5)(x)x = layers.Conv2D(classes, (1, 1), padding='same')(x) #[1,1,classes]x = layers.Activation('softmax')(x) # [1,1,1024]x = layers.Reshape((classes,))(x) # [None, classes]# 模型构建model = Model(input_tensor, x)return model# 模型
model = mobilenet()
# 查看网络结构
model.summary()

4. 完整代码

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers, Model, datasets# (1)数据获取
(x,y), (x_test,y_test) = datasets.cifar10.load_data()# 查看数据
print('x.shape:',x.shape,'y.shape:',y.shape)
print('x_test.shape:', x_test.shape, 'y_test.shape:', y_test.shape)
print('y[:5]:', y[:5])#(2)预处理
# 预处理函数类型转换
def processing(x,y):x = tf.cast(x, dtype=tf.float32) / 255.0  y = tf.cast(y, dtype=tf.int32)return x,y# 创建训练集数据集
y = tf.squeeze(y, axis=1) # 把目标值y维度为1的轴挤压掉
y = tf.one_hot(y, depth=10)
train_db = tf.data.Dataset.from_tensor_slices((x,y))
train_db = train_db.map(processing).shuffle(10000).batch(128)# 创建测试集数据集
y_test = tf.squeeze(y_test, axis=1)
y_test = tf.one_hot(y_test, depth=10)
test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test))
test_db = test_db.map(processing).batch(128)# 构造一个迭代器,检查数据
sample = next(iter(train_db))
print('x_batch:', sample[0].shape,'y_batch', sample[1].shape)#(2)显示图像
import matplotlib.pyplot as plt
for i in range(15):plt.subplot(3,5,i+1)plt.imshow(sample[0][i]) # sample[0]代表取出的一个batch的所有图像信息,映射到[0,1]之间显示图像plt.xticks([]) # 不显示xy轴坐标刻度plt.yticks([])
plt.show()#(3)构造模型
# 卷积+BN+激活函数
def conv_block(x, filter1, alpha, kernel, stride):# 宽度缩放因子filter1 = int(filter1 * alpha)# 卷积x = layers.Conv2D(filter1, kernel, stride, padding='same', use_bias=False)(x)# 标准化x = layers.BatchNormalization()(x)# 激活函数,使用relu6激活函数,保证移动端的精度x = layers.Activation('relu6')(x)return x# 深度可分离卷积块代替普通的3*3卷积,减少参数提高网络检测效果
def depth_conv_block(x, filter1, alpha, stride, depth_multiplier):# 宽度缩放因子filter1 = int(filter1 * alpha)# 深度可分离卷积x = layers.DepthwiseConv2D(kernel_size=(3,3), strides=stride, padding='same', depth_multiplier=depth_multiplier,use_bias=False)(x)# 标准化x = layers.BatchNormalization()(x)# 激活函数x = layers.Activation('relu6')(x)# 1*1普通卷积+BN+激活,调整通道数。注,卷积后有BN层没必要加偏置,占用内存x = layers.Conv2D(filter1, kernel_size=(1,1), strides=(1,1), padding='same', use_bias=False)(x)x = layers.BatchNormalization()(x)x = layers.Activation('relu6')(x)return x# 网络主体部分
# 4种分类,规定图片输入大小和之前读入图片相同
def mobilenet(classes=10, input_shape=[32, 32, 3], alpha=1.0, depth_multiplier=1):# 输入层input_tensor = keras.Input(shape=input_shape)# 普通卷积  [224,224,3]==>[112,112,32]x = conv_block(input_tensor, 32, alpha, kernel=(3,3), stride=(2,2))# 深度可分离卷积块# [112,112,32] ==> [112,112,64]x = depth_conv_block(x, 64, alpha, (1,1), depth_multiplier) # [112,112,64] ==> [56,56,128]x = depth_conv_block(x, 128, alpha, (2,2), depth_multiplier) # [56,56,128]x = depth_conv_block(x, 128, alpha, (1,1), depth_multiplier) # [56,56,128]# [56,56,128] ==> [28,28,256]x = depth_conv_block(x, 256, alpha, (2,2), depth_multiplier) # [28,28,256]x = depth_conv_block(x, 256, alpha, (1,1), depth_multiplier) # [28,28,256]# [28,28,256] ==> [14,14,512]x = depth_conv_block(x, 512, alpha, (2,2), depth_multiplier) # [14,14,512]x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   x = depth_conv_block(x, 512, alpha, (1,1), depth_multiplier) # [14,14,512]   # [14,14,512] ==> [7,7,1024]x = depth_conv_block(x, 1024, alpha, (2,2), depth_multiplier) # [7,7,1024]x = depth_conv_block(x, 1024, alpha, (1,1), depth_multiplier) # [7,7,1024]   # 全局平均池化层[7,7,1024] ==> [b, 1024]x = layers.GlobalAveragePooling2D()(x)shape = (1, 1, int(1024 * alpha))x = layers.Reshape(shape)(x)x = layers.Dropout(0.5)(x)x = layers.Conv2D(classes, (1, 1), padding='same')(x)x = layers.Activation('softmax')(x)x = layers.Reshape((classes,))(x)# 模型构建model = Model(input_tensor, x)return model# 模型
model = mobilenet()
# 查看网络结构
model.summary()#(4)网络配置
# 设置学习率
opt = optimizers.Adam(learning_rate=1e-5)# 编译
model.compile(optimizer=opt, # 学习率loss = tf.losses.CategoricalCrossentropy(),  #损失函数metrics=['accuracy'])  # 评价指标# 训练
history = model.fit(train_db,  # 训练集validation_data=test_db,  # 验证集epochs=30)  # 迭代次数#(5)模型评估
# 准确率
train_acc = history.history['acc']
val_acc = history.history['val_acc']
# 损失
train_loss = history.history['loss']
val_loss = history.history['val_loss']
# 绘图
plt.figure(figsize=(10,5))
# 准确率
plt.subplot(1,2,1)
plt.plot(train_acc, label='train_acc')
plt.plot(val_acc, label='val_acc')
plt.legend()
# 损失曲线
plt.subplot(1,2,2)
plt.plot(train_loss, label='train_loss')
plt.plot(val_loss, label='val_loss')
plt.legend()

【神经网络】(8) 卷积神经网络(Mobilenet_v1),案例:cifar图像10分类相关推荐

  1. 【卷积神经网络】卷积神经网络(Convolutional Neural Networks, CNN)基础

    卷积神经网络(Convolutional Neural Networks, CNN),是一种 针对图像 的特殊的 神经网络. 卷积神经网络概述 Why not DNN? 图像数据的维数很高,比如 1, ...

  2. 卷积神经网络 图像识别,卷积神经网络图像处理

    街道垃圾识别系统的原理是什么? 不久前上海关于垃圾分类的出台政策大家应该还记得,做好垃圾分类成为了许多人的难题.其实,随着人工智能技术的突飞猛进,自动分类垃圾桶已经出现了. 目前有许多关于人工智能自动 ...

  3. BP神经网络与卷积神经网络(CNN)

    BP神经网络与卷积神经网络(CNN) 1.BP神经网络  1.1 神经网络基础  神经网络的基本组成单元是神经元.神经元的通用模型如图 1所示,其中常用的激活函数有阈值函数.sigmoid函数和双曲正 ...

  4. 【数据挖掘】卷积神经网络 ( 视觉原理 | CNN 模仿视觉 | 卷积神经网络简介 | 卷积神经网络组成 | 整体工作流程 | 卷积计算图示 | 卷积计算简介 | 卷积计算示例 | 卷积计算参数 )

    文章目录 I . 人类的视觉原理 II . 卷积神经网络 模仿 视觉原理 III . 卷积神经网络简介 IV . 卷积神经网络 组成 V . 卷积神经网络 工作流程 VI . 降低样本参数数量级 VI ...

  5. 卷积神经网络 图像识别,卷积神经网络 图像处理

    基于深度卷积神经网络进行人脸识别的原理是什么? 本质上是模式识别,把现实的东西抽象成计算机能够理解的数字.如果一个图片是256色的,那么图像的每一个像素点,都是0到255中间的一个值,这样你可以把一个 ...

  6. 全连接神经网络、卷积神经网络

    全连接神经网络.卷积神经网络 前言 全连接神经网络 介绍 结构 损失函数 梯度下降 链式法则 反向传播 总结 卷积神经网络 背景 结构 卷积(Convolution) 池化(Max Pooling) ...

  7. 神经网络与卷积神经网络,什么是卷积神经网络

    前馈神经网络.BP神经网络.卷积神经网络的区别与联系 一.计算方法不同1.前馈神经网络:一种最简单的神经网络,各神经元分层排列.每个神经元只与前一层的神经元相连.接收前一层的输出,并输出给下一层.各层 ...

  8. 神经网络与卷积神经网络,卷积神经网络运用

    1.有哪些深度神经网络模型? 目前经常使用的深度神经网络模型主要有卷积神经网络(CNN) .递归神经网络(RNN).深信度网络(DBN) .深度自动编码器(AutoEncoder) 和生成对抗网络(G ...

  9. 卷积神经网络 图像处理,卷积神经网络基本原理

    基于深度卷积神经网络进行人脸识别的原理是什么? 本质上是模式识别,把现实的东西抽象成计算机能够理解的数字.如果一个图片是256色的,那么图像的每一个像素点,都是0到255中间的一个值,这样你可以把一个 ...

最新文章

  1. 刘满强:干扰和恢复下农田土壤线虫群落研究及热点问题初探
  2. 单调递增最长子序列(南阳理工ACM)
  3. 基于SignalR的消息推送与二维码描登录实现
  4. opencv 使用cvload加载xml出现错误原因解析及方法
  5. Win10安装华三模拟器各种疑难问题
  6. ffmpeg库编译加文字_1.编译ffmpeg库
  7. Cloud一分钟 |亚马逊市值被微软反超;GKE全球大宕机长达19小时;苹果市值跌破9000亿美元...
  8. 最优化学习笔记(十六)——拟牛顿法(2)
  9. 高性能游戏本搭服务器,为吃鸡而生,这几款高性能游戏本不容错过!
  10. Xml和Tomcat
  11. DIY开源mini桌面i3结构3D打印机--分析
  12. 【OBS-studio-webrtc】obs推流到webrtc服务器端:接管OBS输出流到自定义推流服务
  13. 【读书笔记】向上-张自豪:清华学霸的成长之路
  14. 十一式:开发者思维模式-简单而纯粹
  15. webpack之基础篇(四):webpack-dev-server介绍
  16. 用Python实现一个商场管理系统(附源码)
  17. MIPI DSI的linux kernel驱动原理 | 基于RK3399
  18. pe如何查看计算机用户名,用PE如何查看系统版本
  19. JAVA工程师个人简历中的项目经验范文
  20. java8 协程_Java8 异步编程—CompletableFuture

热门文章

  1. 查看Ubuntu 系统的版本
  2. 二叉树的遍历(递归与非递归)
  3. MFC控件编程之复选框单选框分组框
  4. Linux上用户执行命令记录
  5. css中float用法
  6. 简单几何(线段覆盖) POJ 3347 Kadj Squares
  7. 《需求分析》读后感之二
  8. 计算机基础知识综合试卷一,计算机基础知识试题及答案a
  9. oracle 分区使用情况,Oracle Hash分区的使用总结
  10. usaco Riding the Fences(欧拉回路模板)