目录
前言
之前已经用最简单的CNN网络实现了对MNIST数据集的分类问题,并且通过对参数以及网络结构的优化使模型的性能达到了一个不错的状态,本文将对所有参数进行调整比较,分析不同参数在CNN网络训练中的影响,主要是通过控制变量法,对loss以及acc曲线的分析,选择出较好的参数,并分析其原因。
为了比较出同组的不同参数间模型的性能差距,会调整其他的参数,适当的降低模型性能,来比较这组参数对模型性能的影响。
1.梯度下降优化器选择
主要对比的是随机梯度下降算法和Adam算法,RMSProp一般情况下跟Adam算法差不多,我们对这三种优化器进行对比。
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,,学习率0.01
对loss以及acc可视化
可以看到随机梯度下降算法SGD在训练集上表现很差,测试集上准确率也很低,很明显是初始学习率太小,本身SGD算法下降的方向不是沿着正确方向下降,而是不停的在正确方向摆动,为了对比,lr=0.03
将这三个优化器学习率增大一点
可视化losss以及acc
Train loss Test acc
Adam 0.03 0.99
SGD 0.04 0.96
RMSprop 0.03 0.96
可以看出,Adam与SGD以及RMSprop算法在最终结果上差不多,因为任务比较简单,性能差不多,但是Adam拟合的很快,准确率效率也很高,其次是RMSprop算法,有时候不稳定,但是总体上来说比SGD算法好些,而SGD虽然拟合的很慢,但是最终的结果上跟其他算法差不多。对于优化算法的比较以及原理可以看我之前的博客
2.初始学习率参数
学习率会影响每次迭代更新的步长,理论上来说学习率越大更新的越快,但是在最后更新就会出现在最优值左右大幅度摆动的情况并且产生过拟合,但是如果学习率过低,那么梯度会更新的很慢,于是学习率的设置要合理,下面用SGD算法(Adam算法自动更新学习率),
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,使用SGD梯度下降
设置lr=0.01,lr=0.05,lr=0.1,分别比较模型的性能。
对loss以及acc可视化
Train loss Test acc
lr=0.1 0.10 0.97
lr=0.05 0.15 0.96
lr=0.01 0.40 0.30
可以看出lr=0.01时,模型loss下降的很慢准确率也上升的很慢,但是当lr=0.1时,模型梯度更新的很快,但是loss值下降的并不平滑,因此选用lr=0.05比较合适。
3.batch_size参数
样本的数量如果过少模型在训练集上表现很好,但是在测试集上会表现的比较差,会出现过拟合现象,当使用较大的batch_size是一种避免过拟合现象的办法,但是不是所有时候都适合。
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,使用Adam梯度下降,学习率0.01
设置batch_size为100,500,1000
对loss以及acc可视化
Train loss Test acc
batch_size=100 0.01 0.99
batch_size=500 0.15 0.98
batch_size=1000 0.14 0.98
通过对不同batch_size下的loss和acc可视化分析,当batch_size=100时,准确率很高,但是已经出现过拟合现象,但是当batch_size=500时,曲线已经区域平滑,当batch_size=1000时,曲线已经很平滑了,也就是说,这个模型在处理MNIST数据集时,在算法允许的情况下,batch_size越多模型的性能是越好的,因为大的batch_size能缓和过拟合。
4.数据预处理参数
将数据预处理归一化以及打乱数据torchvision.transforms.Normalize((0.1307,), (0.3081,)) shuffle=True
一般来说对数据预处理让它归一,会使数据传入模型时处理更加方便,会提升模型的性能,打乱数据会使模型的过拟合现象下降。
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,使用Adam梯度下降,学习率0.01
对loss以及acc可视化
Train loss Test acc
不处理 0.04 0.98
数据归一处理 0.03 0.99
可以看出加入了Normalize以及shuffle在模型的性能上是有不少的提升的,以及过拟合现象相对于没有加入这些参数是有所缓和的,因此一般情况下,训练模型都应该加入此操作。具体的原理以及实现可以看我博客。
5.正则化参数的选择
5.1Regularization参数
正则化方法之一是Regularization,主要的做法就是在损失值上加入噪声,理论上来说这种做法可以缓解过拟合。如下对不加入噪声以及weight_decay=1e-3,weight_decay=1e-4的性能进行比较。
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,使用Adam梯度下降,学习率0.01
对loss以及acc可视化
可以看出加入的weight_decay=1e-3时有不错的效果,已经很大程度上降低了过拟合现象,也就是说明,噪声的加入要合理,不能太大也不能太小。
Train loss Test acc
w=0 0.04 0.99
w=1e-3 0.06 0.98
w=1e-4 0.03 0.99
5.2.dropout参数的选择
dropout是直接在神经元的传递之间舍弃一些值,减少了神经网络的复杂程度,一下通过对舍弃概率p的取值来分析他对模型的影响。
使用relu作为激活函数,使用随机方法进行初始化,标准差为0.1,使用Adam梯度下降,学习率0.01
分别设置概率p为0,0.5,0.7
对loss以及acc可视化
Train loss Test acc
p=0 0.14 0.99
p=0.5 0.08 0.99
p=0.7 0.18 0.98
可以看出当概率p值比较大的时候,loss值并不能很好的下降,导致在测试集上准确率偏低,但是如果没有加入dropout也就是p值很小的时候,已经出现过拟合了,当p=0.5时,拟合的效果不错,既保证了准确率,又缓和了过拟合。关于正则化的理解以及原理,可以看我博客
6.归一化参数BN
归一层一般都是在池化层之后使用的,用来将数据聚拢,但是又不改变数据的结构。
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,使用Adam梯度下降,学习率0.01
比较加入Bn和不加入Bn
可视化acc以及loss
Train loss Test acc
添加Bn 0.08 0.99
不添加Bn 0.11 0.98
可以看出加入Bn层不管是拟合速度还是loss值以及acc值都要好一些。
7.激活函数选择
CNN网络中激活函数一般都是Relu,用来加入非线性因素,但是也有其他激活函数。
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,使用Adam梯度下降,学习率0.01
分别使用Sigmiod函数以及Relu,tanh函数
对loss以及acc可视化
Train loss Test acc
Relu 0.04 0.99
Tanh 0.08 0.98
Sigmiod 0.10 0.96
可以看出Relu函数更加适合,Tanh函数也比较适合,应该Tanh函数跟Relu函数相似,是它的一个变种,Sigmiod函数就表现得最差,由于任务简单,看着有不错的准确率,但是比其他激活函数效果要差一些,具体有关的理论知识可以看我博客。
7.网络层数参数
对于网络层数一般来说是越层数越多,效果就越好,因为,通过对中间层可视化分析,发现层数越多,通道越多,提取出来的特征就越细致,因此识别的应该是越准确的。
使用relu作为激活函数,添加dropout,使用随机方法进行初始化,标准差为0.1,使用Adam梯度下降,学习率0.01
分别取
conv=1(一层卷积+一层池化+三层全连接),
conv=2(两层卷积+两层池化+三层全连接),
conv=3(三层卷积+三层池化+三层全连接)
对loss以及acc可视化
可以看出两层网络确实比三层网络更加的优秀,但是三层网络却没有理论上的效果,而且性能很低,接着对网络中的参数进行更改,
将网络层越深的网络向下取样的操作减少,保证输入全连接层的特征数量更多,
分别取
conv=2(两层卷积+两层池化+三层全连接),
conv=3(三层卷积+三层池化+三层全连接)
conv=4(四层卷积+四层池化+三层全连接),
对loss以及acc可视化
Train loss Test acc
conv=2 0.10 0.990
conv=3 0.08 0.992
conv=4 0.60 0.994
可以看出,层数越深,网路的性能就越好,不仅拟合的越快,而且准确率更高。
8. 权重初始化参数
为了避免神经元具有相同的输出,我们使用独特权重。我们还可以随机选择权重,避免每个周期后的损失都陷于局部最低点。
使用relu作为激活函数,添加dropout,使用Adam梯度下降,学习率0.01,如果是随机方法生成则,标准差为0.1
分别用四种方法进行初始化:
1.初始幅值较大
m.weight.data=0.05*m.weight.data.normal_(0, 0.1)
m.bias.data.zero_()
2.初始幅值较小
m.weight.data=0.01*m.weight.data.normal_(0, 0.1)
m.bias.data.zero_()
3.Xavier初始化
nn.init.xavier_normal_(m.weight.data)
nn.init.constant_(m.bias.data, 0)
4.Kaiming初始化
nn.init.xavier_normal_(m.weight.data)
nn.init.constant_(m.bias.data, 0)
可视化loss以及acc
Train loss Test acc
初始幅值较大 0.06 0.98
初始幅值较小 0.06 0.98
Xavier初始化 0.04 0.99
Kaiming初始化 0.04 0.99
可以看出Xavier和Kaiming初始化效果更加好,但是初始幅值的大小影响并不是那么大,可能是因为网络结构过于简单,而且此次分类任务也很简单,但是Xavier和Kaiming确实效果更好,
为了扩大初始值大小的影响,直接设置初始值为0以及一个很小的数0.00001,
可视化loss以及acc
initial=0.00001 loss=0.1,acc=0.97,
初始权重为0时,曲线完全不会拟合,但是如果设置一个很小很小的权重值,曲线就会 拟合,
当initial=0.00001,loss已经等于0.1,并且准确率有所下降,所以初始权重值的大小也对模型的拟合有不少影响。
注:除开网络层数参数选择,其他情况网络结构都为conv=2(两层卷积+两层池化+三层全连接)
总结
通过对CNN训练时各种参数的调节以及尝试,更加清楚的了解到了各种参数对模型性能的影响,但是还是有不少地方的理解比较模糊,过后会继续深入的了解。