卷积神经网络中VGG13与LeNet-5模型
卷积神经网络中VGG13与LeNet-5模型
1. 摘要
1.1卷积神经网络的理解
卷积神经网络的卷积层和池化层相当于图片的特征选择。通过卷积层和池化层选择出照片的特征数据。之后通过卷积层和池化层的特征选择数据,传入全连接神经网络进行模型的训练。
卷积提取特征,池化压缩特征。如图,起始输入为663的输入数据,通过设定的两个卷积核大小为443。默认步长为1。卷积核每到一个地方,每一层和对应卷积核的层进行运算,三层的运算结果相加得到最终的3*3的特征图。之后两个特征图过激活函数得到最终的输出数据。

池化层是来降低输入图片的尺寸,也就是压缩图片的特征。一般池化层分为两种一种是取出感受野中最大的数字,还用一种是取出感受野中的平均值。下图为22的卷积核来池化44的数据。

1.2本文使用的算法介绍
本文使用到了GVV13模型、LeNet-5模型和Dropout算法,Dropout算法。Dropout算法主要是针对于神经网络模型过拟合以及费时的缺点。过拟合是很多机器学习的通病。如果模型过拟合,那么模型的不会存在实际的使用价值,为了解决过拟合,一般会采用模型集成的方法,即训练多个模型组合,不管训练还是测试模型时间开销上也会非常大。

Dropout算法就是我们在向前传播的过程中,让某个神经元的激活值以一定的概率p停止工作,使模型的泛华性能更强,因而也不会太依赖某些局部特征。
1.3整体概述
从开始的第一部分介绍了基本的卷积知识,介绍了此次使用的模型设计到的Dropout算法。
第二部分,主要介绍了此次模型原数据的基本情况,使用的数据集为CIFAR10数据集。共有10类标签和10类图片,交代数据处理的方法进行数据的归一化预处理。
第三部分,介绍VGG模型并建立VGG13模型,详细介绍模型的建立过程,进行了模型调优达到预期模型效果。介绍LeNet-5模型的基本架构并建立对比模型LeNet-5,详细介绍模型的建立的过程,运行并输出模型相对应的参数和结果。方便后续模型的比较。
第四部分,模型进行相互的比较的结论,参数比较以及总体体验感的比较。
2. 数据理解与处理
2.1数据理解
CIFAR数据为三通道的彩色照片。数据集共分为10类,分别是飞机、汽车、鸟、猫、 鹿、狗、青蛙、马、船、卡车。所以数据集经常用CIFAR-10进行命名。通过导入数据可以看到,图像一共包含60000张的32*32的彩色图像。

2.2数据预处理
CIFAR-10数据集主要为三通道的彩色照片,我们直接从datasets库中分别导入训练数据和测试用数据。这里直接从datasets中导入的测试集和训练集数据比为50000比10000。
1. #加载数据
2. cifar10=tf.keras.datasets.cifar10
3. #黑白图像的通道数为1,彩色图像的通道个数为3(RGB)
4. (x_train,y_train),(x_test,y_test)=cifar10.load_data()
5. #如此写法,导入自动划分训练接和测试集,50000训练集 ,10000测试集
考虑到后面VGG13模型的参数较多,避免硬件局限造成内存溢出。我们将图片数据都除以255进行归一化处理。使图片的数据的区间范围在于[0,1]之间。由于标签是二维数据,先保证标签数据为整形,之后调用函数flatten对标签进行降维,使标签数据降为一维数据。
1. #数据预处理
2. def data_chuli (x,y):
3. # 数据归一化RGB取值为0-255
4. x=x.astype('float')
5. x/=255.0
6. # 将标签从二维降到一维
7. y=y.astype('int')
8. y=y.flatten()
9. return x,y
3. 使用VGG13进行CIFAR10的预测
3.1 VGG13
3.1.1模型介绍;
VGG类型结构。VGG是2014年创建出的卷积模型。基本模型为:第一层建立两个卷积层每层为64个33的卷积核,之后通过22的池化层选出数据,第二层和第三次四层的原理相近,唯一的变化就是在改变每一组卷积核的个数,最后通过全连接神经网络输出最终的结果。

VGG模型有多种模型的变形类型,据资料查的现在效果最好的为VGG16模型,我们此次主要选择VGG13模型来对CIFAR-10数据进行模型的训练和分类。

3.1.2模型建立
这里在建立模型过程中,数据处理没有在做过多的数据类型变换,由于模型分为卷积部分和全连接神经网络部分。为了保证模型的整体性,减少错误率。调用Tensorflow中的model进行模型Sequential大体的建立。为了保证卷积层与全连接神经网络的连接,在两种模型之间加入TF的Flatten函数。
#模型建立(VGG13)
2. model=models.Sequential()
3. #卷积
4. #第一层 64个3x3的卷积核,输入输出大小相同,并在第一层告诉卷积层要输入
5. #的形状,使用激活函数‘rule’
6. model.add(layers.Conv2D(64,kernel_size=[3,3],padding='same',input_shape=(32,32,3),activation=tf.nn.relu))
7. model.add(layers.Conv2D(64,kernel_size=[3,3],padding='same',activation='relu'))
8. #池化层为2*2 步长2 取2D输入最大池化值
9. model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
10. # 第二层 128个3x3的卷积核,输入输出大小相同,激活函数‘rule’
11. model.add(layers.Conv2D(128,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
12. model.add(layers.Conv2D(128,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
13. #池化层为2*2 步长2 取2D输入最大池化值
14. model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
15. # 第三层 256个3x3的卷积核,输入输出大小相同, 激活函数‘rule’
16. model.add(layers.Conv2D(256,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
17. model.add(layers.Conv2D(256,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
18. #池化层为2*2 步长2 取2D输入最大池化值
19. model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
20. # 第四层 256个3x3的卷积核,输入输出大小相同, 激活函数‘rule’
21. model.add(layers.Conv2D(512,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
22. model.add(layers.Conv2D(512,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
23. #池化层为2*2 步长2 取2D输入最大池化值
24. model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
25. # 第五层 512个3x3的卷积核,输入输出大小相同
26. model.add(layers.Conv2D(512,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
27. model.add(layers.Conv2D(512,kernel_size=[3,3],padding='same',activation=tf.nn.relu))
28. #池化层为2*2 步长2 取2D输入最大池化值
29. model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
30. #使用Dropout算法避免模型过拟合,抛弃率0.25
31. model.add(layers.Dropout(0.25))
32. #连接卷积和全连接神经网络
33. model.add(layers.Flatten())
34. #全连接神经网络
35. #第一层256个神经元,激活函数‘relu’
36. model.add(layers.Dense(256,activation='relu'))
37. #使用Dropout算法避免模型过拟合,抛弃率0.25
38. model.add(layers.Dropout(0.5))
39. #第一层128个神经元,激活函数‘relu’
40. model.add(layers.Dense(128,activation='relu'))
41. #使用Dropout算法避免模型过拟合,抛弃率0.25
42. model.add(layers.Dropout(0.5))
43. #输出层10个神经元,多分类标签,激活函数‘softmax’
44. model.add(layers.Dense(10,activation='softmax'))
之后编译网络模型拟合网络训练集数据和训练集标签。由于在数据预处理过程中没有转换标签为独热编码,顾在loss决策中使用sparse_categorical_crossentropy方法,梯度优化选择Adam。判断依据为准确率。
1. #编译网络
2. #标签非独热处理,选用sparse_categorical_crossentropy,梯度优化选择
3. #Adam策略,判断语句为准确率
4. model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])
5. #拟合网络
6. #根据训练和测试集训练网络,训练次数为50,训练批次为50,并使用测试集数
7. #据和测试集标签进行验证
8. history=model.fit(x=x_train,y=y_train,epochs=50,batch_size=50, validation_data=(x_test, y_test))
在进行第一次的训练过程中,模型发生了过拟合现象。此时的batch_sizew为100,之后分别在最后一次的池化层下,第一层全连接层和第二层全连接层下加入Dropout算法来减少模型的过拟合现象。并减少batch_size的数据量,降为50。

我们由图看到,训练共50次,训练集的loss在前期快速的下落,之后相对稳定的分布到了一个数值之间。并没有了下降或上升趋势。测试集的训练集也可以看到虽然产生波动但波动范围小,相对稳定,基本也没有下降或上升的趋势。前期训练集loss不断下降,验证集loss趋于不变,说明网络过拟合。之后训练集loss趋于不变,测试集loss趋于不变,说明要减小学习率或批量数目。
3.1.3预测结果
我们单独将训练集和测试集的loss变化和准确率分别画出曲线图。由VGG13的loss曲线可以看出训练集的loss曲线持续下降。但下降趋势呈现出周期性变化(如红框中圈出部分变化)。可能的情况有,VGG13的模型参数较多,占用硬件RAM的空间较大,当RAM没有存储空间以后,就会出现内存溢出的现象。内存溢出情况下,硬件会去找存储空间或删除一部分占用内存。由于只是删除一部分数据所以在后面的训练中没有从较大的loss值重新下降。如此反复操作,才出现类似周期的训练情况。

我们结合loss变化和准确率变化来解读两张图,结合两张图可以看到模型训练到大概第9次时达到拐点,第九次往后准确率达到相对稳定且没有较大的变化趋势准确率基本稳定。这才导致9次以后的模型训练出的测试集loss上上升,导致模型的过拟合,最终模型的准确率基本维持在0.76左右。

3.2 LeNet-5
3.2.1模型介绍;
相比VGG13模型,LeNet-5模型的网络明显要小,LeNet-5一共有七层,并不包括输入层。每一个层有多个特征图形,每通过一种卷积提取出输入的一种特征,然后每个特征有多个神经元。也就是卷积池化,再卷积再池化,到最后通过全连接神经网络进行标签输出。

第一层卷积层,55的6个卷积核,池化层选用2D输入22的池化层且步长为2,第二层卷积层,选用55的16个卷积核,池化层为2D输入22的池化层且步长为2。第三层为卷积层为5*5的120核的卷积核。之后连接一层全连接层,最终输出输出层。

3.2.2模型建立
数据处理与上一个模型的数据前期处理一样。之后直接建立LeNet-5模型。进行下一步分析。
1. #模型建立(LeNet-5)
2. model=models.Sequential()
3. #第一层 卷积核为6大小为5*5,输入数据形状[32,32,3],激活函数‘relu’
4. model.add(layers.Conv2D(6,kernel_size=[5,5],padding='same',input_shape=(32,32,3),activation='relu'))
5. #池化层为2*2 步长2 取2D输入最大池化值
6. model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
7. #第二层 卷积核为16大小为5*5,激活函数‘relu’
8. model.add(layers.Conv2D(16,kernel_size=[5,5],padding='same',activation='relu'))
9. #池化层为2*2 步长2 取2D输入最大池化值
10. model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'))
11. #第三层 卷积核为120大小为5*5,激活函数‘relu’
12. model.add(layers.Conv2D(120,kernel_size=[5,5],padding='same',activation='relu'))
13. #连接卷积层与全连接神经网络
14. model.add(layers.Flatten())
15. #全连接神经网络
16. #第一层 84个神经元 激活函数‘relu’
17. model.add(layers.Dense(84,activation='relu'))
18. #由于最大限度的避免模型过拟合,我提前调用了Dropout函数
19. model.add(layers.Dropout(0.5))
20. # 输出层 最终输出10,激活函数‘softmax’
21. model.add(layers.Dense(10,activation='softmax'))
接下来进行网络的编译和数据的拟合。由于标签没有使用独热编码进行处理,所以loss选取了sparse_categorical_crossentropy的策略,梯度优化选用Adam,判断依据为准确率。将模型训练50次。每批数据50个,并使用测试集数据和标签进行模型的验证。
1. #编译网络
2. #标签非独热处理,选用sparse_categorical_crossentropy,梯度优化选择
3. #Adam策略,判断语句为准确率
4. model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])
5. #拟合网络
6. #根据训练和测试集训练网络,训练次数为50,训练批次为50,并使用测试集数
7. #据和测试集标签进行验证
8. history=model.fit(x=x_train,y=y_train,epochs=50,batch_size=50, validation_data=(x_test, y_test))
3.2.3预测结果
LeNet-5模型的loss曲线图和准确率曲线图可以看到。训练集的loss值不断减小,训练集的准确率不断提高。测试集的loss降到一定程度后,由于准确率饱和又会导致训练集的loss值不断变大,呈现出模型过拟合的现象和结果。由于LeNet-5的参数相比于VGG13模型少得太多了,所以没有硬件性能的干扰因素,训练集测试集的loss和准确率曲线都相对平滑。


4. 结论
通过两个模型给出的准确率,基本可以看出(以准确率为评判依据)VGG13的准确率是优于LeNet-5模型的准确率,且两个模型在loss曲线下降的过程中也有明显的不同。LeNet-5模型的loss下降趋势是比VGG13模型的趋势平缓。从训练和测试中LeNet-5模型的稳定性是要比VGG13模型的稳定性稳定(也有可能由于我硬件本身的局限性所导致)。
LeNet-5 模型实际参数
| Layer | Output Shapr | Param# |
|---|---|---|
| conv2d (Conv2D) | (None, 32, 32, 6) | 456 |
| MaxPooling2D | (None, 16, 16, 6) | 0 |
| conv2d_1 (Conv2D) | (None, 16, 16, 16) | 2416 |
| MaxPooling | (None, 8, 8, 16) | 0 |
| conv2d_2 (Conv2D) | (None, 8, 8, 120) | 48120 |
| flatten | (None, 7680) | 0 |
| dense | (None, 84) | 645204 |
| dropout_1 | (None, 84) | 0 |
| dense_1 | (None, 10) | 850 |
通过两个模型的summary也可以看出两个模型之间的差别,两个模型的总参数相差甚多。所以所占用的空间资源较大,对硬件具有一定的要求。这时候LeNet-5的有事就显现出来,由于较小的模型参数,时计算机在空间和时间上所给的开销不会过大,这就导致了LeNet-5模型训练的速度要远远大于VGG13模型的训练速度。且由于没有过多的参数占用硬件资源,这也让一次性训练输入的批次数据量加多。可以更好的选取模型训练批次参数,找到模型优化最佳的情况。(由于这里需要两个模型作比较,我选用了‘控制变量法’即在模型编译过程中选择相同的批次参数和训练次数等等进行训练)。
表 2 VGG13模型实际参数
| Layer | Output Shapr | Param# |
|---|---|---|
| conv2d (Conv2D) | (None, 32, 32, 64) | 1792 |
| conv2d_1 (Conv2D) ( | None, 32, 32, 64) | 36928 |
| MaxPooling2D | (None, 16, 16, 64) | 0 |
| conv2d_2 (Conv2D) | ( None, 16, 16, 128) | 73856 |
| conv2d_3 (Conv2D) | (None, 16, 16, 128) | 147584 |
| MaxPooling | (None, 8, 8, 128) | 0 |
| conv2d_4 (Conv2D) | (None, 8, 8, 256) | 295168 |
| conv2d_5 (Conv2D) | (None, 8, 8, 256) | 590080 |
| MaxPooling | (None, 4, 4, 256) | 0 |
| conv2d_6 (Conv2D) | (None, 4, 4, 512) | 1180160 |
| conv2d_7 (Conv2D) | (None, 4, 4, 512) | 2359808 |
| MaxPooling | (None, 2, 2, 512) | 0 |
| conv2d_8 (Conv2D) | (None, 2, 2, 512) | 2359808 |
| conv2d_9 (Conv2D) | (None, 2, 2, 512 ) | 2359808 |
| MaxPooling | (None, 1, 1, 512) | 0 |
| dropout | (None, 1, 1, 512) | 0 |
| flatten | (None, 512) | 0 |
| dense | (None, 256) | 131328 |
| dropout_1 | (None, 256) | 0 |
| dense_1 | (None, 128) | 32896 |
| dropout_2 | (None, 128) | 0 |
| dense_2 | (None, 10) | 1290 |
所有内容同为本人撰写
葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。
更多推荐
所有评论(0)