基于Keras实现常见卷积神经网络模型(Lenet-5、Alexnet、VGG16)


自己随意搭建一个卷积神经网络模型经过调参后运行结果并没有那么好,此时了解一些常用的网络模型构造就很有必要,虽然模型结构看上去不难,但是通过手动实践后确实会更理解更透彻。

由于Keras模型相对其他深度学习框架而言封装性更好,个人认为初学者学习更为方便,于是本文基于keras框架搭建了Lenet-5、Alexnet、VGG16模型

1. 测试数据的准备

将keras内置的mnist数据集作为测试数据,仅测试网络是否运行,其运行结果并不表示网络的优劣程度。代码如下:

from keras.datasets import mnist#导入keras内置的mnist数据集
from keras.utils.np_utils import to_categorical

def load_mnist_data():#训练集和验证集数据
    (train_data,train_label),(test_data,test_label) = mnist.load_data()
    train_data = train_data.reshape((60000, 28, 28, 1))
    train_data = train_data.astype('float32') / 255
    test_data = test_data.reshape((10000, 28, 28, 1))
    test_data = test_data.astype('float32') / 255
    train_label = to_categorical(train_label)
    test_label = to_categorical(test_label)
    return (train_data,train_label),(test_data,test_label)

2. Lenet-5网络模型的搭建

2.1 Lenet-5模型结构概述

在这里插入图片描述
Lenet模型大致结构如下:

  1. 卷积层Conv_1:由6个5*5卷积核组成,激活函数为’relu’函数
  2. 池化层Pooling_1:2*2最大池化
  3. 卷积层Conv_1:由16个5*5卷积核组成,激活函数为’relu’函数
  4. 池化层Pooling_2:2*2最大池化
  5. 卷积层Conv_1:由120个3*3卷积核组成,激活函数为’relu’函数
  6. Flatten层:将输入展开为一维
  7. 全连接层Dense_1:84个节点
  8. 全连接层Dense_2(输出层):10个节点(该层节点数等于类别数)

2.2 Lenet-5模型搭建

代码如下:

from keras import models
from keras import layers
def create_Lenet():
    model = models.Sequential()
    model.add(layers.Conv2D(filters=6,kernel_size=(5,5),use_bias=True,activation='relu',input_shape = (28,28,1)))
    model.add(layers.MaxPooling2D(pool_size=(2,2)))
    model.add(layers.Conv2D(filters=16,kernel_size=(5,5),use_bias=True,activation='relu'))
    model.add(layers.MaxPooling2D(pool_size=(2,2)))
    model.add(layers.Conv2D(filters=120,kernel_size=(3,3),use_bias=True,activation='relu'))
    model.add(layers.Flatten())
    model.add(layers.Dense(84,activation='relu'))
    model.add(layers.Dense(10,activation='softmax'))
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['acc'])
    return model

2.3 测试结果

模型迭代10次后训练验证loss降为0.0398、验证acc为98.67%
在这里插入图片描述

图1. Lenet模型迭代Loss变化图

在这里插入图片描述

图2. Lenet模型迭代Accuracy变化图

3. Alexnet网络模型的搭建

3.1 Alexnet模型结构概述

在这里插入图片描述
原本的Alexnet模型分了两支,用两个GPU训练,由于条件受限仅使用一支。

Alexnet模型大致结构如下:

  1. 卷积层Conv_1:由48个11*11卷积核组成,步长为4,激活函数为’relu’函数
  2. 标准化BN_1
  3. 卷积层Conv_2:由128个5*5卷积核组成,激活函数为’relu’函数
  4. 标准化BN_2
  5. 卷积层Conv_3:由192个3*3卷积核组成,激活函数为’relu’函数
  6. 卷积层Conv_4:由192个3*3卷积核组成,激活函数为’relu’函数
  7. 卷积层Conv_5:由192个3*3卷积核组成,激活函数为’relu’函数
  8. 池化层Pooling_1:2*2最大池化
  9. Flatten层:将输入展开为一维
  10. 全连接层Dense_1:64个节点,激活函数为’relu’函数
  11. Dropout层:防止过拟合
  12. 全连接层Dense_2:64个节点,激活函数为’relu’函数
  13. Dropout层:防止过拟合
  14. 全连接层Dense_3(输出层):10个节点(该层节点数等于类别数)

(注:原本在卷积层Conv_1和卷积层Conv_2后面应分别跟一个池化层,由于输入图像尺寸并不大,使得多次卷积之后特征尺寸小于卷积核尺寸,无法继续卷积,故将最开始的两个池化层删去)

3.2 Alexnet模型搭建

代码如下:

def create_Alexnet():
    model = models.Sequential()
    model.add(layers.Conv2D(filters=48,padding='same',kernel_size=(11,11),strides=4,activation='relu',input_shape = (28,28,1)))
    # model.add(layers.MaxPooling2D(pool_size=(3,3),strides=2))
    model.add(layers.BatchNormalization())
    model.add(layers.Conv2D(filters=128,padding='same',kernel_size=(5,5),activation='relu'))
    # model.add(layers.MaxPooling2D(pool_size=(3,3),strides=2))
    model.add(layers.BatchNormalization())
    model.add(layers.Conv2D(filters=192,padding='same',kernel_size=(3,3),activation='relu'))
    model.add(layers.Conv2D(filters=192,padding='same',kernel_size=(3,3),activation='relu'))
    model.add(layers.Conv2D(filters=128,padding='same',kernel_size=(3,3),activation='relu'))
    model.add(layers.MaxPooling2D(pool_size=(3,3),strides=2))
    model.add(layers.Flatten())
    model.add(layers.Dense(64,activation='relu'))
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(64,activation='relu'))
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(10,activation='softmax'))
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['acc'])
    return model

3.3 测试结果

模型迭代10次后训练验证loss降为0.0832、验证acc为98.70%
在这里插入图片描述

图3. Alexnet模型迭代Loss变化图

在这里插入图片描述

图4. Alexnet模型迭代Accuracy变化图

4. VGG16网络模型的搭建

4.1 VGG16模型结构概述

在这里插入图片描述
VGG16模型大致结构如下:(2+2+3+3+3+3 = 16)

  1. Group1:
    卷积层Conv_1_1:由16个11 * 11卷积核组成,激活函数为’relu’函数
    卷积层Conv_1_2:由16个3 * 3卷积核组成,激活函数为’relu’函数
    池化层Pooling_1:2 * 2最大池化
  2. Group2:
    卷积层Conv_2_1:由32个3 * 3卷积核组成,激活函数为’relu’函数
    卷积层Conv_2_2:由32个3 * 3卷积核组成,激活函数为’relu’函数
    池化层Pooling_2:2 * 2最大池化
  3. Group3:
    卷积层Conv_3_1:由64个3 * 3卷积核组成,激活函数为’relu’函数
    卷积层Conv_3_2:由64个3 * 3卷积核组成,激活函数为’relu’函数
    卷积层Conv_3_3:由64个1 * 1卷积核组成,激活函数为’relu’函数
    池化层Pooling_3:2 * 2最大池化
  4. Group4:
    卷积层Conv_4_1:由128个3 * 3卷积核组成,激活函数为’relu’函数
    卷积层Conv_4_2:由128个3 * 3卷积核组成,激活函数为’relu’函数
    卷积层Conv_4_3:由128个1 * 1卷积核组成,激活函数为’relu’函数
    池化层Pooling_4:2 * 2最大池化
  5. Group5:
    卷积层Conv_5_1:由256个3 * 3卷积核组成,激活函数为’relu’函数
    卷积层Conv_5_2:由256个3 * 3卷积核组成,激活函数为’relu’函数
    卷积层Conv_5_3:由256个1 * 1卷积核组成,激活函数为’relu’函数
    Flatten层:展开为一维
  6. Group6:
    全连接层Dense_6_1:由1024个节点组成,激活函数为sigmoid函数
    全连接层Dense_6_1:由1024个节点组成,激活函数为sigmoid函数
    全连接层Dense_6_2:由10个节点组成

(注:本次调试减少了原VGG16各层卷积核个数(毕竟mnist数据集不需要数量过于庞大的卷积核))

4.2 VGG16模型搭建

代码如下:

def create_VGGnet():
    model = models.Sequential()

    model.add(layers.Conv2D(16, (3, 3), activation='relu', padding='same', input_shape=(28, 28, 1)))
    model.add(layers.Conv2D(16, (3, 3), activation='relu', padding='same'))
    model.add(layers.MaxPooling2D(2, 2))

    model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
    model.add(layers.MaxPooling2D(2, 2))

    model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
    model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
    model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
    model.add(layers.MaxPooling2D(2, 2))

    model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
    model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
    model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
    model.add(layers.MaxPooling2D(2, 2))

    model.add(layers.Conv2D(256, (3, 3), activation='relu', padding='same'))
    model.add(layers.Conv2D(256, (3, 3), activation='relu', padding='same'))
    model.add(layers.Conv2D(256, (3, 3), activation='relu', padding='same'))

    model.add(layers.Flatten())

    model.add(layers.Dense(1024, activation='relu'))
    model.add(layers.Dense(1024, activation='relu'))
    model.add(layers.Dense(10, activation='softmax'))
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['acc'])
    return model

4.3 测试结果

模型迭代10次后,验证loss降为0.0424,验证Accuracy为99.05%
在这里插入图片描述

图5. VGG16模型迭代loss变化图

在这里插入图片描述

图6. VGG16模型迭代Accuracy变化图

5. 备注

此处附上画图代码以及主函数代码

import matplotlib.pyplot as plt

def plot_results(history):
    history_dict = history.history
    loss_values = history_dict['loss']
    val_loss_values = history_dict['val_loss']

    epochs = range(1,len(loss_values)+1)
    plt.plot(epochs,loss_values,'ro',label='Training_loss')
    plt.plot(epochs,val_loss_values,'b',label = 'validation_loss')
    plt.title('Training and Validation Loss')
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.legend()
    plt.show()

    ##训练精度和验证精度绘图
    plt.clf()
    acc = history_dict['acc']
    val_acc = history_dict['val_acc']

    plt.plot(epochs,acc,'ro',label='Training_acc')
    plt.plot(epochs,val_acc,'b',label = 'Validation_acc')
    plt.title('Training and Validation Accuracy')
    plt.xlabel('Epochs')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.show()
if __name__ == '__main__':
    (train_data, train_label), (test_data, test_label) = load_mnist_data()
    #LeNet = create_Lenet()
    #AlexNet = create_Alexnet()
    VGGNet = create_VGGnet()
    history = VGGNet.fit(train_data,train_label,epochs=10,batch_size=512,validation_data=(test_data,test_label))
    plot_results(history)

小结

  1. 就三个模型来说实质上都很简单,都是通过卷积层提取特征,中间穿插池化层与BN层,同时为了防止过拟合可考虑添加Drouout层(参数一般设为0.5),自己动手搭建搭建并亲自调节参数后确实会理解更透彻。
  2. 从Lenet的到Alexnet到VGG,直观来讲,我们可以看到面对更为复杂的分类问题时,改善网络模型的方法之一便是增加网络深度(即增加卷积层),同时模型层数多,卷积核个数多,则考虑采用更小尺寸的卷积核来提取特征。
  3. 有任何问题欢迎指出,同时非常感谢该篇博主,总结的十分全面详细
    参考博客:卷积神经网络超详细介绍
  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值