108 lines
8.3 KiB
Markdown
108 lines
8.3 KiB
Markdown
# 深度学习训练技巧
|
||
|
||
随着神经网络变得越来越深,训练它们的过程变得越来越具有挑战性。一个主要的问题是所谓的[消失梯度](https://en.wikipedia.org/wiki/Vanishing_gradient_problem)或[爆炸梯度](https://deepai.org/machine-learning-glossary-and-terms/exploding-gradient-problem#:~:text=Exploding%20gradients%20are%20a%20problem,updates%20are%20small%20and%20controlled.)。[这篇文章](https://towardsdatascience.com/the-vanishing-exploding-gradient-problem-in-deep-neural-networks-191358470c11)对这些问题进行了很好的介绍。
|
||
|
||
为了使深度网络的训练更加高效,可以使用一些技术。
|
||
|
||
## 保持值在合理范围内
|
||
|
||
为了使数值计算更加稳定,我们希望确保神经网络中的所有值都在合理的范围内,通常为[-1..1]或[0..1]。这并不是一个非常严格的要求,但浮点计算的性质使得不同数量级的值无法准确地一起操作。例如,如果我们将10<sup>-10</sup>和10<sup>10</sup>相加,我们可能会得到10<sup>10</sup>,因为较小的值会被“转换”为与较大的值相同的数量级,从而导致尾数丢失。
|
||
|
||
大多数激活函数在[-1..1]附近具有非线性,因此将所有输入数据缩放到[-1..1]或[0..1]范围是有意义的。
|
||
|
||
## 初始权重初始化
|
||
|
||
理想情况下,我们希望在经过网络层后,值保持在相同的范围内。因此,以保持值的分布为目的初始化权重是很重要的。
|
||
|
||
正态分布 **N(0,1)** 并不是一个好主意,因为如果我们有 *n* 个输入,输出的标准差将是 *n*,并且值很可能会超出[0..1]的范围。
|
||
|
||
以下初始化方法经常被使用:
|
||
|
||
* 均匀分布 -- `uniform`
|
||
* **N(0,1/n)** -- `gaussian`
|
||
* **N(0,1/√n_in)** 确保对于均值为零且标准差为1的输入,均值/标准差保持不变
|
||
* **N(0,√2/(n_in+n_out))** -- 所谓的 **Xavier 初始化** (`glorot`),它有助于在前向和反向传播过程中保持信号在范围内
|
||
|
||
## 批归一化
|
||
|
||
即使在适当的权重初始化下,权重在训练过程中也可能变得任意大或小,这会将信号带出适当的范围。我们可以通过使用一种**归一化**技术来将信号恢复到适当范围。虽然有几种归一化方法(权重归一化、层归一化),但最常用的是批归一化。
|
||
|
||
**批归一化**的思想是考虑小批量中的所有值,并基于这些值执行归一化(即减去均值并除以标准差)。它被实现为一个网络层,在应用权重之后但在激活函数之前执行这种归一化。结果,我们可能会看到更高的最终准确性和更快的训练速度。
|
||
|
||
这里是关于批归一化的[原始论文](https://arxiv.org/pdf/1502.03167.pdf)、[维基百科上的解释](https://en.wikipedia.org/wiki/Batch_normalization)以及[一篇很好的入门博客文章](https://towardsdatascience.com/batch-normalization-in-3-levels-of-understanding-14c2da90a338)(还有一篇[俄文](https://habrahabr.ru/post/309302/))。
|
||
|
||
## 随机失活
|
||
|
||
**随机失活**是一种有趣的技术,在训练过程中随机去除一定比例的神经元。它也被实现为一个层,具有一个参数(要去除的神经元百分比,通常为10%-50%),在训练过程中,它会将输入向量的随机元素置为零,然后传递到下一层。
|
||
|
||
虽然这听起来像是一个奇怪的想法,但您可以在 [`Dropout.ipynb`](../../../../../lessons/4-ComputerVision/08-TransferLearning/Dropout.ipynb) 笔记本中看到随机失活对训练 MNIST 数字分类器的影响。它加速了训练,并使我们在更少的训练轮次中实现更高的准确性。
|
||
|
||
这个效果可以通过几种方式解释:
|
||
|
||
* 它可以被视为对模型的随机冲击因素,帮助优化脱离局部最小值
|
||
* 它可以被视为*隐式模型平均*,因为我们可以说在随机失活期间,我们正在训练稍微不同的模型
|
||
|
||
> *有人说,当一个醉酒的人试图学习某些东西时,他会在第二天早上记住得更好,与一个清醒的人相比,因为一个有些神经元失常的大脑会更好地适应以抓住意义。我们从未测试过这是否属实*
|
||
|
||
## 防止过拟合
|
||
|
||
深度学习中一个非常重要的方面是能够防止[过拟合](../../3-NeuralNetworks/05-Frameworks/Overfitting.md)。虽然使用非常强大的神经网络模型可能很诱人,但我们应该始终平衡模型参数的数量与训练样本的数量。
|
||
|
||
> 确保您理解我们之前介绍的[过拟合](../../3-NeuralNetworks/05-Frameworks/Overfitting.md)的概念!
|
||
|
||
防止过拟合的方法有几种:
|
||
|
||
* 提前停止 -- 持续监控验证集上的误差,并在验证误差开始增加时停止训练。
|
||
* 显式权重衰减/正则化 -- 为损失函数中高绝对值的权重添加额外惩罚,以防止模型获得非常不稳定的结果
|
||
* 模型平均 -- 训练多个模型,然后对结果进行平均。这有助于最小化方差。
|
||
* 随机失活(隐式模型平均)
|
||
|
||
## 优化器/训练算法
|
||
|
||
训练的另一个重要方面是选择合适的训练算法。虽然经典的**梯度下降**是一个合理的选择,但有时它可能太慢,或者导致其他问题。
|
||
|
||
在深度学习中,我们使用**随机梯度下降**(SGD),它是应用于从训练集中随机选择的小批量的梯度下降。权重使用以下公式进行调整:
|
||
|
||
w<sup>t+1</sup> = w<sup>t</sup> - η∇ℒ
|
||
|
||
### 动量
|
||
|
||
在**动量 SGD**中,我们保留来自前一步的梯度的一部分。这类似于当我们以惯性移动时,如果受到另一个方向的冲击,我们的轨迹不会立即改变,而是保持一部分原始运动。在这里,我们引入另一个向量v来表示*速度*:
|
||
|
||
* v<sup>t+1</sup> = γ v<sup>t</sup> - η∇ℒ
|
||
* w<sup>t+1</sup> = w<sup>t</sup> + v<sup>t+1</sup>
|
||
|
||
这里参数γ表示我们考虑惯性的程度:γ=0对应于经典的SGD;γ=1是纯粹的运动方程。
|
||
|
||
### Adam, Adagrad等
|
||
|
||
由于在每一层中我们将信号乘以某个矩阵W<sub>i</sub>,根据||W<sub>i</sub>||,梯度可能会减小并接近0,或者无限增加。这就是爆炸/消失梯度问题的本质。
|
||
|
||
解决这个问题的一种方法是仅在方程中使用梯度的方向,而忽略绝对值,即:
|
||
|
||
w<sup>t+1</sup> = w<sup>t</sup> - η(∇ℒ/||∇ℒ||),其中 ||∇ℒ|| = √∑(∇ℒ)<sup>2</sup>
|
||
|
||
这个算法称为**Adagrad**。其他使用相同思想的算法有:**RMSProp**、**Adam**
|
||
|
||
> **Adam** 被认为是许多应用中非常高效的算法,因此如果您不确定使用哪个 - 请使用Adam。
|
||
|
||
### 梯度裁剪
|
||
|
||
梯度裁剪是上述思想的扩展。当 ||∇ℒ|| ≤ θ 时,我们在权重优化中考虑原始梯度,而当 ||∇ℒ|| > θ 时 - 我们将梯度除以其范数。这里θ是一个参数,在大多数情况下我们可以取θ=1或θ=10。
|
||
|
||
### 学习率衰减
|
||
|
||
训练的成功往往取决于学习率参数η。合理的推测是,较大的η值会导致更快的训练,这通常是我们在训练开始时想要的,然后较小的η值使我们能够微调网络。因此,在大多数情况下,我们希望在训练过程中降低η。
|
||
|
||
这可以通过在每个训练轮次后将η乘以某个数字(例如0.98)来完成,或者使用更复杂的**学习率调度**。
|
||
|
||
## 不同的网络架构
|
||
|
||
为您的问题选择正确的网络架构可能很棘手。通常,我们会选择一种已经证明适用于我们特定任务(或类似任务)的架构。这里是关于计算机视觉的神经网络架构的[良好概述](https://www.topbots.com/a-brief-history-of-neural-network-architectures/)。
|
||
|
||
> 选择一个足够强大的架构以适应我们拥有的训练样本数量是很重要的。选择过于强大的模型可能会导致[过拟合](../../3-NeuralNetworks/05-Frameworks/Overfitting.md)。
|
||
|
||
另一种好的方法是使用一种可以自动调整到所需复杂度的架构。在某种程度上,**ResNet**架构和**Inception**是自我调整的。[有关计算机视觉架构的更多信息](../07-ConvNets/CNN_Architectures.md)
|
||
|
||
**免责声明**:
|
||
本文件使用基于机器的人工智能翻译服务进行翻译。尽管我们努力追求准确性,但请注意,自动翻译可能包含错误或不准确之处。原始文件的母语版本应被视为权威来源。对于关键信息,建议进行专业人工翻译。我们对因使用本翻译而导致的任何误解或错误解释不承担责任。 |