【神经网络】(8) 卷积神经网络(Mobilenet_v1),案例:cifar图像10分类
各位同学大家好,今天和大家分享一下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分类相关推荐
- 【卷积神经网络】卷积神经网络(Convolutional Neural Networks, CNN)基础
卷积神经网络(Convolutional Neural Networks, CNN),是一种 针对图像 的特殊的 神经网络. 卷积神经网络概述 Why not DNN? 图像数据的维数很高,比如 1, ...
- 卷积神经网络 图像识别,卷积神经网络图像处理
街道垃圾识别系统的原理是什么? 不久前上海关于垃圾分类的出台政策大家应该还记得,做好垃圾分类成为了许多人的难题.其实,随着人工智能技术的突飞猛进,自动分类垃圾桶已经出现了. 目前有许多关于人工智能自动 ...
- BP神经网络与卷积神经网络(CNN)
BP神经网络与卷积神经网络(CNN) 1.BP神经网络 1.1 神经网络基础 神经网络的基本组成单元是神经元.神经元的通用模型如图 1所示,其中常用的激活函数有阈值函数.sigmoid函数和双曲正 ...
- 【数据挖掘】卷积神经网络 ( 视觉原理 | CNN 模仿视觉 | 卷积神经网络简介 | 卷积神经网络组成 | 整体工作流程 | 卷积计算图示 | 卷积计算简介 | 卷积计算示例 | 卷积计算参数 )
文章目录 I . 人类的视觉原理 II . 卷积神经网络 模仿 视觉原理 III . 卷积神经网络简介 IV . 卷积神经网络 组成 V . 卷积神经网络 工作流程 VI . 降低样本参数数量级 VI ...
- 卷积神经网络 图像识别,卷积神经网络 图像处理
基于深度卷积神经网络进行人脸识别的原理是什么? 本质上是模式识别,把现实的东西抽象成计算机能够理解的数字.如果一个图片是256色的,那么图像的每一个像素点,都是0到255中间的一个值,这样你可以把一个 ...
- 全连接神经网络、卷积神经网络
全连接神经网络.卷积神经网络 前言 全连接神经网络 介绍 结构 损失函数 梯度下降 链式法则 反向传播 总结 卷积神经网络 背景 结构 卷积(Convolution) 池化(Max Pooling) ...
- 神经网络与卷积神经网络,什么是卷积神经网络
前馈神经网络.BP神经网络.卷积神经网络的区别与联系 一.计算方法不同1.前馈神经网络:一种最简单的神经网络,各神经元分层排列.每个神经元只与前一层的神经元相连.接收前一层的输出,并输出给下一层.各层 ...
- 神经网络与卷积神经网络,卷积神经网络运用
1.有哪些深度神经网络模型? 目前经常使用的深度神经网络模型主要有卷积神经网络(CNN) .递归神经网络(RNN).深信度网络(DBN) .深度自动编码器(AutoEncoder) 和生成对抗网络(G ...
- 卷积神经网络 图像处理,卷积神经网络基本原理
基于深度卷积神经网络进行人脸识别的原理是什么? 本质上是模式识别,把现实的东西抽象成计算机能够理解的数字.如果一个图片是256色的,那么图像的每一个像素点,都是0到255中间的一个值,这样你可以把一个 ...
最新文章
- 刘满强:干扰和恢复下农田土壤线虫群落研究及热点问题初探
- 单调递增最长子序列(南阳理工ACM)
- 基于SignalR的消息推送与二维码描登录实现
- opencv 使用cvload加载xml出现错误原因解析及方法
- Win10安装华三模拟器各种疑难问题
- ffmpeg库编译加文字_1.编译ffmpeg库
- Cloud一分钟 |亚马逊市值被微软反超;GKE全球大宕机长达19小时;苹果市值跌破9000亿美元...
- 最优化学习笔记(十六)——拟牛顿法(2)
- 高性能游戏本搭服务器,为吃鸡而生,这几款高性能游戏本不容错过!
- Xml和Tomcat
- DIY开源mini桌面i3结构3D打印机--分析
- 【OBS-studio-webrtc】obs推流到webrtc服务器端:接管OBS输出流到自定义推流服务
- 【读书笔记】向上-张自豪:清华学霸的成长之路
- 十一式:开发者思维模式-简单而纯粹
- webpack之基础篇(四):webpack-dev-server介绍
- 用Python实现一个商场管理系统(附源码)
- MIPI DSI的linux kernel驱动原理 | 基于RK3399
- pe如何查看计算机用户名,用PE如何查看系统版本
- JAVA工程师个人简历中的项目经验范文
- java8 协程_Java8 异步编程—CompletableFuture