介绍一些重要的网络设计过程中的超参数设定技巧和训练技巧,如学习率,批规范化操作和网络优化化策略的选择。
网络超参数设定在搭建整个网络架构之前,需首先指定与网络结构相关的各项超参数:输入图像像素,卷积层个数,卷积核相关参数。
使用卷积神经网络处理图像问题时,对不同输入图像为得到同规格输出,同时便于GPU运行,会将图像压缩到 2 2 2^2 22大小。一些经典的案例例如:CIFAR-10 数据 32 × 32 像素,STL数据集的96 × 96像素。另外如果不考虑硬件设备限制(通常是GPU显存大小),更高分辨率的图像一般有利于网络性能提升更为显著。此外需要指出,由于一般卷积神经网络采用全连接层作为最后分类层,若直接改变原始网络模型的输入图像分辨率,会导致原始模型卷积层的最终输出无法输入全连接层的状况,此时要重新改变全连接层输入滤波器大小或重新指定其他相关参数。
卷积层的超参数主要包括卷积核大小,卷积操作的步长和卷积核个数。关于卷积核大小,小卷积相比大卷积的优势:
同卷积核大小类似,池化层的核大小一般也设定为比较小的值,如 2 * 2 , 3 * 3 等。常用的参数设定为2 * 2 , 池化步长为 2 。在此设定下,输出结果大小仅为输入数据长宽大小的 3 / 4。也就是说有 75% 的相应值被丢弃。这就起到了下采样的作用。为了不丢弃过多的输入相应而损失网络性能,池化操作极少使用超过 3 * 3 大小的池化操作。
在训练卷积神经网络时,尽管训练数据固定,但由于采用了随机批处理的训练机制,因此我们可在模型每轮训练进行前将训练数据随机打乱,以确保模型不同轮次相同批次看到的数据是不同的。这样的处理不仅会提高模型的收敛速度,而且,相对固定次序的训练模型,此操作会略微提升模型在测试集上的预测结果。
###学习率的设定
训练模型时另一关键设定便是模型学习率,一个理想的学习率会促进模型收敛,而不理想的学习率甚至会导致模型直接损失函数损失值爆炸无法完成训练,学习率的设定可遵循以下原则:
优化算法的功能就是改善训练方式,来最小化(最大化)损失函数
模型内部有些参数,是用来计算测试集中目标值 Y 的真实值和预测值的偏差,基于这些参数,就形成了损失函数E(x)。
比如说,权重( ω ω ω)和偏差(b)就是这样的内部参数,一般用于计算输出值,在训练神经网络模型时起到主要作用。
在有效地训练模型并产生准确结果时,模型的内部参数起到了非常重要的作用。这也是为什么我们应该用各种优化策略和算法,来更新和计算影响模型训练和模型输出的网络参数,使其逼近或达到最优值。
优化算法分为两大类:
这种算法使用各参数的梯度值来最小化或最大化损失函数,最常用的一阶优化算法是梯度下降。
函数梯度:导数 dy / dx 的多变量表达式,用来表示y相对于x的瞬时变化率。往往为了计算多变量函数的导数时,会用梯度取代导数,并使用偏导数来计算梯度。梯度和导数之间的一个主要区别是函数的梯度形成了一个向量场。
因此,对单变量函数,使用导数来分析;而梯度是基于多变量函数而产生的。更多理论细节在这里不再进行详细解释。
二阶优化算法使用了二阶导数(也叫做Hessian方法)来最小化或最大化损失函数。由于二阶导数的计算成本很高,所以这种方法并没有广泛使用。
深度卷积神经网络通常采用随机梯度下降类型的优化算法进行模型训练和参数求解。经过近些年相关领域的发展,出现了一系列有效的网络训练优化新算法。许多工具箱都提供了了这些优化算法,工程实践中只需要根据自身的任务的需求选择合适的优化算法即可。
以下介绍为了简化起见,我们假设待学习参数 ω \omega ω,学习率或步长为 η \eta η,一阶梯度值为 g g g, t t t表示第t轮训练。
经典的随机梯度下降法(Stochastic Gradient Descent,简称SGD)是神经网络训练的基本算法,即每次批处理训练时计算网络误差并作误差反向传播,后根据一阶梯度信息对参数进行更新,其更新策略可表示为:
ω t = ω t − 1 − η ∗ g \omega_t =\omega_{t-1 }- \eta * g ωt=ωt−1−η∗g
其中,一阶梯度信息 $ g $ 完全依赖与当前批数据在网络目标函数上的误差,故可以将学习率 η \eta η理解为当前批的梯度对网络整体参数更新的影响程度。经典的随机梯度下降是最常见的神经网络优化方法,收敛效果稳定,不过收敛速度慢。
###基于动量的随机梯度下降法
随机梯度下降算法是非常受欢迎的优化方法,但学习过程会有时很慢。动量方法旨在加速学习,特别是处理高曲率,小但一致的梯度或是带噪声的梯度。动量的方法积累了之前梯度指数级衰减的移动平均,并且沿着该方向移动。
上图为没有动量,下图为有动量,可以看出动量相当于在连续梯度指向相同方向时,加大步长。我们可以将梯度下降比喻成一个小球在冰上,每当它沿着表面最抖的部分下降时,它会累计继续在该方向上滑行的速度,直到其开始向上滑为止。在上滑时步长变小。
公式为:
v t = μ ∗ v t − 1 − η ∗ g v_t = \mu * v_{t-1} - \eta * g vt=μ∗vt−1−η∗g
ω t = ω t − 1 + v t \omega_t = \omega_{t-1} + v_t ωt=ωt−1+vt
这个公式和SDG的区别其实就是加上了一个 μ ∗ v t − 1 \mu * v_{t-1} μ∗vt−1
其中 μ \mu μ为动量因子,控制动量信息对整体梯度更新的影响程度,一般取值0.5, 0.9, 0.99。 基于动量的随机梯度下降算法除了可以抑制震荡,还可以在网络训练后期趋于收敛,网络参数在局部最小值附近来回震荡时帮助其跳出局部限制。
当其梯度指向实际移动方向时,动量项 v v v增大;当梯度与实际移动方向相反时, v v v减小。这种方式意味着动量项只对相关样本进行参数更新,减少了不必要的参数更新,从而得到更快且稳定的收敛,也减少了振荡过程。
Nesterov型动量随机梯度下降方法是在上述动量梯度下降法更新梯度时加入对当前梯度的校正。相比一般动量方法,Nesterov型动量法对于凸函数在收敛性上有更强的理论保证。同时,Nesterov型动量也有更好的表现。
自己理解:动量随机梯度下降法从公式上看应该只是对于连续梯度指向同一个方向时,加大步长。而Nesterov是不仅仅改变步长,而且还对梯度方向进行调整。
ω a h e a d = ω t − 1 + μ ∗ v t − 1 \omega_{ahead} = \omega_{t-1} + \mu * v_{t-1} ωahead=ωt−1+μ∗vt−1
v t = μ ∗ v t − 1 − η ∗ ∇ ω a h e a d v_t = \mu * v_{t-1} - \eta * \nabla_{\omega_{ahead}} vt=μ∗vt−1−η∗∇ωahead
ω t = ω t − 1 + v t \omega_t = \omega_{t-1} + v_t ωt=ωt−1+vt
Require:学习率η, 动量参数μ
Require:初始参数w,初始速度v
while 没有达到停止条件准则 do
从训练集中找m个样本X={x1,x2...xm}的小批量,对应目标yi
应用临时更新: w' = w + μv
计算梯度(在临时点)g = 1/m ▽w'
计算速度更新: v = μ*v- η*g
应用更新:w = w + v
Adagrad 能独立地适应所有模型参数的学习率,缩放每个参数反比与其它所有梯度历史平方值总和的平方根。具有损失最大偏导的参数相应地有一个快速下降的学习率,而具有小偏导的参数在学习率上有相对较小的下降。净效果是在参数空间中更为平缓的倾斜方向会取得更大进步。
AdaGrad算法具有一些令人满意的理论性质。然而,经验上已经发现,对于训练神经网络模型而言,从训练开始累计梯度平方会导致有效的学习率过早和过量的减小。
Require:全局学习率η
Require:初始参数w
Require:小常数δ, 为了数值稳定大约设定为10^-7
初始化梯度累计变量 r=0
while 没有达到停止准则 do
从训练集中采包含m个样本X={x1,x2...xm}的小批量,对应目标yi
计算梯度(在临时点)g = 1/m ▽w'
累积平方梯度: r = r + g*g (g 和 g逐元素相乘)
计算更新 w' = η / (δ + sqrt(r))*g
应用更新 w = w + w'
end while
RMSProp改进了Adagrad在训练开始就累计梯度平方会导致有效的学习率过早和过量的减少。
Require:全局学习率η, 衰减速率ρ
Require:初始参数w
Require:小常数δ, 为了数值稳定大约设定为10^-6
初始化梯度累计变量 r=0
while 没有达到停止准则 do
从训练集中采包含m个样本X={x1,x2...xm}的小批量,对应目标yi
计算梯度(在临时点)g = 1/m ▽w'
累积平方梯度: r = ρr + (1-ρ)g*g (g 和 g逐元素相乘)
计算更新 w' = η / (δ + sqrt(r))*g
应用更新 w = w + w'
end while
RMSProp使用指数衰减平均以丢弃遥远过去的历史,使其能够找到凹碗之后快速收敛。
###使用Nesterov动量的RMSProp算法
Require:全局学习率η, 衰减速率ρ, 动量系数μ
Require:初始参数w, 初始参数v
Require:小常数δ, 为了数值稳定大约设定为10^-6
初始化梯度累计变量 r=0
while 没有达到停止准则 do
从训练集中采包含m个样本X={x1,x2...xm}的小批量,对应目标yi
应用临时更新: w' = w + μv
计算梯度(在临时点)g = 1/m ▽w'
累积平方梯度: r = ρr + (1-ρ)g*g (g 和 g逐元素相乘)
计算更新 w' = μ * v - η / (sqrt(r))*g
应用更新 w = w + w'
end while
Require: 步长η(默认为:0.001)
Require: 距估计的指数衰减速率,ρ1和ρ2在区间[0, 1)内,建议0.9 / 0.99
Require:用于数值稳定的小常数δ(建议默认为10^-8)
Require: 初始参数w
初始化一阶和二阶矩变量 s=0, r=0
初始化时间步t=0
while没有达到停止准则 do
从训练集中采包含m个样本X={x1,x2...xm}的小批量,对应目标yi
计算梯度(在临时点)g <- 1/m ▽w'
t <- t+1
更新有偏一阶距估计: s <- ρ1*s + (1 - ρ1)g
更新有偏二阶距估计: r <- ρ2*r + (1 - ρ2)g*g (*表示点乘)
更新一阶矩的偏差:s' <- s / (1 - ρ1(t))
更新二阶矩的偏差:r' <- r / (1 - ρ2(t))
计算更新:w' = -η * s' / ()sqrt(r')+δ)
应用更新 w <- w + w'
end while
除了从头训练自己的网络之外,一种更加有效,高效的方法是微调已训练好的网络模型。微调预训练模型简单有效,就是用目标任务数据在原先预训练模型上继续进行训练过程。
针对“当目标数据极少,同时还与原始数据有较大差异时”的情况,目前比较有效的方式是借助部分原始数据与目标数据协同训练。Ge和Yu提出,因预训练模型的浅层网络特征更具有泛化力,故可在浅层空间选择目标数据的近邻作为原始数据子集。之后,将微调阶段改为多任务学习(多任务学习就是有两个不同的任务,用同一个网络,同时生成两个结果):一者将目标任务基于原始数据子集,二者将目标任务基于全部目标数据。
[1] 解析卷积神经网络——深度学习实践手册
[2] 深度学习(花书)