0. 总述
不同于XGboost和LightGBM等传统机器学习模型,神经网络凭借极大的灵活性具有更好的学习能力,但也在网络结构设计和超参数调整上存在极大的困难。本文阐述作者在这方面实践中的一些心得体会,希望能帮大家打开新世界的大门。
神经网络模型中主要的超参数有:样本批量大小(batch_size)、周期步幅(steps)、迭代次数(epochs)、模型深度(网络隐藏层数量)、隐藏层神经元数量、优化算法、学习率(learn_rate)、激活函数、初始化方法、批量归一化(BatchNormalization)、梯度裁剪、正则化系数和droupout概率等。它们主要分为模型训练进程控制、学习能力控制、梯度稳定性控制和过拟合抑制控制四大类。
其中,样本批量大小(batch_size)、周期步幅(steps)、迭代次数(epochs)三个参数共同控制模型训练进程,在所有超参数中应最先调整。之后,隐藏层数量、隐藏层神经元数量、优化算法、学习率(learn_rate)四个参数共同控制模型学习能力,建议按参数写明顺序依次调整。激活函数、初始化方法、批量归一化(Batch Normalization)、梯度裁剪四个参数共同控制模型梯度稳定性,应根据模型深度在第三梯队给予调整。最后是正则化系数和droupout概率,它们共同控制模型的过拟合抑制强度。下面将注意介绍每个超参数的作用和调整方法。
1. 训练进程控制参数
样本批量大小(batch_size)主要控制每次更新模型参数所使用的样本数量,周期步幅(step)主要控制遍历学习一次训练集数据所经历的样本数量,而迭代次数(epochs)主要控制模型的训练进程。三者间的关系可详见作者早期博文《TensorFlow框架中batch、batch_size、iteration、step和epoch间的关系与意义》 link。
1.1 batch_size 调整方法
在所有超参数中,应首先应调整batch_size。设置较大batch_size,可加速模型训练且参数更新的梯度下降方向更稳定,但也因此更容易陷入鞍点造成局部最优解。配合较大的学习率和适当的优化算法可以改善易陷入局部最优解情况,但这也极大增强了梯度下降方向发散、模型无法收敛的风险。
通常,较小的batch_size( b a t c h s i z e ∈ [ 2 , 32 ] batchsize\in [2,32] batchsize∈[2,32])是更常见的选择,此时模型参数更新梯度下降的随机性更强、更容易跳出鞍点通向全局最优解,同时配合较小的学习率能取得更稳定的模型训练效果。
1.2 steps 调整方法
steps可以是大于0且小于训练集样本数 / 样本批量大小的任意整数,即:
s
t
e
p
s
∈
(
0
,
t
r
a
i
n
N
u
m
÷
b
a
t
c
h
s
i
z
e
]
steps \in (0, trainNum {\div} batch size]
steps∈(0,trainNum÷batchsize]
通常等于训练集样本数量除以样本批量大小,当steps小于它时,相当于随机森林算法中对输入样本进行随机采样的效果,可以减小模型方差、提高泛化性能。
1.3 迭代次数 epochs
若配合早停法,epochs是一个不用人工教调的超参数,可在避免过拟合的情况下,保证模型得到最充分的训练。具体方法是初始给定一个特别大的epochs值(比如10万),然后配置好早停规则,确定提前停止训练条件即可。
2. 学习能力控制参数
模型学习能力有四种超参数共同控制,隐藏层数量与隐藏层神经元个数控制模型复杂度,优化算法控制更新模型参数的梯度的计算方法,学习率控制每次梯度下降所走的步长。
2.1 隐藏层数量
一般来讲,只要有足够的神经元数量,只有一个隐藏层的神经网络模型理论上就可以对最复杂的功能进行建模。但是对复杂问题,更深的网络层数,往往比更多神经元的浅层网络效果更好。这是因为深层网络可以用更少的神经元对复杂函数进行建模,它学习效率更高、且训练速度更快。
总而言之,模型越深学习能力越强,也就越适合解决更为复杂的问题。但同时,学习能力越强的网络也越容易出现过拟合,且随着层次的加深,神经网络也越来越容易出现梯度消失或梯度爆炸等梯度不稳定现象。
2.2 隐藏层神经元数量
隐藏层中神经元数量越多(隐藏层中神经元的数量称作层的宽度),模型学习能力越强。在神经网络模型中,随隐藏层种类的不同,神经元排布数量尤其特有的规律。
2.2.1 全连接层
全连接层有两种经典的网络排布,即桶式结构和塔式结构。
其中,桶式结构每层神经元数量相同,随参数更新模型loss下降的更为稳定、对训练集数据中噪音的抗干扰能力更强,但桶式结构模型的学习能力及参数梯度下降的随机性都不如塔式结构,在适当条件下模型最终的训练效果往往不如踏实结构(但适当的训练条件需要精细教调,往往不易达成)。
塔式结构隐藏层神经元数量逐层递减,模型往往具有更好的学习能力,且随参数更新模型loss下降更为迅速但波动性也更强,优点是模型学习能力强且具有一定的随机性不易陷入局部最优解,但若学习率、优化算法等超参数控制不好也有很大的梯度下降方向发散、模型不收敛的风险。
2.2.2 卷积层
卷积神经网络隐藏层神经元数量排布比较简单,往往是由少到多,随隐藏层深度增加而增加(注意不一定是线性递增哈)。
比较经典的有VGG结构,即两到三层卷积网络组成一个VGG模块,然后数个模块依次串联组成网络模型。VGG模块内,数个卷积层的卷积核数量相同;模块间,随网络深度增加,卷积层的卷积核数量依次增加,如下图所示。
2.3 优化算法
不同优化算法比较:
优化算法类别 | 收敛速度 | 收敛质量 |
---|---|---|
SGD | 落后 | 突出 |
SGD(momentum=…) | 平均 | 突出 |
SGD(momentum=…, nesterov=True) | 平均 | 突出 |
Adagrad | 突出 | 落后(停止太早) |
RMSprop | 突出 | 突出 |
Adam | 突出 | 突出 |
Nadam | 突出 | 突出 |
AdaMax | 突出 | 突出 |
一般来讲,默认选择Adam算法作为优化器,即可满足绝大数任务的需要。
2.4 学习率
学习率有多种设置方法,一般不宜太大,后期详述。
3. 梯度稳定性控制参数
3.1 激活函数与参数初始化方法
激活函数要配合对应的初始化方法使用,其对应关系如下表所示:
初始化 | 激活函数 | σ 2 \sigma^2 σ2 |
---|---|---|
Glorot | None、logistic、softmax、tanh | 1 / f a n a v g 1 / fan_{avg} 1/fanavg |
He | ReLU、leaky ReLU(及其变体) 、ELU | 2 / f a n i n 2 / fan_{in} 2/fanin |
LeCum | SELU | 1 / f a n i n 1 / fan_{in} 1/fanin |
从缓解梯度不稳定问题的效果来讲,通常 SELU > ELU > leaky ReLU(及其变体) > ReLU > tanh > logistic,如果网络不能自归一化,那么ELU的性能可能会优于SELU。但实际使用中看,如果输入激活函数前网络计算结果存在比较大的负值,ELU激活函数也容易陷入饱和区造成梯度消失,此时leaky ReLU激活函数是更好的选择。
所以综合来看,一般选用默认初始化方法和ReLU激活函数就能取得很好的效果,当观测到梯度不稳定时可优先选用He初始化+leaky ReLU激活函数这一时间成本最低的组合看能否取得满意的效果。
3.2 批归一化
加入Batch Normalization层是有效抑制深层网络梯度不稳定的手段,它可添加在任何种类的隐藏层的激活函数之前。但批量归一化也增加了模型的复杂性,因此应配合过拟合抑制技术(如dropout层)使用。实现代码如下例:
import tensorflow as tf
model = tf.keras.models.Sequential([
……
tf.keras.layers.Dense(300),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Activation('relu'),
tf.keras.layers.Dropout(0.2),
……
])
3.3 梯度裁剪
梯度裁剪是一种流行的梯度爆炸缓解技术,它在反向传播期间裁剪梯度,使它们永远不会超过某个阈值。梯度裁剪常用于循环神经网络(RNN)中,因为RNN中难以使用批量归一化。对于其他类型的网络,批量归一化通常就足够了。
4. 过拟合抑制控制参数
4.1 L1和L2正则化
比较简单,后期待续
4.2 droupout
droupout概率一般在0.2到0.5之间。
卷积神经网络中,pooling层也有一定过拟合抑制效果,当droupout层与pooling层同时出现时,droupout层可排列在pooling层之后。