首页 股吧 正文

[华夏回报前002001]机器学习算法如何调参?这里有一份神经网络学习速率设置指南

2024-01-31 11:01:06 1
admin
每个机器学习的研究者都会面对调参进程的检测,而在调参进程中,学习速率(learning rate)的调整则又是十分重要的一部分。学习速率代表了神经网络中随时刻推移,信息累积的速度。在抱负情况下,咱们会以很大的学习速率开端,逐渐减小速度,直至丢失值不再发散。不过,说来简略做来难,本文作者对学习速率的调整思路进行了扼要介绍,希望能够对你有所协助。

在之前的文章里,我现已讲了怎么用反向传达和梯度下降来练习神经网络。为了练习神经网络,其间一个需求设置的要害超参数是学习率。提示一下,为了最小化此网络的丢失函数,这个参数缩放了权重更新的起伏。

假如你把学习率设置太低,练习会发展的很慢:由于你在网络的权重上只做了很少的调整。可是,假如你的学习率被设置的太高,它或许在你的丢失函数上带来不抱负的成果。我现已可视化了这些事例——假如你发现这些图很难了解,我主张你事前参阅一下(至少)我此前发布的关于梯度下降的榜首部分。

所以,咱们怎样找到最优学习速率呢?

让咱们看看 Tesla AI 主管、李飞飞高徒 Andrej Karpathy 怎么说:

推文:3e-4 是对 Adam 最好的学习速率,妥妥地~

完美,我觉得我的作业完结了

好吧,并没有……

第二条推:我想承认一下每个人都知道这是个打趣吧……?

神经网络的丢失函数地图(loss landscape)(下图所示)是网络参数值的函数,当在特定数据集上履行揣度(猜测)时量化与运用特定参数装备相关的「差错」。这个丢失地图或许关于很类似的网络架构也看起来很不同。下图来自论文《Visualizing the Loss Landscape of Neural Nets》,其间展现了残差衔接可发生更滑润的拓扑结构。

最优学习率取决于你的丢失地图的拓扑结构,也便是由你的模型结构和数据集。当你用默许的学习率(由你的深度学习库主动决议)能够供给一个差不多的成果,你也能够经过搜索最优学习率来进步体现。我希望你鄙人一部分发现这很简略。

一个找寻最优学习速率的系统化办法

终究,咱们希望得到一个学习率,极大地削减网路丢失。咱们能够在逐渐进步每一次小批量(迭代)的学习速率的一起经过做一个简略试验来调查,记载每一次增量之后的丢失。这个逐渐的增加能够是线性或指数的。

关于太慢的学习速率来说,丢失函数或许减小,可是依照十分浅陋的速率减小的。当进入了最优学习率区域,你将会调查到在丢失函数上一次十分大的下降。进一步增加学习速率会形成丢失函数值「跳来跳去」甚至在最低点邻近发散。记住,最好的学习速率调配着丢失函数上最陡的下降,所以咱们首要重视剖析图的斜度。

你应该为这个试验设置你的学习率边界然后你能看到一切的三个阶段,保证辨认最优规模。

[华夏回报前002001]机器学习算法如何调参?这里有一份神经网络学习速率设置指南

设置时刻表以在练习中调整你的学习率

另一个咱们常用的技巧是学习速率退火(learning rate annealing),引荐咱们先从一个比较高的学习速率开端然后慢慢地在练习中下降学习速率。这个办法背面的思维是咱们喜爱快速地从初始参数移动到一个参数值「好」的规模,但这之后咱们又想要一个学习速率小到咱们能够开掘「丢失函数上更深且窄的当地」,(来自 Karparthy 的 CS231n 课程笔记:cs231n.github.io/neural-networks-3/# annealing-the-learning-rate)。假如你很难幻想我方才所言,回想一下太高的学习速率能够形成参数更新会在最小值和随后的更新间「跳来跳去」,这点子会形成在极小值规模内持续的有噪声的收敛,或许在更极点的比如里或许形成从最小值发散出去。

学习速率退火的最盛行办法是「步衰减」(Step Decay),其间学习率经过必定数量的练习 epochs 后下降了必定的百分比。

更常见的,咱们能够创立一个学习速率时刻表(learning rate schedule),便是在练习期间依据特定规矩来更新学习速率。

周期性学习率

在上述论文中《Cyclical Learning Rates for Training Neural Networks》中,Leslie Smith 提出了一种周期性学习率表,可在两个束缚值之间改变。如下图所示,它是一个三角形更新规矩,但他也说到怎么运用这一规矩与固定周期衰减或指数周期衰减相结合。

留意:在本文终究,我将给出完结这一学习率的代码。因而,假如你不关心数学公式的了解,能够越过该部分。

咱们能够将其写为:

其间 x 被界说为

而且 cycle 被核算为

其间η_min 和η_max 界说学习率的边界,iterations 表征已完结的小批量(mini-batches)的数量,stepsize 界说了一个周期长度的一半。据我所知,1?x 一向为正,因而看起来 max 操作并非肯定必要。

为了搞了解这一方程式怎么作业,让咱们逐渐使用可视化构建它。关于下面的视觉作用,三个完好周期的三角形更新以 100 次迭代的步长显现。记住,一次迭代对应于一个小批量的练习。

最重要的是,咱们能够在练习期间依据咱们已完结的半个周期来确认「进程」。咱们用半周期而不是全周期来衡量咱们的进程,然后就能够在一个周期内完结对称(后边你会愈加明晰认识到这点)。

接下来,咱们把半周期进程与在当时周期完结时的半周期数量进行比照。当一个周期开端时,咱们有两个半周期要完结;当一个周期完毕时,该值到达零。

再接下来,咱们将该值加 1,然后把函数移为以 y 轴为中心。现在咱们参阅半周期点展现一个周期内的进程。

在该点上,咱们取肯定值以在每个周期内完结一个三角形。这便是咱们分配给 x 的值。

可是,咱们希望学习率表从最小值开端,在周期中心增加到最大值,然后再下降到最小值。咱们可经过简略核算 1-x 来完结这一点。

经过把学习率规模的一部分增加到最小学习率(也称为根本学习率),现在咱们有了一个能够调整学习率的值。

Smith 写到,周期性学习率背面的首要理论假定(与下降学习率相对反)是「增加学习率或许有一个短期的负面影响,但却获得了长时刻的正面影响」。的确,他的论文包括若干个丢失函数演化的实例,与基准固定学习率比较,它们暂时违背到较高的丢失,并终究收敛到较低的丢失。

为了直观了解这一短期影响怎么带来长时刻的正面作用,重要的是了解咱们收敛最小值的希望特征。终究,咱们想要咱们的网络以一种泛化到不行见数据的办法从数据中学习。从而,具有杰出泛化才能的网络是应该是鲁棒的,参数的小改变并不会太大影响功能。考虑到这一点,尖利的极小值导致很差的泛化才能也就合理了,正如参数值的小改变会导致巨大的较高丢失。经过答应咱们的学习率在次数上增加,咱们能够「跳出」尖利的极小值,虽然这会暂时增加丢失,但或许终究收敛到愈加抱负的极小值。

留意:虽然「杰出泛化的恰当极小值」已被广泛承受,但也存在很有力的反论(arxiv.org/abs/1703.04933)。

此外,增加学习率答应「更快速地穿越鞍点高原」。如下图所见,鞍点上梯度能够十分小。由于参数更新是一个梯度函数,这导致咱们优化进程十分短;在这里增加学习率能够防止在鞍点卡住太久,这很有用。

留意:依据界说,鞍点是一个临界点,其间一些维度观测部分极小值,另一些维度观测部分极大值。由于神经网路存在数千或数百万个参数,在一切维度上观测一个真实的部分极小值不太实际;这便是鞍点呈现的含义。当我说到「尖利的极小值」,实际上咱们应该描画一个鞍点,其间极小值维度十分峻峭,极大值维度十分广大(如下图所示)。

带有热重启的随机梯度下降(SGDR)

带有热重启的随机梯度下降(SGDR)与周期性办法很类似,其间一个活跃的退火表与周期性「再发动」融合到原始的初始学习率之中。

咱们能够将其写为

其间η_t 是时刻步 t 的学习率,(在每一个 mini batch 间增加)和界说抱负学习率的规模,T_current 表征前次再发动之后 epoch 的数量,T_i 界说周期之中 epoch 的数量。让咱们试着分化这个等式。

这个退火表依赖于余弦函数,其在-1 和 1 之间改变。能够取 0 到 1 之间的值,这是咱们的余弦函数的输入。余弦函数的相应区域鄙人图用绿色杰出显现。经过增加 1,咱们的函数在 0 到 2 之间改变,然后缩小 1/2,现在在 0 到 1 之间改变。因而,咱们简略地取极小值学习率,并增加指定学习率规模的一部分。由于这一函数从 1 开端并降为 0,成果是一个从特定规模的极大值开端并衰减为极小值的学习率。一旦咱们的周期完毕,T_current 重置为 0,咱们从极大值学习率再开端循环这一进程。

作者也发现这个学习速率安排表能够适用于:

当练习进行时延伸周期 在每一周期之后衰减??和 在每一次重启的时分彻底地进步学习速率,咱们能够本质上的退出一个部分低点而且持续探究丢失地图。

十分酷的主见:在每一轮循环后截图一下权重,研究员能够经过练习单个模型去树立一个全套模型。这是由于从一个周期到另一个周期,这个网络「沉积」在不同的部分最优,像鄙人面图中画的相同。

完结

找寻最优学习速率的和设定一个学习速率安排表都能够简略的用 Keras 的回调函数中使用。

寻觅最优学习速率规模

咱们能够写一个 Keras 回调函数,便是追寻与一个在确认规模内改变的线性的学习速率相调配的丢失函数。

from keras.callbacks import Callback import matplotlib.pyplot as plt class LRFinder(Callback): ''' A simple callback for finding the optimal learning rate range for your model + dataset. # Usage ```python lr_finder = LRFinder(min_lr=1e-5, max_lr=1e-2, steps_per_epoch=10, epochs=3) model.fit(X_train, Y_train, callbacks=[lr_finder]) lr_finder.plot_loss() # Arguments min_lr: The lower bound of the learning rate range for the experiment. max_lr: The upper bound of the learning rate range for the experiment. steps_per_epoch: Number of mini-batches in the dataset. epochs: Number of epochs to run experiment. Usually between 2 and 4 epochs is sufficient. # References Blog post: jeremyjordan.me/nn-learning-rate Original paper: arxiv.org/abs/1506.01186 ''' def __init__(self, min_lr=1e-5, max_lr=1e-2, steps_per_epoch=None, epochs=None): super().__init__() self.min_lr = min_lr self.max_lr = max_lr self.total_iterations = steps_per_epoch * epochs self.iteration = 0 self.history = {} def clr(self): '''Calculate the learning rate.''' x = self.iteration / self.total_iterations return self.min_lr + (self.max_lr-self.min_lr) * x def on_train_begin(self, logs=None): '''Initialize the learning rate to the minimum value at the start of training.''' logs = logs or {} K.set_value(self.model.optimizer.lr, self.min_lr) def on_batch_end(self, epoch, logs=None): '''Record previous batch statistics and update the learning rate.''' logs = logs or {} self.iteration += 1 K.set_value(self.model.optimizer.lr, self.clr()) self.history.setdefault('lr', []).append(K.get_value(self.model.optimizer.lr)) self.history.setdefault('iterations', []).append(self.iteration) for k, v in logs.items(): self.history.setdefault(k, []).append(v) def plot_lr(self): '''Helper function to quickly inspect the learning rate schedule.''' plt.plot(self.history['iterations'], self.history['lr']) plt.yscale('log') plt.xlabel('Iteration') plt.ylabel('Learning rate') def plot_loss(self): '''Helper function to quickly observe the learning rate experiment results.''' plt.plot(self.history['lr'], self.history['loss']) plt.xscale('log') plt.xlabel('Learning rate') plt.ylabel('Loss') **设置一个学习速率表** **步衰减** 关于一个简略的步衰减(step decay),咱们能够用 LearningRateScheduler 回调。 import numpy as np

from keras.callbacks import LearningRateScheduler

def step_decay_schedule(initial_lr=1e-3, decay_factor=0.75, step_size=10):

''' Wrapper function to create a LearningRateScheduler with step decay schedule. ''' def schedule(epoch): return initial_lr * (decay_factor ** np.floor(epoch/step_size)) return LearningRateScheduler(schedule) lr_sched = step_decay_schedule(initial_lr=1e-4, decay_factor=0.75, step_size=2)

model.fit(X_train, Y_train, callbacks=[lr_sched])

**周期性学习速率** 要使用周期性学习速率技巧,咱们能够参阅这个 repo(github/bckenstler/CLR),其已在论文中完结了该技能。实际上这个 repo 已在论文附录中被引证。 **带有重启的随机梯度下降** 要使用这个 SGDR 技巧,咱们能够参阅:github/keras-team/keras/pull/3525/files? _原文链接:.jeremyjordan.me/nn-learning-rate/_ [](javascript:;)[](javascript:;)[ ](javascript:;) 原文作者Jeremy Jordan,由机器之心编译出品,参加:黄小天、许迪 #机器学习、神经网络、算法#原文发布于宽客论坛,点击阅览原文
收藏
分享
海报
1