从入土到入门学习超参数的调整

最近在做第十五届全国大学生智能汽车竞赛线上选拔赛,人流密度检测这块的效果一直不好,error_rate越整越大,交流群里的大佬也看不下去了:
在这里插入图片描述
确实,要是调整调整超参数,也不会是现在这样的成绩(流下了没技术的眼泪…)

于是,我下定决心,好好地啃啃这块硬骨头!(先把自己从土里拉出来…)

  1. 参数&超参数
  2. 手动调整超参数
  1. 自动优化超参数

在这里插入图片描述

在开始之前,首先好好学习一下什么是参数,什么又是超参数?

参数&超参数

参数:
模型根据数据可以自动学习出的变量

超参数:
用来确定模型的一些参数

参数

参数是机器学习算法的关键,是从训练数据中学习到的,属于模型的一部分。

不知道大家还记得权重吗?
适合新手入门且最简单的ANN人工神经网络模型(Python)

看看这篇文章里讲到的只有一个神经元的神经网络的权重:
在这里插入图片描述
输入一个值(x),乘以权重,结果就是网络的输出值。权重可以随着网络的训练进行更新,从而找到最佳的值,这样网络就能尝试匹配输出值与目标值。

下面再来看一下更复杂的网络:
在这里插入图片描述
为了得到预期的输出结果,将权重初始化后,权重可以随着网络的训练进行更新,从而找到最佳的值,这样网络就能尝试匹配输出值与目标值,从而得到预期的结果。

这里的权重其实就是一种参数

超参数

模型的超参数指的是模型外部的配置变量,是不能通过训练的进行来估计其取值不同的,且不同的训练任务往往需要不同的超参数

超参数不同,最终得到的模型也是不同的。

一般来说,超参数有:学习率,迭代次数,网络的层数,每层神经元的个数等等。

常见的超参数有以下三类:

  1. 网络结构,包括神经元之间的连接关系、层数、每层的神经元数量、激活函数的类型等 .
  2. 优化参数,包括优化方法、学习率、小批量的样本数量等 .
  3. 正则化系数

实践中,当你使⽤神经⽹络解决问题时,寻找好的超参数其实是一件非常困难的事情,对于刚刚接触的同学来说,都是"佛系调优",这也是一开始就"入土"的原因,没有依据的盲目瞎调肯定是不行的。

手动调整超参数

我们在使用某一网络时,一般是比较好的论文中出现过的,是证明过的,当然也可以直接套用,然后在这个基础上,调参。

可是如果识别的领域不同,比如同样是LeNet网络,在解决手写数字识别时使用的超参数能得到很好的效果,但是在做眼疾识别时,因为数据集的不同,虽然使用同样的超参数,但是效果可能并不理想。

在<< Neural Network and Deep Learning >>这本书中,作者给出⼀些⽤于设定超参数的启发式想法。⽬的是帮读者发展出⼀套⼯作流来确保很好地设置超参数。这里我把书上的内容总结一下,再结合自己的思考,与大家共同探讨调整超参数的方法论。

不过呢,目前不存在⼀种通⽤的关于正确策略的共同认知,这也是超参数调节的"玄学"之处

  1. 使⽤提前停⽌来确定训练的迭代期数量
  2. 让学习率从高逐渐降低
  3. 宽泛策略
  4. 小批量数据(mini-batch)大小不必最优
  5. 发展出⼀个确保自己能快速进行超参数优化的工作流

使⽤提前停止来确定训练的迭代期数量

这个策略是我的老师最早教我的,个人认为这也是防止过拟合最直接的方式

做法其实很简单,做一个判断,满足条件时退出循环,终止训练:

for epoch in range(MAX_EPOCH):
	// 训练代码
	print('{}[TRAIN]epoch {}, iter {}, output loss: {}'.format(timestring, epoch, i, loss.numpy()))
	if ():
		break
	model.train()

那么这个if条件判断就十分重要了,这里有两种方案:

  1. 分类准确率不再提升时
  2. loss降到一个想要的范围时

1. 分类准确率不再提升时

方案一是书中给的方法。

我们需要再明确⼀下什么叫做分类准确率不再提升,这样⽅可实现提前停⽌。

我们知道,分类准确率在整体趋势下降的时候仍旧会抖动或者震荡。如果我们在准确度刚开始下降的时候就停⽌,那么肯定会错过更好的选择。⼀种不错的解决⽅案是如果分类准确率在⼀段时间内不再提升的时候终⽌。

当然这块用loss也是可以的,loss也是一个评判标准

2. loss降到一个想要的范围时

方案二是我经常使用的、更直接的方法。

比如在前几轮的训练中,我知道loss一直在2.6-2.7的附近徘徊:
在这里插入图片描述
在下一次训练中,可以把条件设置为当loss小于2.0时终止训练

因为⽹络有时候会在很⻓时间内于⼀个特定的分类准确率附近形成平缓的局⾯,然后才会有提升。如果你想获得相当好的性能,方案一的规则可能就会太过激进了 —— 停⽌得太草率。

方案二能很好地解决这一问题,但随之而来的问题就是不知不觉地又多了一个超参数,实际应用上,这个用于条件判断的loss值的选择也很困难。

让学习率从高逐渐降低

我们⼀直都将学习速率设置为常量。但是,通常采⽤可变的学习速率更加有
效。

如果学习率设置的过低,在训练的前期,训练速度会非常慢;而学习率设置地过高,在训练的后期,又会产生震荡,降低模型的精度:
在这里插入图片描述

所以最好是在前期使⽤⼀个较⼤的学习速率让权重变化得更快。越往后,我们可以降低学习速率,这样可以作出更加精良的调整。

⼀种⾃然的观点是使⽤提前终⽌的想法。就是保持学习速率为⼀个常量直到验证准确率开始变差,然后按照某个量下降学习速率。我们重复此过程若⼲次,直到学习速率是初始值的 1/1024(或者1/1000),然后终⽌训练。

宽泛策略

在使⽤神经网络来解决新的问题时,⼀个挑战就是获得任何⼀种⾮寻常的学习,也就是说,达到⽐随机的情况更好的结果。

也许下面的方法能给你带来某些不一样的启发:

  1. 通过简化网络来加速实验进⾏更有意义的学习
  2. 通过更加频繁的监控验证准确率来获得反馈

通过简化网络来加速实验进⾏更有意义的学习

假设,我们第⼀次遇到 MNIST 分类问题。刚开始,你很有激情,但是当模型完全失效时,你会就得有些沮丧。

此时就可以将问题简化,将十分类问题转化成二分类问题。丢开训练和验证集合中的那些除了 0 和 1的那些图像,即我们只识别0和1。然后试着训练⼀个⽹络来区分 0 和 1。

这样一来,不仅仅问题⽐ 10 个分类的情况简化了,同样也会减少 80% 的训练数据,这样就多出了 5 倍的加速。同时也可以保证更快的实验,也能给予你关于如何构建好的⽹络更快的洞察。

通过更加频繁的监控验证准确率来获得反馈

这个方法调的其实是输出:

if i % 200 == 0:
	timestring = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))
	print('{}[VALID]epoch {}, iter {}, output loss: {}'.format(timestring, epoch, i, loss.numpy()))

对模型本身并没有任何关系,但是,你能得到更多并且更快地得到反馈,从而快速地实验其他的超参数,或者甚⾄近同步地进⾏不同参数的组合的评⽐。

这一点看似不重要,但对于超参数的调整来说,是很重要的一步

因为在实际的应用中,很容易会遇到神经⽹络学习不到任何知识的情况。你可能要花费若干天在调整参数上,仍然没有进展。所以在前期的时候,就应该从实验中尽可能早的获得快速反馈。直觉上看,这看起来简化问题和架构仅仅会降低你的效率。而实际上,这样能够将进度加快,因为你能够更快地找到传达出有意义的信号的网络。⼀旦你获得这些信号,你可以尝试通过微调超参数获得快速的性能提升。

这和人生中很多情况⼀样 —— 万事开头难。

小批量数据(mini-batch)大小不必最优

假设我们使⽤大小为 1 的小批量数据。而一般来说,使用只有⼀个样本的小批量数据会带来关于梯度的错误估计

而实际上,误差并不会真的产⽣这个问题。原因在於单⼀的梯度估计不需要绝对精确。我们需要的是确保代价函数保持下降足够精确的估计。

这就好像你现在要去北极点,但是只有⼀个不⼤精确的指南针。如果你不再频繁地检查指南针,指南针会在平均状况下给出正确的⽅向,所以最后你也能抵达北极点。

不过使用更⼤的小批量数据看起来还是显著地能够进⾏训练加速的。

所以,选择最好的小批量数据大小是⼀种折中。小批量数据太小会加长训练时间;而小批量数据太大是不能够足够频繁地更新权重的。你所需要的是选择⼀个折中的值,可以最大化学习的速度。

幸运的是,小批量数据大小的选择其实是相对独⽴的⼀个超参数(⽹络整体架构外的参数),所以你不需要优化那些参数来寻找好的小批量数据大小。

因此,可以选择的⽅式就是使⽤某些可以接受的值(不需要是最优的)作为其他参数的选择,然后进⾏不同小批量数据大小的尝试,就像上面调整学习率那样,画出验证准确率的值随时间(非回合)变化的图,选择得到最快性能提升的小批量数据大小。

发展出⼀个确保自己能快速进行超参数优化的工作流

超参数优化不是⼀个已经被完全解决的问题。总有⼀些技巧能够尝试着来提升性能。有句关于作家的谚语是:“书从来不会完结,只会被丢弃。”这点在神经⽹络优化上也是⼀样的:超参数的空间太大了,所以⼈们无法真的完成优化,只能将问题丢给后⼈。

所以你的目标应是发展出⼀个工作作流来确保自己快速地进行参数优化,这样可以留有足够够的灵活性空间来尝试对重要的参数进行更加细节的优化。

自动优化超参数

超参数优化( Hyperparameter Optimization )主要存在两方面的困难 :

  1. 超参数优化是一个组合优化问题,无法像一般参数那样通过梯度下降方法来优化,也没有一种通用有效的优化方法
  2. 评估一组超参数配置的时间代价非常高,从而导致一些优化方法在超参数优化中难以应用

常见的优化方法主要有:

  1. 网格搜索
  2. 随机搜索
  3. 贝叶斯优化
  4. 动态资源分配
  5. 神经架构搜索

1. 网格搜索

网格搜索( Grid Search )是一种通过尝试所有超参数的组合来寻址合适一
组超参数配置的方法。网格搜索根据这些超参数的不同组合分别训练一个模型,然后测试这些模型在开发集上的性能,选取一组性能最好的配置 。

说的直接一点就是穷举法

我们在搜索超参数的时候,如果超参数个数较少(3-4个或者更少),那么我们可以采用网格搜素,一种穷尽式的搜索方法。

但是当超参数个数比较多的时候,我们仍然采用网格搜索,那么搜索所需时间将会指数级上升。

比如我们有四个超参数,每个范围都是[10,100],那么我们所需的搜索次数是101010*10=10^4

如果再增加一个超参数,那么所需的搜索次数是10^5,搜索时间指数级上升。

2. 随机搜索

不同超参数对模型性能的影响有很大差异 。有些超参数(比如正则化系数)
对模型性能的影响有限,而另一些超参数(比如学习率)对模型性能影响比较大 。在这种情况下,采用网格搜索会在不重要的超参数上进行不必要的尝试 。

一种在实践中比较有效的改进方法是对超参数进行随机组合,然后选取一个性能最好的配置,这就是随机搜索( Random Search )。

随机搜索在实践中更容易实现,一般会比网格搜索更加有效 。

然而网格搜索和随机搜索都没有利用不同超参数组合之间的相关性,即如果模型的超参数组合比较类似,其模型性能也是比较接近的 。因此这两种搜索方式一般都比较低效。

另外,这两种方法都有一个比较大的缺陷:资源浪费

这两种方法只有一小部分神经网络将被优质的超参数训练,但是剩下大部分网络无法接受更好的训练,因此这种方法浪费计算资源。

3. 贝叶斯优化

贝叶斯优化( Bayesian optimization )是一种自适应的超参数优化方法,根据当前已经试验的超参数组合,来预测下一个可能带来最大收益的组合 。

这种搜索策略是建立一个代理模型,试图从超参数配置中预测我们关心的度量指标。在每一次迭代中,代理将会变得越来越有信心,新的猜测会带来新的改进。

要想搞明白贝叶斯优化,就要明白什么是高斯过程:

高斯过程( Gaussian Process )会产生预测值,同时还会给我们一个不确定性的范围,通常是均值和方差。

新的超参数就从这个不确定的范围里取出,相比随机搜索,贝叶斯优化更具有目标性

4. 动态资源分配

在超参数优化中,每组超参数配置的评估代价比较高。如果我们可以在较早
的阶段就估计出一组配置的效果会比较差,那么我们就可以中止这组配置的评估,将更多的资源留给其他配置。

这个问题可以归结为多臂赌博机问题的一个泛化问题:最优臂问题( Best-Arm Problem ),即在给定有限的机会次数下,如何玩这些赌博机并找到收益最大的臂。和多臂赌博机问题类似,最优臂问题也是在利用和探索之间找到最佳的平衡。

由于目前神经网络的优化方法一般都采取随机梯度下降,因此我们可以通过一组超参数的学习曲线来预估这组超参数配置是否有希望得到比较好的结果。

如果一组超参数配置的学习曲线不收敛或者收敛比较差,我们可以应用早期停止( Early-Stopping )策略来中止当前的训练。

动态资源分配的关键是将有限的资源分配给更有可能带来收益的超参数组
合。 一种有效方法是逐次减半( SuccessiveHalving )方法,将超参数优化看作是一种非随机的最优臂问题。

在逐次减半方法中,尝试的超参数配置数量十分关键。如果数量越大,得到最佳配置的机会也越大,但每组配置分到的资源就越少,这样早期的评估结果可能不准确。反之如果超参数的数量越小,每组超参数配置的评估会越准确,但有可能无法得到最优的配置。

5. 神经架构搜索

上面介绍的超参数优化方法都是在固定(或变化比较小)的超参数空间中进行最优配置搜索,而最重要的神经网络架构一般还是需要由有经验的专家来
进行设计。从某种角度来讲,深度学习使得机器学习中的“特征工程”问题转变为“网络架构工程”问题 。

神经架构搜索( Neural Architecture Search , NAS )是一个新的比较有前景的研究方向,通过神经网络来自动实现网络架构的设计。一个神经网络的架构可以用一个变长的字符串来描述。利用元学习的思想,神经架构搜索利用一个控制器来生成另一个子网络的架构描述。 控制器可以由一个循环神
经网络来实现。控制器的训练可以通过强化学习来完成,其奖励信号为生成的子网络在开发集上的准确率 。

神经架构搜索的原理是给定一个称为搜索空间的候选神经网络结构集合,用某种策略从中搜索出最优网络结构。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章