干货 | 深度学习模型超参数搜索实用指南
https://mp.weixin.qq.com/s/wG_N6hKlKXcrXrAhzj3QwQ
乾明 整理编译自 FloydHub Blog
量子位 报道 | 公众号 QbitAI
在文章开始之前,我想问你一个问题:你已经厌倦了小心翼翼地照看你的深度学习模型吗?
如果是的话,那你就来对地方了。
近日,FloydHub Blog发表了一篇文章,详细讨论了为深度学习模型寻找最佳超参数集的有效策略。
文章在一开头就说,读完之后能够让你在找最佳配置的过程中变得事半功倍。
要知道,与机器学习模型不同,深度学习模型里面充满了各种超参数。而且,并非所有参数变量都能对模型的学习过程产生同样的贡献。
考虑到这种额外的复杂性,在一个多维空间中找到这些参数变量的最佳配置并不是件容易的事情。
每一位科学家和研究人员,都希望在现有的资源条件下(计算、金钱和时间),找到最佳的模型。
通常情况下,研究人员和业余爱好者会在开发的最后阶段尝试一种搜索策略。这可能会有助改进他们辛辛苦训练出来的模型。
此外,在半自动/全自动深度学习过程中,超参数搜索也是的一个非常重要的阶段。
说了这么久,你可能已经等不及了吧?
好的,暖场结束,让我们进入正题~
超参数到底是什么?
先让我们从最简单的定义开始:
超参数是在构建机器/深度学习模型时可以转动的旋钮。
或者这样说:
超参数是开始训练前,用预先确定的值,手动设置的所有训练变量。
我们应该都会认可Learning Rate和Dropout Rate是超参数,但是模型设计变量呢?比如嵌入、层数、**函数等。我们是否应该将这些变量视为超参数?
△模型设计变量 + 超参数→模型参数
简单起见,我们也将模型设计变量视为超参数集的一部分。
那么,从训练过程中获得的参数,以及从数据中获得的变量应该怎么考虑呢?这被称为模型参数。我们将把它们排除在超参数集之外。
让我们来举个例子。请看下图,用一个例子说明了深度学习模型中变量的不同分类。
△变量分类示例
我们的下一个问题:搜索的代价很高
寻找超参数的最佳配置,通常会面临的挑战是,超参数搜索是一个受计算、金钱和时间约束的迭代过程。
△超参数搜索周期
从一个有潜力的配置的猜测(步骤1 )开始,等到一次完整的训练(步骤2 )结束后,来获得对相关有益度量的实际评估(步骤3 )。然后,我们将跟踪搜索过程(步骤4 ),再根据我们的搜索策略,选择新的猜测(步骤1 )。
我们会一直这样下去,直到我们结束。通常情况下,是钱或者时间用完了。
让我们来谈谈策略
我们有四种主要策略可用于搜索最佳配置:
Babysitting,又名试错(Trial & Error)
网格搜索(Grid Search)
随机搜索(Random Search)
贝叶斯优化(Bayesian Optimization)
Babysitting
在学术领域,Babysitting也被称为“试错”或“研究生下降”(Grad Student Descent)。这种方法是100%的手工操作,通常被研究人员、学生和业余爱好者采用。
流程非常简单:比如一个学生设计一个新的实验后,她会遵循学习过程的所有步骤,从数据收集到特征映射可视化,然后她会按照顺序迭代超参数,直到她到了截止日期或耗完了其他的驱动力。
△Babysitting
当然,如果你上过deeplearning.ai的课程,你对这种方法应该会很熟悉。这就是吴恩达教授所描述的熊猫工作流程。
这种方法非常有教育意义。但是,在一个团队或者一个公司里,这种方法并不适用,因为数据科学家的时间是非常宝贵的。
这就给我们提出了一个问题:
“有没有更好的方法来利用我们的时间?”
当然有,我们可以通过定义一个自动的超参数搜索策略来利用你的时间。
网格搜索
网格搜索,是一种简单尝试所有可能配置的方法。
下面是工作流程:
在n维上定义一个网格,其中每一个映射代表一个超参数。例如,n= (learning_rate, dropout_rate, batch_size)
对于每个维度,定义可能值的范围:例如batch _ size = [ 4、8、16、32、64、128、256 ]
搜索所有可能的配置并等待结果来建立最佳配置:例如 C1 = (0.1, 0.3, 4) -> acc = 92%, C2 = (0.1, 0.35, 4) -> acc = 92.3%, 等等……
下图展示了一个简单的二维网格搜索的Dropout和Learning rate。
△并行执行两个变量的网格搜索
通常情况下,这种并行策略会使人为难,因为它没有考虑到计算背景。使用网格搜索,你拥有的计算资源越多,你能同时尝试的猜测就会越多。
这种方法的真正痛点被称为维数灾难。即我们增加的维度越多,搜索就变得越困难,最终会导致这种策略难以为继。
当维度小于或等于4时,可以使用这种方法。但在实践中,即使它能保证最终找到最佳配置,它仍然是不可取的。相反,最好使用随机搜索。
随机搜索
几年前,Bergstra和Bengio发表了一篇论文,论证了网格搜索的效率低下。
网格搜索和随机搜索之间唯一真正的区别是第一步:随机搜索从配置空间中随机选择点。
让我们使用下面的一些图片,来展示研究人员的论证结果。
△网格搜索 vs 随机搜索
图片中, 主要是通过在两个超参数空间上搜索最佳配置来比较这两种方法。它还假设一个参数比另一个更重要。
这是一个安全的假设,正如开头提到的那样,深度学习模型中确实充满了各种超参数,通常研究者/科学家/学生知道哪些参数对训练的影响最大。
在网格搜索中,我们很容易注意到,即使我们训练了9个模型,但每个变量只使用了3个值。
在随机搜索中,多次地选择相同变量的可能性微乎其微。如果使用第二种方法,每个变量会使用9个不同值来训练9个模型。
划重点:如果你的搜索空间包含3到4个维度,不要使用网格搜索。相反,使用随机搜索,它会为每个搜索任务提供一个非常好的基准。
△网格搜索和随机搜索的优缺点
后退一步,前进两步
另外,当你需要为每个维度设置空间时,为每个变量设定正确的尺度是非常重要的。
△批次大小和learning rate的通用比例空间
例如,使用批量大小的值作为2的幂,并且在日志中对learning rate进行抽样是很常见的。
△放大!
另一个很常见的做法是,在一定次数的迭代中,从上面的一个布局开始,然后通过在每个变量范围内更密集地采样,来放大有潜力的子空间,甚至用相同或不同的搜索策略开始新的搜索。
还有一个问题:独立猜测
不幸的是,网格搜索和随机搜索有一个共同的缺点:
“每个新的猜测都独立于之前的运行!”
相比之下,Babysitting的优势就显现出来了。Babysitting之所以有效,是因为科学家有能力利用过去的猜测,并将其作为改进下一步工作的资源,来有效地推动搜索和实验。
等一下,这听起来很熟悉……如果我们试着将超参数搜索作为一个机器学习任务来建模呢?会发生什么?
好了,请允许我“请出”贝叶斯优化。
贝叶斯优化
这种搜索策略是建立一个代理模型,试图从超参数配置中预测我们关心的度量指标。
在每一次迭代中,代理将会变得越来越有信心,新的猜测会带来新的改进。像其他搜索策略一样,它也会等到一切都耗尽的时候停止。
△贝叶斯优化工作流程
这好像听起来让人有点懵逼,不要担心,我们再来举一个例子。
高斯过程
高斯过程( Gaussian Process )不仅会产生预测值,还会给我们一个不确定性的范围,通常是均值和方差。
让我们来深入研究一下这个很棒的教程提供的例子。
传送门:https://www.iro.umontreal.ca/~bengioy/cifar/NCAP2014-summerschool/slides/Ryan_adams_140814_bayesopt_ncap.pdf
△2点高斯过程
在上图中,我们在单个变量上(横轴上)遵循高斯过程优化的第一步。在这个例子中,可以代表learning rate或dropout rate。
在纵轴上,我们将某个度量指标绘制为单个超参数的函数。因为我们在寻找尽可能低的值,所以我们可以把它看作损失函数。
黑点代表迄今为止训练出来的模型。红线是真实值(ground truth),换句话说,是我们试图学习的函数。
黑线表示我们对真实值函数假设的平均值,灰色区域表示空间中的不确定性或方差。
正如我们能注意到的,点周围的不确定性减少了,因为我们对这些点周围的结果非常有信心,主要是因为我们已经在这里训练了模型。
因此,在信息较少的领域,不确定性会增加。
既然已经定义了起点,我们已经准备好选择下一个有潜力的变量来训练模型。我们需要定义一个采集函数,来告诉我们在哪里采样下一个配置。
在这个例子中,我们使用了Expected Improvement:如果我们使用不确定性区域中的推荐配置,这个函数的目的是为了找到尽可能低的值。
上面图表中的蓝点显示了Expected Improvement函数为下一次训练选择的点。
△3点高斯过程
我们训练的模型越多,代理对下一个有潜力采样的点就越有信心。以下是经过8次训练后的模型图表:
△8点高斯过程
高斯过程属于一类称为基于序列模型的优化(SMBO)的算法。正如我们刚刚看到的,这些算法为搜索最佳超参数提供了非常好的基准。
但是,就像所有工具一样,它们也有缺点:
根据定义,这个过程是循序渐进的
它只能处理数字参数
如果训练表现不佳,它也没有任何机制来终止训练
请注意,对这个话题,我们只是浅尝辄止,如果你想深入研究,并对如何扩展SMBO感兴趣,可以看看这篇论文。
传送门:https://www.cs.ubc.ca/~hutter/papers/10-TR-SMAC.pdf
搜索策略比较
好了,具体的搜索策略已经介绍完了,是时候总结一下了,这样才能更好地了解每个方案的优缺点。
△总结
只要你或你的团队不受资源的约束,贝叶斯SMBO可能是最好的选择,但是你也应该考虑建立一个随机搜索的基准。
另一方面,如果你还在学习或处于开发阶段,即使在空间探索方面不切实际,Babysitting也是可行的。
正如我在上一节中提到的,如果一个训练表现不佳,这些策略都不能提供节省资源的机制,我们必须等到计算结束。
这就引申出了这样的一个问题:
“我们能优化训练时间吗?”
让我们来研究研究。
提前停止的力量
提前停止,不仅是一种著名的正则化技术,而且在训练方向不正确时,它还是一种能够防止资源浪费的机制。
下面是最常用的停止标准的图表:
前三个标准不用多说,大家都明白,所以让我们把注意力集中在最后一个标准上。
通常情况下,研究者都会根据实验类别来限定训练时间。这可以优化团队内部的资源。
在训练模型的过程时,可以手动应用这些标准,或者通过最常见的框架中提供的钩子/回调组件,将这些规则集成到实验中,你可以做得更好,比如说:
Keras提供了一个很好的提前停止功能,甚至还有一套回调组件。由于Keras最近已经集成到了Tensorflow中,你可以使用Tensorflow代码中的回调组件。
Tensorflow提供了训练钩子,这些钩子可能不像Keras回调那样直观,但是它们能让你对执行状态有更多的控制。
Pytorch还没有提供钩子或回调组件,但是你可以在论坛上查看TorchSample报告。我不太清楚Pytorch 1.0的功能列表,这个功能可能会随新版本一起发布。
Fast.ai库也提供回调组件,即使它目前没有提供任何类型的文档( WIP ),你也可以在这里找到一个不错的教程。
传送门:https://github.com/sgugger/Deep-Learning/blob/master/Using%20the%20callback%20system%20in%20fastai.ipynb
Ignite ( Pytorch的高级库)提供类似于Keras的回调,虽然还在开发阶段,但它看起来确实是一个不错的选择。
这并不是结束
机器学习有一个子领域叫做“AutoML” (Automatic Machine Learning,自动机器学习),目的是将模型选择、特征提取和/或超参数优化变得自动化。
这就引申出了这个指南的最后一个问题:
“我们能了解整个过程吗?”
你可以认为,AutoML是一个解决了另一个机器学习任务的机器学习任务。本质上是元机器学习。
研究:AutoML和PBT
你很可能听说过谷歌的AutoML。神经网络结构搜索是AutoML的子领域,目的是为给定任务找到最佳模型。关于这个主题的全面讨论需要一系列文章。幸运的是,Fast.ai的Rachel Thomas博士做了一份很棒的工作。
传送门:http://www.fast.ai/2018/07/12/auto-ml-1/
我想和大家分享另一个来自 DeepMind 的有趣的研究成果,他们使用遗传算法的一种变体来执行超参数搜索,称为基于群体的训练(Population Based Training)。
PTB 也是 DeepMind 的另一项令人惊讶的研究的基础,我强烈建议你去看看,(传送门:https://deepmind.com/blog/capture-the-flag/)。 引用自DeepMind:
就像随机搜索一样,PBT首先需要以随机超参数的方式训练许多并行的网络。但是这些网络并不是独立训练的,而是使用其它网络的训练信息来修正这些超参数,并将计算资源分配到那些有潜力的模型上。这种方法的灵感来自于遗传算法:其中一个群体中的每个个体(worker),可以利用除自身外其余个体的信息。例如,个体可能会从表现较好的个体那里复制模型参数,它还能通过随机改变当前的值而探索新的超参数集。
当然,在这一领域可能还有许多其他超级有趣的研究。在这里,我只是和大家分享了最近得到媒体关注的一些研究。
希望你能够有所收获~
原文链接:https://blog.floydhub.com/guide-to-hyperparameters-search-for-deep-learning-models/