【DL碎片4】深度学习中的的超参数调节
深度学习中的的超参数调节
我们平时一直都在说“调参、调参”,但实际上,不是调“参数”,而是调“超参数”。
一、参数(Parameter)和超参数(HyperParameter)是指什么呢?
参数是我们训练神经网络 最终要学习的目标,最基本的就是神经网络的权重 W和bias b,我们训练的目的,就是要找到一套好的模型参数,用于预测未知的结果。这些参数我们是不用调的,是模型来训练的过程中自动更新生成的。
超参数是我们控制我们模型结构、功能、效率等的 调节旋钮,具体有哪些呢:
- learning rate
- epochs(迭代次数,也可称为 num of iterations)
- num of hidden layers(隐层数目)
- num of hidden layer units(隐层的单元数/神经元数)
- activation function(激活函数)
- batch-size(用mini-batch SGD的时候每个批量的大小)
- optimizer(选择什么优化器,如SGD、RMSProp、Adam)
- 用诸如RMSProp、Adam优化器的时候涉及到的β1,β2等等
- ......
太多了,上面是一些最常见的超参数,一般的深度学习框架就是调节这些玩意儿。
具体怎么调节,在不同的场景中基本都不同,没有统一的标准说learning rate取多少比较好、epochs多少比较好,都是在在实际情况中反复试验的。当然,如果我们可以借鉴一些知名的项目的超参数的选择,来应用到我们类似的项目中去。
二、用什么方法来选择“(超)参数组合”呢?
hyperparameters众多,每一个hyperparameter有多种取法,这就是一个 组合问题了。
比如我们需要对两个超参数进行调节,可能会想到用 “网格法”:
这种方法有个很大的缺陷,主要是由 “不同的超参数的重要性/作用效果有区别”导致的。
比如,假设在某个问题中,上面的Hyper1的作用其实微乎其微,而Hyper2的改变对模型的效果很明显。那么,由网格法可知,H1和H2的组合有25种,我们需要试验25次。但是实际上呢,由于H1基本不起作用,我们相当于只进行了5次试验。
换句话说, 我们花了25次试验的时间,只做了5次试验。显然效率低下。
事实上,不同超参数的效果有区别是很常见的,所以用网格法会浪费我们大量的时间和资源。
因此,我们最好在两个参数构成的矩形内,随机取样,理想状态下,任何两点都不同行不同列:
随机取样法具体方法为:
- 在大范围内随机取样
- 在效果较好的几个点的附近,再划分较小区域,在其中再进行随机取样
- 重复上述过程
这样做的好处是,可以保证没有浪费的试验,同时可以迅速锁定最优区域,更快地找到最佳的超参数组合。
三、用合适的尺度(scale)来选择超参数
上面我们解决了如何选择组合的方法问题,但是具体 对于每一个超参数,应该在怎样的一个尺度上进行划分呢?
一般从经验上讲,我们可能会直接 “均匀采样(uniformly)”,就是用均匀分布去选择各个候选的超参数。然而,这里直接给出结论,这样 意义不大! 比如下面这种对学习率的在0~1上以0.1为尺度来采样:
对learning rate均匀采样,没有意义实际上效果是极差的。也许你会发现,对所有的点,试验的效果都是类似的。
为什么呢?(实际上,learning rate基本不会取大于0.1的值,因为太大了,梯度下降根本没法有效进行)
因为像这种超参数,我们在调节的时候,更关注的不是实际的数值,而是变化的程度。
例如,learning rate 从0.001到0.1,扩大了100倍,实际梯度下降中每一步都比之前增大了100倍。但是,从0.1到1,虽然实际的数值差比0.001到0.1的距离要大的多,但是实际的变化量最多就10倍。
因此,我们做实验就可以发现,0.001到0.1这个范围内,learning rate极为敏感,也许一个小小的改变就可以让我们的梯度下降cost曲线大有不同,但是从0.1到1,cost曲线也许基本没有变化。
更好的办法,是 在对数尺度上随机取样:
对数尺度上取样可以看到,这把“尺子”的每个刻度都是相差十倍的关系,我们的learning rate在这个尺度上进行随机采样,就可以得到很好的效果,尽快地找到最佳的超参数。
为啥这个是对数尺度呢?
不妨将取样的区间定义为[10a,10b],
但是,learning rate不是在上述区间均匀取样,而是令 learning rate=10r,让r在[a,b]内均匀取样。而r=log(learning rate).
因此称这种取样为log尺度取样。
通常,像learning rate这种连续性的超参数,都会在某一端特别敏感,learning rate本身在 靠近0的区间会非常敏感,因此我们一般在靠近0的区间会多采样。
类似的,动量法梯度下降中(SGD with Momentum)有一个重要的超参数 β,β越大,动量越大,因此 β在靠近1的时候非常敏感,因此一般取值在0.9~0.999.
四、训练模型的两种方式
吴恩达很形象地用两种动物来形容在实践中我们训练一个模型的两种方法:
熊猫法(Panda) VS. 鱼子酱法(Caviar)
熊猫法:
当我们训练一个很大的模型,但是计算资源又没有那么多的时候,我们会很珍惜我们的训练机会,通常会像照顾一个熊猫一样去照顾我们的模型的训练过程。
具体来说,我们先初始化一组超参数,然后每训练一段时间,比如一天,就赶紧去看看进展如何,是否按照我们预想的方向发展,然后做一定的微调,接着训练,保持观察;如果发现偏离了方向,赶紧对超参数进行调整。就这样,一天天地照看,直到最后达到我们的训练目标。
可以用下面的图来表示:
熊猫法
如图所示,每一天我们观察一次效果,并做微调。可以看到,前三天都不错,第四天突然走偏了,于是我们赶紧退回到D3的节点,调整参数重新训练,让它回到正轨。
这就跟熊猫的养成一样,熊猫每次只能生一个,而且存活率也很低,所以我们必须特别小心地看护。
鱼子酱法
鱼产卵一次就是一大坨,成千上万个小孩生出来,生死由命。
如果我们的计算资源足够丰富,可以同时训练多个模型,那么我们就可以用鱼子酱法:
鱼子酱法
我们直接丢一堆超参数组合的模型去训练,然后不管了,最后看看谁的效果最好就选择谁。
对于这两种方式怎么选择,当然是看具体的情况了,一般情况话,训练一个大模型的时候,我们没有那么壕,所以小心翼翼地去像照顾熊猫一样去调节我们的模型可能更常见一些。
好了,关于超参数调节(Hyperparameters tuning)的内容就差不多这些。具体的细节还是需要我们在实践中不断去尝试,以及可以多看看一些成功的神经网络结构的参数都是怎么设置的,作为借鉴。
欢迎关注我的专栏:
DeepLearning.ai学习笔记
和我一起一步步学习深度学习。
专栏其他文章:
【DL笔记1】Logistic回归:最基础的神经网络
【DL笔记2】神经网络编程原则&Logistic Regression的算法解析
【DL笔记3】一步步亲手用python实现Logistic Regression
【DL笔记4】神经网络详解,正向传播和反向传播
【DL碎片1】神经网络参数初始化的学问
【DL碎片2】神经网络中的优化算法
【DL碎片3】神经网络中的激活(Activation)函数及其对比