深度学习实用方法 - 选择超参数篇

序言

在深度学习的浩瀚领域中,超参数的选择无疑是通往卓越模型性能的一把关键钥匙。超参数,作为训练前设定的、用于控制学习过程而非通过学习自动获得的参数,如学习率、批量大小、网络层数及节点数等,直接影响着模型的收敛速度、泛化能力及最终性能。它们如同精心调配的食谱中的调味料,微妙地改变着模型的"味道"。因此,如何智慧地选择超参数,成为了每一个深度学习研究者与工程师必须面对的挑战与机遇。

选择超参数

  • 大部分深度学习算法都有许多超参数来控制算法。有些超参数会影响算法运行的时间和存储成本。有些超参数会影响学习到的模型质量,以及在新输入上推断正确结果的能力。
  • 有两种选择超参数的基本方法:手动选择和自动选择。
    • 手动选择超参数需要了解超参数做了些什么,以及机器学习模型如何取得良好的泛化。
    • 自动选择超参数算法大大减少了解这些想法的需要,但它们往往需要更高的计算成本。

手动调整

  • 手动设置超参数,我们必须了解超参数,训练误差,泛化误差和计算资源(内存和运行时间)之间的关系。这需要切实了解应用数学与机器学习基础 - 学习算法篇的有效容量。
  • 手动搜索超参数的目标通常是:最小化受限于运行时间和内存预算的泛化误差。我们不去探讨如何确定各种超参数对运行时间和内存的影响,因为这高度依赖于平台。
  • 手动搜索超参数的主要目标是 :调整模型的有效容量以匹配任务的复杂性。
    • 有效容量受限于三个因素:模型的表示容量,学习算法成功最小化训练模型成本函数的能力,以及代价函数和训练过程正则化模型的程度。
    • 具有更多网络层,每层有更多隐藏单元的模型具有较高的表达能力------能够表示更复杂的函数。然而,如果训练算法不能找到合适的函数来最小化训练代价,或是如果正则化项,如权重衰减,排除了这些函数,那么模型就不能学习到所有这些函数。
  • ++当泛化误差以某个超参数为变量,作为函数绘制出来时,通常会表现为 U \text{U} U 形曲线,如[图例1](#当泛化误差以某个超参数为变量,作为函数绘制出来时,通常会表现为 U \text{U} U 形曲线,如图例1所示)所示++ 。
    • 在某个极端情况下, 超参数对应着低容量,并且泛化误差由于训练误差较大而很高。这便是欠拟合的情况。
    • 另一种极端情况, 超参数对应着高容量,并且泛化误差由于训练误差和测试误差之间的差距较大而很高。最优的模型容量位于曲线中间的某个位置,能够达到最低可能的泛化误差,由中等的泛化误差和中等的训练误差相加构成。
  • 超参数数值太大时,会发生过拟合。
    • 例如,中间层隐藏单元数量太大时,会发生过拟合。因为隐藏单元数量增多提高了模型容量。 超参数数值太小时,也会发生过拟合。
    • 例如,权重衰减系数为零时,学习算法具有最大的有效容量,容易过拟合。
  • 并非每个超参数都能对应着完整的 U \textbf{U} U 形曲线。
    • ++很多超参数是离散的++ ,如中间层单元数目或是 maxout \text{maxout} maxout 单元中线性元件的数目,这种情况只能沿曲线探索离散的点。
    • ++有些超参数是二值的。++通常这些超参数用来指定是否使用学习算法中的一些可选部分,如预处理步骤减去均值,除以标准差,标准化输入特征。这些超参数只能探索曲线上的两点。
    • ++其他一些超参数可能会限制其探索曲线某部分的最大值或最小值。++例如,权重衰减系数最小是零。这意味着,如果权重衰减系数为零时模型欠拟合,那么我们将无法通过修改权重衰减系数探索过拟合区域。换言之,有些超参数只能减少模型容量。
  • 学习率可能是最重要的超参数
    • 如果你只有时间调整一个超参数,那就调整学习率。
    • 相比其他超参数,它以一种更复杂的方式控制模型的有效容量------当学习率适合优化问题时,模型的有效容量最高,此时学习率既不是特别大也不是特别小。
    • 学习率关于训练误差具有 U \text{U} U 形曲线,在图例2所示。
    • 当学习率过大时,梯度下降可能会不经意地增加而非减少训练误差。在理想化的二次情况下,如果学习率是最佳值的两倍大时,会发生这种情况 ( LeCun et al., 1998a \text{LeCun et al., 1998a} LeCun et al., 1998a)。
    • 当学习率太小,训练不仅慢,还有可能永久停留在一个很高的训练误差。关于这种情况,我们知之甚少(不会发生于一个凸损失函数中)。
  • 调整学习率外的其他参数时,需要同时监测训练误差和测试误差,以判断您的模型是否过拟合或欠拟合,然后适当调整其容量。
  • 如果训练集错误率大于目标错误率,那么只能增加模型容量以改进模型。如果没有使用正则化,并且确信优化算法正确运行,那么有必要添加更多的网络层或隐藏单元。然而,令人遗憾的是,这增加了模型的计算代价。
  • 如果测试集错误率大于目标错误率,那么可以采取两个方法。
    • 测试误差是训练误差和测试误差之间差距与训练误差的总和。
    • 寻找最佳的测试误差需要权衡这些数值。当训练误差较小(因此容量较大),测试误差主要取决于训练误差和测试误差之间的差距时,通常神经网络效果最好。
    • 此时目标是缩小这一差距,使训练误差的增长速率不快于差距减小的速率。
    • 要减少差距,我们可以改变正则化超参数,以减少有效的模型容量,如添加 Dropout \text{Dropout} Dropout或权重衰减。
    • 通常,最佳性能来自正则化得很好的大规模模型,比如使用 Dropout \text{Dropout} Dropout的神经网络。
  • 大部分超参数可以通过推理其是否增加或减少模型容量来设置。如图表1所示部分示例。
  • 手动调整超参数时,不要忘记最终目标 :++提升测试集性能。++
    • 加入正则化只是实现这个目标的一种方法。只要训练误差低,随时都可以通过收集更多的训练数据来减少泛化误差。
    • 实践中能够确保学习有效的的暴力方法就是不断提高模型容量和训练集的大小,直到解决问题。这种做法增加了训练和推断的计算代价,所以只有在拥有足够资源时才是可行的。原则上,这种做法可能会因为优化难度提高而失败,但对于许多问题而言,优化似乎并没有成为一个显著的障碍,当然,前提是选择了合适的模型。

自动超参数优化算法

  • 理想的学习算法应该是只需要输入一个数据集,就可以输出学习的函数,而不需要手动调整超参数。一些流行的学习算法,如++逻辑回归++ 和++支持向量机++,流行的部分原因是这类算法只有一到两个超参数需要调整,它们也能表现出不错的性能。有些情况下,所需调整的超参数数量较少时,神经网络可以表现出不错的性能;但超参数数量有几十甚至更多时,效果会提升得更加明显。当用户有一个很好的初始值,例如由在相同类型的应用和架构上具有经验的人确定初始值,或者用户在相似问题上,具有几个月甚至几年的神经网络超参数调整经验,那么手动调整超参数能有很好的效果。然而,对于很多应用而言,这些起点都不可用。在这些情况下,自动算法可以找到合适的超参数。
  • 如果我们思考用户搜索学习算法合适超参数的方式,我们会意识到这其实是一种优化:我们在试图寻找超参数来优化目标函数,例如验证误差,有时还会有一些约束(如训练时间,内存或识别时间的预算)。
  • 因此,原则上有可能开发出封装学习算法的超参数优化 ( hyperparameter optimization \text{hyperparameter optimization} hyperparameter optimization) 算法,并选择其超参数,从而用户不需要指定学习算法的超参数。令人遗憾的是, 超参数优化算法往往有自己的(次级) 超参数,如学习算法的每个超参数的值应该被探索的范围。然而,这些次级超参数通常很容易选择,这是说,相同的次级超参数能够很多不同的问题上具有良好的性能。

网格搜索

  • 当有三个或更少的超参数时,常见的超参数搜索方法是网格搜索 ( grid search \text{grid search} grid search)。
    • 对于每个超参数,用户选择一个较小的有限值集去探索。
    • 然后,这些超参数笛卡尔乘积为一组组超参数,网格搜索使用每组超参数训练模型。
    • 挑选验证集误差最小的超参数。如图例3所示超参数值的网络。
  • 应该如何选择搜索集合的范围呢?
    • 在超参数是数值(有序)的情况下,每个列表的最小和最大的元素可以基于先前相似实验的经验保守地挑选出来,以确保最优解非常可能在所选范围内。
    • 通常,网格搜索大约会在对数尺度 ( logarithmic scale \text{logarithmic scale} logarithmic scale) 下挑选合适的值,例如,一个学习率的取值集合是 { 0.1 , 0.01 , 1 0 − 3 , 1 0 − 4 , 1 0 − 5 } \{0.1,0.01,10^{-3},10^{-4},10^{-5}\} {0.1,0.01,10−3,10−4,10−5},或者隐藏单元数目的取值集合 { 50 , 100 , 200 , 500 , 1000 , 2000 } \{50,100,200,500,1000,2000\} {50,100,200,500,1000,2000}。
    • 通常重复进行网格搜索时,效果会最好。例如,假设我们在集合 { − 1 , 0 , 1 } \{-1,0,1\} {−1,0,1}上网格搜索超参数 α \alpha α。如果找到的最佳值是 1 1 1,那么说明我们低估了最优值 α \alpha α 所在的范围,应该扩大搜索范围,例如在集合 { 1 , 2 , 3 } \{1,2,3\} {1,2,3} 中搜索。如果最佳值是 0 0 0,那么我们不妨通过细化搜索范围以改进估计,在集合 { − 0.1 , 0 , 0.1 } \{-0.1,0,0.1\} {−0.1,0,0.1} 上进行网格搜索。
  • 网格搜索带来的一个明显问题是,计算代价会随着超参数数量呈指数级增长。如果有 m m m 个超参数,每个至少取 n n n 个值,那么训练和估计所需的试验数将是 O ( n m ) \Omicron(n^m) O(nm)。可以并行地进行实验,并且并行要求十分宽松(不同搜索的机器之间几乎没有必要进行通信)。令人遗憾的是,由于网格搜索指数级增长计算代价,即使是并行,我们也无法提供令人满意的计算能力。

随机搜索

  • ++幸运的是,有一个替代网格搜索的方法,并且编程简单,使用更方便,能更快地收敛到超参数的良好取值++ : 随机搜索 ( Bergstra and Bengio, 2012 \text{Bergstra and Bengio, 2012} Bergstra and Bengio, 2012)。

  • 随机搜索过程如下。首先,我们为每个超参数定义一个边缘分布,例如, Bernoulli \text{Bernoulli} Bernoulli分布或分类分布(对应着二元超参数或离散超参数),或者对数尺度上的均匀分布(对应着正实值超参数)。例如:
    { log_learning_rate ∼ u ( − 1 , − 5 ) --- 公式1 learning_rate = 1 0 log_learning_rate --- 公式2 \begin{cases} \begin{aligned} \text{log\_learning\_rate} &\sim u(-1,-5) &\quad\textbf{---\footnotesize{公式1}}\\ \text{learning\_rate}&=10^{\text{log\_learning\_rate}} &\quad\textbf{---\footnotesize{公式2}}\\ \end{aligned} \end{cases} {log_learning_ratelearning_rate∼u(−1,−5)=10log_learning_rate---公式1---公式2

    其中, u ( a , b ) u(a,b) u(a,b)表示区间 ( a , b ) (a,b) (a,b)上均匀采样的样本。类似地, log_number_of_hidden_units \text{log\_number\_of\_hidden\_units} log_number_of_hidden_units可能表示在 u ( log ⁡ ( 50 ) , log ⁡ ( 2000 ) ) u(\log(50),\log(2000)) u(log(50),log(2000))上采样。

  • 和网格搜索不同,我们不需要离散化超参数的值,我们可以在一个更大的集合上进行搜索,而不产生额外的计算代价。

    • 实际上,如图例3所示,当有几个超参数对性能度量没有很强的影响时, 随机搜索指数级高效于网格搜索。
    • Bergstra and Bengio(2012) \text{Bergstra and Bengio(2012)} Bergstra and Bengio(2012) 进行了详细的研究,发现随机搜索比网格搜索要快得多地减小验证集误差(就每个模型运行的试验数而言)。
  • 与网格搜索一样,可以经常重复运行不同版本的随机搜索,以基于前一次运行的结果改进下一次搜索。

  • ++随机搜索能比网格搜索更快地找到良好超参数的原因是,没有浪费的实验,不像网格搜索有时会对一个超参数的两个不同值(给定其他超参数值不变)给出相同结果。++

    • 在网格搜索中,其他超参数将在这两次实验中拥有相同的值。
    • 而在随机搜索中,它们通常会具有不同的值。
  • 因此,如果这两个值的变化不能勉强使验证集误差有明显区别的话, 网格搜索没有必要重复两个等价的实验,而随机搜索仍然会对其他超参数进行两次独立地探索。

基于模型的超参数优化

  • 超参数搜索问题可以转化为一个优化问题。
    • 决策变量是超参数。
    • 优化的目标是最小化超参数训练出来的模型在验证集上的误差。
    • 在简化的设定下,可以计算验证集上可导误差函数关于超参数的导数,然后我们遵循这个导数更新 ( Bengio et al.,1999; Bengio, 2000; Maclaurin et al., 2015 \text{Bengio et al.,1999; Bengio, 2000; Maclaurin et al., 2015} Bengio et al.,1999; Bengio, 2000; Maclaurin et al., 2015)。
    • 令人遗憾的是,在大多数实际设定中,这个梯度是不可用的。
    • 这可能是因为其高额的计算代价和存储成本,也可能是因为验证集误差在超参数上本质不可导,例如超参数是离散值的情况。
  • 为了弥补导数这一不足,我们可以对验证集误差建模,然后通过优化该模型来提出新的超参数猜想。
    • 大部分基于模型的超参数搜索算法,都是使用贝叶斯回归模型来估计每个超参数的验证集误差期望,和该期望的不确定性。
    • 因此,优化涉及到探索(探索高度不确定的超参数,可能有重大效果提升,也可能效果很差)和使用(使用已经确信效果不错的超参数------通常是先前非常熟悉的超参数)之间的权衡。
    • 关于超参数优化,现在的方法还有 Spearmint(Snoek et al., 2012) \text{Spearmint(Snoek et al., 2012)} Spearmint(Snoek et al., 2012), TPE(Bergstra et al.,2011) \text{TPE(Bergstra et al.,2011)} TPE(Bergstra et al.,2011) 和 SMAC(Hutter et al., 2011) \text{SMAC(Hutter et al., 2011)} SMAC(Hutter et al., 2011)。
  • ++目前,我们无法明确确定,贝叶斯超参数优化是否是一个能够实现更好深度学习结果或是能够事半功倍的工具。++
    • 贝叶斯超参数优化有时表现得像人类专家,能够在有些问题上取得很好的效果,但有时又会在某些问题上发生灾难性的失误。
    • 看看它是否适用于一个特定的问题是值得尝试的,但目前该方法还不够成熟或可靠。
    • 就像所说的那样, 超参数优化是一个重要的研究领域,通常主要受深度学习所需驱动,但是它不仅能贡献于整个机器学习领域,还能贡献于一般的工程学。
  • ++大部分超参数优化算法比随机搜索更复杂,并且具有一个共同的缺点,在它们能够从实验中提取任何信息之前,它们需要运行完整的训练实验。++
    • 相比于人类实践者手动搜索,考虑实验早期可以收集的信息量,这种方法是相当低效的,因为手动搜索通常可以很早判断出某组超参数是否是完全病态的。
    • Swersky et al. (2014) \text{Swersky et al. (2014)} Swersky et al. (2014) 提出了一个可以维护多个实验的早期版本算法。
    • 在不同的时间点, 超参数优化算法可以选择开启一个新实验, ''冻结'' 正在运行但希望不大的实验,或是 ''解冻'' 并恢复早期被冻结的,但现在根据更多信息后又有希望的实验。

  • 图例1:容量和误差之间的典型关系。
    • 容量和误差之间的典型关系。

    • 说明:

      • 在图的左端, 训练误差和泛化误差都非常高。
      • 这是欠拟合期 ( underfitting regime \text{underfitting regime} underfitting regime)。
      • 当我们增加容量时, 训练误差减小,但是训练误差和泛化误差之间的间距却不断扩大。
      • 最终,这个间距的大小超过了训练误差的下降,我们进入到了过拟合期 ( overfitting regime \text{overfitting regime} overfitting regime),其中容量过大,超过了最佳容量 ( optimal capacity \text{optimal capacity} optimal capacity)。

  • 图例2:训练误差和学习速率之间的典型关系。
    • 训练误差和学习速率之间的典型关系。

    • 说明:

      • 要注意当学习速率大于最优值时误差会有显著的提升。
      • 此图是对于固定的训练时间,越小的学习速率有时候可以以一个正比于学习速率减小量的因素来减慢训练过程。
      • 泛化误差也会得到类似的曲线,由于正则项作用在学习速率过大或过小处比较复杂。
      • 由于一个糟糕的优化从某种程度上说可以避免过拟合,即使是训练误差相同的点也会拥有完全不同的泛化误差。

  • 图例3: 网格搜索和随机搜索的比较。
    • 网格搜索和随机搜索的比较。

    • 说明:

      • 为了方便地说明,我们只展示两个超参数的例子,但是通常我们关注的问题中超参数个数会更多。
      • 左图:
        • ++为了实现网格搜索++,我们为每个超参数提供了一个值的集合。
        • 搜索算法对每一种在这些集合的交叉积中的超参数组合进行训练。
      • 右图:
        • ++为了实现随机搜索++,我们给联合超参数赋予了一个概率分布。
        • 通常超参数之间是相互独立的。
        • 常见的这种分布的选择是均匀分布或者是对数均匀(从对数均匀分布中抽样,就是对从均匀分布中抽取的样本进行指数运算)的。
        • 然后这些搜索算法联合的超参数空间中采样,然后运行每一个样本。
      • ++网格搜索随机搜索都运行了验证集上的误差并返回了最优的解。++ 这个图说明了通常只有一个超参数对结果有着重要的影响。在这个例子中,只有水平轴上的超参数对结果有重要的作用。 网格搜索将大量的计算浪费在了指数级个数的对结果无影响的超参数中,相比之下随机搜索几乎每次测试都测试了对结果有影响的每个超参数的一个值。此图是从 Bergstra and Bengio (2011) \text{Bergstra and Bengio (2011)} Bergstra and Bengio (2011) 中复制的,并且经过了允许。

  • 图表1:各种超参数对模型容量的影响 。
超参数 容量何时增加 原因 注意事项
隐藏单元数量 增加 增加隐藏单元会增加模型的表示能力。 几乎模型每个操作所需的时间和内存代价都会随隐藏单元数量的增加而增加。
学习速率 调至最优 不正确的学习速率,不管是太高还是太低都会由于优化失败而导致低有效容量的模型。
卷积核宽度 增加 增加卷积核宽度会增加模型的参数数量。 较宽的卷积核导致较窄的输出尺寸,除非使用隐藏式零填充减少此影响,否则会降低模型容量。较宽的卷积核需要更多的内存存储参数,并会增加运行时间,但较窄的输出会降低内存代价。
隐式零填充 增加 在卷积之前隐式添加零能保持较大尺寸的表示。 大多数操作的时间和内存代价会增加。
权重衰减系数 降低 降低权重衰减系数使得模型参数可以变得更大。
Dropout比率 降低 较少地丢弃单元可以更多地让单元彼此"协力"来适应训练集。

总结

深度学习中超参数的优化是一场既需科学严谨又需创新思维的探索之旅。从随机搜索到网格搜索,再到更为高效的贝叶斯优化、遗传算法等智能方法,研究者们不断尝试与突破,力求在超参数空间中找到那条通往最佳性能的路径。同时,随着自动化机器学习( AutoML \text{AutoML} AutoML)技术的兴起,超参数的自动调优变得日益普及,这不仅极大地减轻了人工调参的负担,更使得深度学习模型的应用门槛进一步降低。然而,值得注意的是,尽管技术日新月异,但深入理解模型与数据的本质,结合实际问题灵活调整超参数,仍是取得卓越成果的关键。在深度学习的征途中,超参数的选择始终是一门艺术,也是一门科学。

往期内容回顾

应用数学与机器学习基础 - 学习算法篇
应用数学与机器学习基础 - 容量、过拟合和欠拟合篇
深度学习中的正则化技术 - Dropout篇

相关推荐
菜鸡中的奋斗鸡→挣扎鸡1 分钟前
滑动窗口 + 算法复习
数据结构·算法
蓝天星空8 分钟前
Python调用open ai接口
人工智能·python
睡觉狂魔er9 分钟前
自动驾驶控制与规划——Project 3: LQR车辆横向控制
人工智能·机器学习·自动驾驶
Lenyiin10 分钟前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码17 分钟前
Cmd命令大全(万字详细版)
python·算法·小程序
scan72431 分钟前
LILAC采样算法
人工智能·算法·机器学习
leaf_leaves_leaf34 分钟前
win11用一条命令给anaconda环境安装GPU版本pytorch,并检查是否为GPU版本
人工智能·pytorch·python
夜雨飘零139 分钟前
基于Pytorch实现的说话人日志(说话人分离)
人工智能·pytorch·python·声纹识别·说话人分离·说话人日志
菌菌的快乐生活1 小时前
理解支持向量机
算法·机器学习·支持向量机
爱喝热水的呀哈喽1 小时前
《机器学习》支持向量机
人工智能·决策树·机器学习