Table of Contents
1.1 AlexNet 简介
1.2 tensorflow2.0利用keras搭建AlexNet网络结构
1.3 AlexNet实现Fasion MNIST分类
参考文献及链接:
一、前言
在构建了LetNet网络实现对Fasion MNSIT的分类后,熟悉了深度学习在图像分类应用的大致流程,但精度不佳,于是决定搭建深度学习发展历程中经典的网络模型,对Fasion MNIST数据集进行进一步分析,了解各个网络模型的闪光点,也通过对网络模型的分析学习深度学习的知识点,秉承“实践出真理”的实干注意真谛,为后期在实际项目中的模型优化打好基础。
学习记录:
1. tensorflow2.0深度学习开发环境搭建(ubuntu/win10)
2. 项目实战1:TF2.0+LetNet-5构建Fasion MNSIT分类器
3. 项目实战2:TF2.0+AlexNet构建Fasion MNSIT分类器
4. 项目实战3:TF2.0+VGG-16构建Fasion MNIST分类器
5. 项目实战4:TF2.0+ResNet构建Fasion MNIST分类器
5. 项目实战5:TF2.0+mobilieNet构建Fasion MNIST分类器
AlexNet是2012年ImageNet竞赛冠军获得者Hinton和他的学生Alex Krizhevsky设计的。也是在那年之后,更多的更深的神经网路被提出,比如优秀的VGG,GoogleLeNet。其官方提供的数据模型,准确率达到57.1%,top 1-5 达到80.2%. 这项对于传统的机器学习分类算法而言,已经相当的出色,其网络结构如图1所示。
AlexNet中包含了几个比较新的技术点如下:
Dropout的作用及原理简介:Dropout可以作为训练深度神经网络的一种trick供选择。在每个训练批次中,通过忽略一半的特征检测器(让一半的隐层节点值为0),可以明显地减少过拟合现象。这种方式可以减少特征检测器(隐层节点)间的相互作用,检测器相互作用是指某些检测器依赖其他检测器才能发挥作用。即:在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征,示意图如图所示:
论文链接:Dropout: A Simple Way to Prevent Neural Networks from Overfitting
在AlexNet论文里由于采用了两块GUP进行训练,而当时深度学习框架也不想现在tensorflow这么人性化,所以看似挺复杂,这里我们将网络进行简化为单gpu版本,后期需要进行多gpu训练,可利用tensorflow的多gpu训练api进行改善,网络结构如图所示:(图片来自:详解深度学习之经典网络架构(二):AlexNet)
注:AlexNet原始输入图像尺寸为227x227x3大小的1000分类,而Fasion MNIST图像尺寸为28x28x1的10分类,输入尺寸太小不足以完成网络的下采样过程,故需要对网络进行简单的修改:
(1)卷积层1:卷积核步长设为:2
(2)输出层:输出向量长度设为:10
在networks文件夹中创建AlexNet.py,添加以下内容:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
def AlexNet_inference(in_shape):
model = keras.Sequential(name='AlexNet')
# model.add(layers.Conv2D(96,(11,11),strides=(4,4),input_shape=(in_shape[1],in_shape[2],in_shape[3]),
# padding='same',activation='relu',kernel_initializer='uniform'))
model.add(layers.Conv2D(96,(11,11),strides=(2,2),input_shape=(in_shape[1],in_shape[2],in_shape[3]),
padding='same',activation='relu',kernel_initializer='uniform'))
model.add(layers.MaxPooling2D(pool_size=(3,3),strides=(2,2)))
model.add(layers.Conv2D(256,(5,5),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(layers.MaxPooling2D(pool_size=(3,3),strides=(2,2)))
model.add(layers.Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(layers.Conv2D(384,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(layers.Conv2D(256,(3,3),strides=(1,1),padding='same',activation='relu',kernel_initializer='uniform'))
model.add(layers.MaxPooling2D(pool_size=(2,2),strides=(2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(2048,activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(2048,activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(10,activation='softmax'))
model.compile(optimizer=keras.optimizers.Adam(),
loss='sparse_categorical_crossentropy', #不能直接用函数,否则在与测试加载模型不成功!
metrics=['accuracy'])
model.summary()
return model
利用上一节构建的LetNet-5对Fasion MNIST数据集分类的工程,将推理模型更换为本次建立的AlexNet,进行训练,代码如下:
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
print(tf.__version__)
from utils import mnist_reader
from networks import LetNet_5
from networks import AlexNet
MODEL_DIR = "models/"
DataSetPath = "dataSets/fashion/"
# DataSetPath = "dataSets/mnist/"
x_train, y_train = mnist_reader.load_mnist(DataSetPath, 'train')
x_test, y_test = mnist_reader.load_mnist(DataSetPath, 't10k')
x_train = x_train.reshape((-1,28,28,1))
x_test = x_test.reshape((-1,28,28,1))
print(x_train.shape[1], x_train.shape[2], x_train.shape[3])
x_shape = x_train.shape
def AlexNet_train():
# 加载与训练权重
# AlexNet_model = keras.models.load_model(PRE_MODEL_DIR)
AlexNet_model = AlexNet.AlexNet_inference(x_shape)
totall_epochs = 0
epochs = 10
while(True):
history = AlexNet_model.fit(x_train, y_train, batch_size=64, epochs=epochs, validation_split=0.1)
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.legend(['training', 'valivation'], loc='upper left')
plt.show()
res = AlexNet_model.evaluate(x_test, y_test)
print(res)
totall_epochs += epochs
model_save_dir = MODEL_DIR+'AlexNet_model_'+str(totall_epochs)+'.h5'
AlexNet_model.save( model_save_dir )
keyVal = input('please enter your command!(0:quite, 1>:continue!)')
keyVal = int(keyVal)
if 0==keyVal:
break
elif 0<=keyVal and 10>=keyVal:
epochs = keyVal
在训练5个epochs后效果如下图所示:
最后在测试集得到87.67%的精度,不到200us(>5000fps)的推理时间,精度并没有比LetNet-5高?(论调参侠的重要性!)。
(1)AlexNet: ImageNet Classification with Deep ConvolutionalNeural Networks
(2)Dropout: A Simple Way to Prevent Neural Networks from Overfitting
(3)深入理解AlexNet网络(一篇讲解很棒的文章)