神经网络的调参技巧与关键点汇总

常用的神经网络调参技巧

在搭建好了一个网络模型之后,我们还需要对网络进行调整超参数与设置参数,以使得模型收敛或者达到更好的效果。
在此本文收集总结了一些常见神经网络(以CNN、RNN、GAN为主)较为通用的调参技巧,在后续还会对这些技巧做补充或者添加。

1 模型结构的优化

模型结构的优化指的就是对模型本身的结构做一些处理,使得模型的结构本身达到更优的效果。

1.1 激活函数的选择

在神经网络中,激活函数是用来加入非线性因素的,提高网络对模型的表达能力,解决线性模型所不能解决的问题;换个角度讲,激活函数也是实现神经网络多层次的必要条件,否则10层的线性网络与1层就没有本质区别了。目前常见的激活函数有:sigmoid、tanh、ReLU、Maxout、ELU、Leaky ReLU。

sigmoid

σ ( x ) = 1 1 + e − x \displaystyle \sigma(x) =\frac{1}{1+e^{-x}} σ(x)=1+ex1
特点:
a.可以将0-1之间的取值解释成一个神经元的激活率
b.输出均值非零(为0.5)
c.指数的运算比较复杂
d.输入过大或过小时函数无梯度
e.在深层次网络中容易导致梯度消失

tanh

t a n h ( x ) = e x − e − x e x + e − x \displaystyle tanh(x) =\frac{e^x-e^{-x}}{e^x+e^{-x}} tanh(x)=ex+exexex
特点:
a.输出均值为0
b.指数的运算比较复杂
c.输入过大或过小时函数无梯度

ReLU

f ( x ) = m a x ( 0 , x ) \displaystyle f(x) =max(0,x) f(x)=max(0,x)
特点:
a.计算量,收敛速度快
b.不会饱和,梯度不会太小(梯度为1)
c.输出均值非0
d.存在死激活现象(0的缘故)

Maxout

f ( x ) = m a x ( w 1 T x + b 1 , w 2 T x + b 2 ) \displaystyle f(x) =max(w_1^Tx+b_1,w_2^Tx+b_2) f(x)=max(w1Tx+b1,w2Tx+b2)
特点:
a.ReLU的泛化版本
b.没有死激活现象
c.参数过多,需要两组参数

ELU

f ( x ) = m a x ( α ( e x − 1 ) , x ) \displaystyle f(x) =max(\alpha(e^x-1), x) f(x)=max(α(ex1),x)
特点:
a.解决了ReLU死激活的问题
b.是ReLU的变种
c.均值更加接近于0
d.计算量更大

Leaky ReLU

f ( x ) = m a x ( 0.1 x , x ) \displaystyle f(x) =max(0.1x,x) f(x)=max(0.1x,x)
特点:
a.解决了ReLU死激活的问题
b.是ReLU的变种
c.计算量小

总结

目前,使用较多的是Leaky ReLU、ELU、maxout等,此时需要注意学习率的设置;再者使用tanh,毕竟其具有均值为零的特性;避免使用sigmoid激活函数。

1.2 添加更深层次的网络

在解决一个问题时,我们应该先添加尽可能少的网络层次解决问题,在浅网络层次收敛的基础上,通过添加各种网络层次实现模型效果的提升。
即对模型进行由浅入深的搭建过程。

1.3 使用前人调好的稳定模型

通过在github等网站上寻找已有的问题网络结构,在调通之后对其进行使用并改进。
即使用前人调好的稳定的模型结构。

1.4 选择合适的优化算法

在优化算法中,常见的有随机梯度下降与动量梯度下降,但是这两种算法受学习率的影响较大。
为了解决上述的问题,目前改进的算法有AdaGrad优化算法,梯度会随着训练次数的增加而降低,因此受学习率的影响会变小。RMSProp优化算法,解决了训练后期提前结束的问题,谷歌的alpha go围棋机器人就采用的这种优化算法。
目前,Adam优化算法的提出集众家之长,是我们平时最常用的优化算法,在tensorflow库中也有相关的封装,在一般环境下我们使用Adam优化算法就足够了。

1.5 dropout层的添加

dropout方法是针对网络过拟合问题提出的一种网络级解决措施,它随机使得一些隐藏的节点值为0,以减少神经网络中各节点之间相互作用,提高模型的泛化能力。
添加dropout层,可以提高模型的泛化能力,并可以提升训练的速度。dropout层的添加有几个关键点:
a.dropout层的设置是为了防止模型训练的过拟合,与损失函数上的正则化项本质很相似,所以dropout层也只是在训练上进行添加,测试与验证过程从不会使用dropout。
b.dropout层的本质是减少网络节点,因此它可以添加在网络中任意一层。不过有些时候我们在输入输出层也可以进行dropout操作,有时候却不可以。
c.dropout有个最大的问题在于通过dropout之后,损失函数可能并不会一直下降,很可能出现震荡等情况。因此一般都是在模型训练收敛的基础上再进行dropout操作,而不是上来就dropout。

2 参数值的设置优化

2.1 参数初始化

参数初始化很明显指的是对神经网络中的所有参数的初始化过程,在tensorflow中我们往往都是用一句话初始化参数的,并且一般都是使用正态分布。
在神经网络内部,真正起作用的就是我们训练得到的参数值,最终训练得到的参数值与初始化的参数值之间的关系还是比较密切的。如果我们对网络参数有一个好的初始化过程,那么网络的训练过程也会变得比较顺利高效。
如何判断初始化的优劣,可以通过查看网络节点激活值的分布来判断。
常见的初始化方法可以分为以下几类:

a.全部为0

所有的参数值权重为零,这种方法只使用于单层的神经网络,因为对于普通单层BP神经网络而言,单层的梯度会直接作用于参数,所以参数初始化为0并没有什么关系。但是多层网络不能使用这种方法,因为链式法则作用下,梯度从后向前传播时会导致消失。
因此,参数初始化为0只适用于单层神经网络。

b.均值为0,方差较小的正态分布初始化(如0.02)

这种初始化下会导致高层的均值为0,对深层网络而言不是好的初始化。

c.均值为0,方差较大的正态分布初始化(如1)

这种初始化的问题在于高层的均值全都变成了-1,导致-1于1非常集中,已经饱和了。

d.Xavier-tanh初始化方法

参数的初始化公式为:
w = n p . r a n d o m . r a n d n ( i n p u t , o u t p u t ) / n p . s q r t ( i n p u t ) w=np.random.randn(input,output)/np.sqrt(input) w=np.random.randn(input,output)/np.sqrt(input)
在这种初始化下,参数分布都比较均匀。但是这种初始化方法需要配套使用tanh激活函数,无法使用ReLU相关激活函数。

2.2 批归一化batch normalization

批归一化,它的意义和它的字面意思一样,就是对每一批处理的数据都进行归一化操作。批归一化操作可以理解为在网络输出层之后,激活函数层之前夹的一层计算网络,我们可以叫它批归一化层。批归一化层所做的主要工作就是对任意一层的数据做归一化操作,注意这里是任意层,而不仅仅是输入层。
每个批归一化层所作的事情如下图所示:

批归一化操作在CNN中应用广泛,在其他网络中也有应用。它通过将每一层的输出值进行归一化操作,使得每一层的参数训练变得更加高效,是解决深层次网络参数难以高效训练的有效手段。 我们可以在网络结构中添加批归一化层解决模型的一些参数训练问题,从而获得比较好的训练结果。
2.3 损失函数添加正则化项

首先,损失函数的正则化操作是为了解决模型过拟合的问题而提出的,这一点与dropout层一样,因此一般有dropout层的话就不需要损失函数的正则化操作了。但是有些时候我们还是会用到正则化操作来约束参数数量,惩罚损失函数。更多的时候,有dropout层就不需要正则化的损失函数了,所以大家可以灵活选择。

两种正则化方法:

J = ∑ i = 1 k ( y i − y i , ) J=\sum_{i=1}^k(y_i-y_i^,) J=i=1k(yiyi,)
对于上式损失函数J来说,在L1与L2正则化后的损失函数为下述所示:

L1:

J , = J + η ∑ i = 1 k ∣ θ ∣ J^,=J+\eta\sum_{i=1}^k|\theta| J,=J+ηi=1kθ

L2:

J , = J + 1 2 η ∑ i = 1 k θ 2 J^,=J+\frac{1}{2}\eta\sum_{i=1}^k\theta^2 J,=J+21ηi=1kθ2
一般来说,L2正则化比L1正则化更容易解决模型过拟合的问题,因此如果使用正则化来解决过拟合的话建议使用L2;L1在解决稀疏矩阵问题上比较好,尤其是处理以词袋模型为代表的一系列特征提取矩阵时可以考虑。

2.4 Fine Tuning

Fine Tuning简单来说就是用训练好的模型(参数训练好的),再训练新的数据。此时训练模型时,参数不会发生大的变化,很快模型就会收敛,得到的最终模型泛化能力也较强。
新数据集可以与元数据集相似,也可以不相似,但是当不相似时,最好只使用原模型的底层的特征值,而不使用高层的特征值。
总的来说,Fine Tuning是一种比较考验github检索能力的方法,找到与当前解决问题相似的已训练好的模型,对于我们解决问题而言十分有效。我一直觉得Fine Tuning与迁移学习有一点相似的感觉。目前,很多实际问题在解决时都是采用这种Fine Tuning的策略,毕竟从头训练一个“准确”的网络效率还是比较低的。

2.5 learning rate设置

learning rate是近乎所有参数里最能影响训练效果的一个了(自认为的),他只需要一个值就可以近乎影响整个训练的过程。一般用 λ \lambda λ表示学习率,学习率与参数更新的关系如下所示:
w , = w − λ ∗ δ w^,=w-\lambda*\delta w,=wλδ
δ \delta δ代表从后面传过来的梯度。
一般来说,学习率越小,训练速度越慢,学习率越大,训练越容易出问题。但是我们为了寻求模型的准确度,往往还是把学习率设置成一个比较小的值,如1e-4,但这往往导致我们模型训练的速度比较慢。
因此,我们可以使用动态变化的学习率来适当解决这个问题。即 λ \lambda λ值随着参数更新而不断变化。很明显,我们希望模型训练的早期学习率大一点,在模型训练后期学习率不断衰减,这样既兼顾了训练速度,又提升了模型准确度。
目前主要的学习率衰减方式有指数衰减、多项式衰减(可调成线性衰减)、余弦衰减等,在实际中可以灵活选取。

2.6 batch size与epoch的设置

首先,要先明白batch与epoch的区别:
batch是指更新网络参数所需要的固定数量的样本集合,最少包含一个样本,最多包含所有训练集的样本,batch size就是一个batch包含的样本数。epoch是把所有训练集全过一遍的次数,把训练集过1遍就叫1个epoch,过10遍就叫10个epoch。

batch与epoch在神经网络中的工作方式:
在网络的训练过程中,我们每次传入一个batch size的样本数据集,样本集以矩阵的形式传入(n个样本n行),一行是一个样本,一列是样本的一个特征。在经过一个个网络层之后,得到损失函数的计算值矩阵(应该是一个n行1列的),我们再对损失函数的计算矩阵求均值,得到我们看到的一个损失函数值。根据这一个损失函数的值,我们就会采用反向传播的方式更新整个网络参数的值。以batch为单位更新了所有训练集的数据之后,我们就完成了一个epoch。
batch size的常见值为32 64 128 256等2的整数次幂。batch size越大,模型训练越快,梯度更新的方向也越准确,但是可能最后模型的准确度差一点;batch size越小,模型训练的精度越高,但是容易产生梯度方向错误或者训练时间过长等问题,一般建议的batch size 值设置在128或者256即可。对于epoch参数,一般情况下,在GPU或者服务器资源充足的情况下越多越好。

3 数据层次的优化

3.1 数据增强

数据增强指的是对输入的训练数据的扩充和增加,这种扩充不是增加新的数据,而是通过一些变换手段来用原来的数据变换出新的数据。
数据增强的操作主要用在图片处理领域,通过将原始图片进行旋转、裁剪、扩大缩小、镜像等,将原始数据扩充为原来的几倍,达到增强模型训练效果的目的。

在做图像相关训练时,可以使用图像增强的方法来提高模型的泛化能力,其他类型的数据目前应用数据增强还比较有限。
3.2 shuffle

shuffle是指对原有训练数据集的顺序调整过程,将输入的样本数据完全随机化,使得输入数据更加模拟真实的训练数据,提高模型的整体效果。
例如:
{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } − > { 3 , 6 , 1 , 8 , 9 , 2 , 7 , 4 , 5 } \{1,2,3,4,5,6,7,8,9\}->\{3,6,1,8,9,2,7,4,5\} {1,2,3,4,5,6,7,8,9}>{3,6,1,8,9,2,7,4,5}
这个过程就是一个shuffle的过程。在python中也有一个单独的模块是shuffle,它并不是深度学习特有的方法。
有一个关于数据集顺序的笑话:一个猫狗分类器,由于训练数据集都是一张猫再一张狗地传给网络训练,导致最后网络没有学到半点猫狗的图像特征。

3.3 数据平衡

数据平衡比较好理解,就是指训练的数据应该均匀分布,这个问题在分类模型上比较明显。
例如,想要训练一个2分类器,最好就是两个类别输入的训练数据量为1:1;训练一个3分类器,最好就是两个类别输入的训练数据量为1:1:1…保持数据的均衡,对于模型的训练效果有一定的提升。

3.4 小数据集测试

在搭建一个新网络时,使用小数据集进行测试,可以更快地发现一些比较共性的问题。

3.5 增加数据量

一般情况下,数据越充分模型的训练效果就越好。但是这里的数据主要指的是有效数据,这一点很明显。当一个模型在大量数据集下的表现都较优时,可以更好的证明模型的泛化能力。

3.6 使用公开的数据集

公开的数据集是指一些著名高校或者企业公开的相关数据集。使用公开数据集的好处有三点:1 数据集是公开的,我们可以用。2 数据集质量高,我们不需要过多关注数据质量的问题,而可以把更多精力投入在模型上。3 通过公开数据集,我们可以比较方便的与传统的算法作比较,看出自己模型与传统模型的优劣。
例如,在Kim著名的textCNN论文中,他就是用了一些公开的数据集解释他的模型优点,他使用的MR 、SST-1、SST-2 、Subj 、TREC 、CR 、MPQA这七个数据集,在其他一些NLP相关论文中也有过使用。
所以使用公开的数据集与很多好处。

4 外部的相关优化

4.1 使用GPU或服务器加速训练

GPU的计算速度与CPU是没有办法比较的,运行速度快了对于实际模型调试而言十分重要。如果没有服务器支持的话,也可以在单机安装GPU,目前tensorflow就支持GPU版本的运算,可以去下载尝试。

4.2 可视化训练结果

在模型的训练过程中,可以通过观察模型各个节点以及输入输出的变化来控制模型的训练。例如,我们可以通过损失函数的值来判断模型的问题。

  • 7
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在PyTorch中神经网络训练过程中非常重要的一部分。下面我将给出一些常用的PyTorch神经网络方法: 1. 数访问和修改:你可以使用`model.parameters()`方法来访问模型的所有数。这个方法返回一个可迭代的数列表,你可以通过遍历这个列表来访问和修改每个数的值。例如,你可以使用`param.data`来访问数的值,并使用`param.data = new_value`来修改数的值。 2. 数初始化:在PyTorch中,你可以使用不同的方法来初始化神经网络数。PyTorch提供了一些预定义的初始化方法,比如`torch.nn.init.xavier_uniform_()`和`torch.nn.init.kaiming_normal_()`等。你可以在创建模型的时候使用这些初始化方法来初始化数。此外,你也可以自定义初始化方法,并在模型中用它们。可以考中的示例代码来了解如何在PyTorch中进行数初始化。 3. 数绑定:在某些情况下,你可能希望共享模型中的数。在PyTorch中,你可以通过将一个数的引用赋给另一个数来实现数的绑定。这样做的好处是可以节省内存,并且可以同时更新所有绑定的数。你可以使用`param1.data = param2.data`来将数2绑定到数1。 总结起来,神经网络训练中的重要环节,你可以通过访问和修改数、初始化数以及绑定数等方法来神经网络的性能和表现。你可以考和中的内容来学习更多关于在PyTorch中进行神经网络的方法。同样,你也可以考中提供的教程来深入了解PyTorch的使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值