如何进行调参

参考:http://theorangeduck.com/page/neural-network-not-working

My Neural Network isn't working! What should I do?

因此,你正在开发深度学习的下一个重大突破,但你遇到了一个不幸的挫折:你的神经网络失灵了,你不知道该怎么办。你去找你的老板/主管,但他们也不知道——他们和你一样对这一切都是新手——那现在怎么办?

幸运的是,我在这里列出了你可能做错的所有事情,这些事情都是根据我自己实施神经网络和监督其他学生完成项目的经验整理而成的:

1.忘记对数据进行归一化

1)what

在使用神经网络时,准确地考虑如何将数据标准化是非常重要的。如果没有这是一个不可协商的步骤-如果没有正确并小心地做到这一点,你的网络可能几乎机会工作。由于这一步在深度学习社区中是如此重要和众所周知,所以很少在论文中提及,所以几乎总是让初学者感到困惑。

2)how

一般归一化意味着——从数据中减去均值,然后除以标准差。通常,这是针对每个输入和输出特性单独完成的,但是你可能经常希望对一组特性执行此操作,或者特别注意某些特性的标准化。

3)why

我们需要对数据进行归一化的主要原因是,神经网络管道大部分都假设输入和输出数据都分布在标准差为1左右、均值约为0的地方。这些假设在深度学习文献中随处可见,从权重初始化到激活函数,再到训练网络的优化算法。

4)and

未经训练的神经网络通常输出的值大致在-1到1之间。如果你希望它输出其他范围内的值(例如以字节形式存储的RGB图像在0到255之间),那么你将遇到一些问题。当开始训练时,网络将非常不稳定,因为当像255这样的值被期望时,它将产生-1或1的值——大多数用于训练神经网络的优化算法都认为这是一个巨大的错误。这将产生巨大的梯度,很可能你的训练错误将爆炸。如果你的训练没有爆炸,那么前几个阶段的训练仍然是浪费,因为网络首先要学习的是将输出值扩展到所需的范围。如果你将数据标准化(在本例中,你可以简单地除以128并减去1),那么这些都不是问题。

一般来说,神经网络中特征的规模也决定了它们的重要性。如果在输出中有一个大规模的特性,那么与其他特性相比,它将生成更大的错误。同样,输入中的大规模特性将主导网络,并在下游造成更大的变化。由于这个原因,仅仅使用许多神经网络库的自动归一化是不够的,这些神经网络库盲目地在每个特征偏差上减去均值并除以标准差。你可能有一个输入特征一般范围在0.0和0.001之间,这个特性的范围如此之小,因为它是一个不重要的特性(在这种情况下,也许你不想 ),或因为它相比其他特性有一些小单元?同样,要小心那些范围非常小的特性,它们的标准偏差接近于,或者确切地说,等于零——如果你对它们进行标准化,这些特性将导致NaNs的不稳定性。仔细考虑这些问题是很重要的——考虑你的每个特性真正代表什么,并将标准化视为使所有输入特性的“单元”相等的过程。我相信这是深度学习中为数不多的几个在循环中每个人都需要的进行的操作的其中之一

 

2.忘记查看结果

1)what

你已经训练了你的网络几轮了,你可以看到错误正在减少——这是否意味着你成功了?不幸的是,没有——几乎可以肯定,你的代码仍然存在一些错误。它可能是数据预处理、训练代码甚至推理中的一个bug。仅仅因为错误减少了并不意味着你的网络正在学习任何有用的东西。

2)how

在管道的每个阶段检查数据是否正确是非常重要的。通常这意味着找到某种方法来可视化结果。如果你有图像数据,那么它很容易-动画数据也可以可视化,不会有太多的麻烦。如果你有更奇特的数据,你必须找到一种方法来检查它,以确保在预处理、训练和推理的每个阶段它看起来都是正确的,并将其与真实数据进行比较。

3)why

与传统编程不同,机器学习系统几乎在所有情况下都可能会无声地失败。在传统的编程中,我们习惯了计算机在出错时抛出一个错误,并以此作为返回并检查错误的信号。不幸的是这一过程在机器学习应用程序中不工作,所以我们应该使用我们的眼睛非常小心检查每个阶段的过程,这样我们才能知道什么时候一个错误已经产生,并且什么时候我们需要返回去更彻底地检查代码。

4)and

有很多方法可以检查你的网络是否正常工作。其中一部分是找出报告的训练错误的确切含义。可视化应用于数据集中数据的网络的结果——并与真实数据进行比较,结果如何?在训练过程中,你可能会看到误差从1.0上升到0.01,但是如果0.01的误差在实践中仍然是不可接受的结果,那么结果仍然是不可用的。如果它在训练集上有效,那么在验证集上检查它——它是否仍然对以前没有见过的数据有效?我的建议是从训练一开始就进行可视化,不要只有当你的网络不工作才开始,确保在你开始尝试不同的神经网络结构前,你已经准备好了到最终用户的完整管道,并进行了完整性检查。这是你能够准确评估许多潜在的不同方法的唯一方法 

 

3.忘记对数据进行预处理

1)what

大多数数据都很棘手,而且我们所知道的相似事物的数据往往具有截然不同的数值表示。举个例子从角色动画——如果我们使用角色相对于动作捕捉工作室的关节的3d位置来表示我们的数据,然后生成在一个位置或者面对一个方向的动作,可能会有大量不同的数值表示去生成在不同的位置,或者面对一个不同的方向的相同的动作。相反,我们需要做的是能够不同地表示数据——例如在某个局部参照系中(例如相对于角色的质心),这样我们知道的两个运动是相似的,就可以得到相似的数值表示。

2)how

想想你的特性到底代表了什么——你是否可以对它们进行一些简单的变换,以确保代表我们所知道的相似事物的数据点总是得到相似的数值表示?是否有一个局部坐标系可以用来表示数据,从而使事物更自然——也许是更好的颜色空间——以不同的格式表示? 

3)why

神经网络仅对他们作为输入的数据做几个基本假设——这些基本假设之一是数据的空间是连续的——即对于大部分的空间,两个数据点之间的点至少是有点这两个数据点的“混合”,并且两个邻近的数据点在某种意义上代表“相似”的事物。因此在数据空间中如果存在较大的不连续点,或者表示相同事物的大量分离数据集群,将会使学习任务变得更加困难。

4)and

另一种考虑数据预处理的方法是尝试减少可能需要的数据变化的组合爆炸。例如,如果一个训练角色动画数据的神经网络必须在每个位置和方向上为角色学习相同的一组动作,那么网络的大量容量就会被浪费,大量的学习过程就会被重复。

 

4.忘记使用任何正则化方法

1)what

 正则化——通常以dropout、噪声或注入网络的随机过程的形式出现,是训练现代神经网络的另一个重要方面。即使你认为你有比参数多得多的数据,或者你有一些过拟合无关紧要或看起来不可能的情况,添加dropout或其他形式的噪声通常仍然是有帮助的。

2)how

正则化神经网络最基本的方法是在网络的每个线性层(卷积层或稠密层)之前添加dropout。从中等到高的保留率开始,比如0.75或0.9。根据你认为过度拟合的可能性,以及你是否发现了任何证据来进行调整。如果你认为过拟合是非常不可能的,考虑设置保留的概率非常高,如0.99。 

3)why

正则化不仅仅是控制过度拟合。通过在训练过程中引入一些随机过程,你在某种意义上“平滑”了成本前景。这可以加快训练速度,帮助处理数据中的噪音或异常值,并防止网络的极端权重配置。

4)and

数据增强或其他类型的噪声也可以像dropout一样充当正则化的角色,有时,如果有足够的数据增强,dropout就不再需要了。虽然将dropout看作是一种结合许多随机子网络预测的技术,但也有可能将dropout看作是数据增强的一种形式——在训练期间生成许多类似的输入数据变体。正如我们所知,避免过度拟合的最好方法是拥有如此多的数据,以至于神经网络永远不会看到相同的东西两次!最后,就像训练神经网络的所有方面一样,你需要小心使用正则化。记住,在预测过程中要关闭它,并且要注意,一旦关闭它,你通常可以得到稍微不同的结果。在需要非常精确的数字预测的情况下,某些形式的正则化有时会使这一点变得困难。

 

5.使用了过大的batch size

1)what

在训练过程中使用过大的批处理大小会对网络的准确性产生负面影响,因为它会降低梯度下降的随机性。 

2)how

找出你能够容忍训练时间的最小批处理大小。当涉及到精度时,最优利用GPU并行性的批处理大小可能不是最好的,因为在某些情况下,更大的批处理大小将需要对网络进行更多的训练,以达到相同的精度水平。不要害怕从非常小的批处理大小开始,比如16、8甚至1。

3)why

使用更小的批处理大小会产生更不稳定、更随机的权重更新。这有两个积极的影响。首先,它可以帮助训练“跳出”以前可能陷入的局部极小值;其次,它可以使训练稳定在“平坦”的极小值中,这通常意味着更好的泛化性能。

4)and

数据中的一些其他元素有时可以有效地发挥批处理大小的作用。例如,以两倍于以前的分辨率处理图像可以产生与使用四倍于以前批处理大小的效果类似的效果。为了直观地理解这一点,考虑一下在CNN中,每个过滤器的权值更新将在输入图像中应用它的所有像素以及批处理中的每个图像上取平均值。将图像分辨率增加两倍将产生超过四倍的像素的平均效果,这与将批处理大小增加四倍非常相似。总的来说,重要的是要考虑最终的梯度更新在每次迭代中平均会有多少,并确保在其的有害影响和使用尽可能多的GPU潜在并行性的需求之间取得平衡。

 

6.使用不正确的学习率

1)what

学习速度会对训练网络的难易程度产生巨大影响,如果你是新手,几乎可以肯定你的设置是错误的,这要感谢常用深度学习框架中使用的各种默认选项。

2)how

关闭梯度裁剪。找到学习率的最大值,这样在训练过程中不会出现错误爆炸。将学习率设置为比这个低一个数量级——这可能非常接近最优学习率。

3)why

许多深度学习框架在默认情况下都启用了梯度裁剪。这个选项通过强制在每个步骤中改变最大权重来防止在训练中使用的优化发生爆炸。这可能很有用——特别是如果你的数据包含许多异常值,这些异常值会产生较大的错误,因此会产生较大的梯度和权重更新——但是默认启用它也会使手工查找最佳学习率变得非常困难。我发现大多数初学深度学习的人都把学习率设置得太高,并且用梯度剪裁来解释这一点,使得整体训练行为变慢,改变学习率的效果无法预测。

4)and

如果你正确地清理了数据,删除了大部分异常值,并正确地设置了学习率,那么你真的不应该需要梯度裁剪。如果没有它,你发现你的训练错误偶尔会爆发,那么无论如何,打开梯度裁剪,但要记住,看到你的训练错误爆发几乎总是一个迹象,表明你的一些数据有其他问题——裁剪是一个临时的修复。

 

7.在最后一层使用了错误的激活函数

1)what

在最后一层使用激活函数有时可能意味着你的网络无法生成所需的全部值。最常见的错误是在最后一层使用ReLU——导致网络只能产生正值作为输出。

2)how

如果要进行回归,那么通常不希望在最后一层使用任何类型的激活函数,除非你对希望生成的输出值有特定的了解。 

3)why

再想想你的数据值实际表示的是什么,以及规范化之后它们的范围是什么。输出值很可能是无界的正数或负数——在这种情况下,不应该在最后一层使用激活函数。如果你的输出值只在某个范围内有意义,例如,它由0-1范围内的概率组成,那么很有可能在最后一层使用一个特定的激活函数,比如sigmoid激活函数。 

4)and

在最后一层使用激活函数有许多微妙之处。也许你知道你神经网络生成的系统最终将剪辑输出到范围- 1,1后。这样,添加这个剪切过程作为最后一层激活似乎是有意义的,因为这将确保网络错误函数不会惩罚大于1或小于-1的值。但是没有错误意味着这些值大于或小于1没有梯度——在某些情况下,这将使你的网络无法训练。或者你可能想在最后一层使用tanh激活函数,因为这个激活函数输出值范围在1到1 ——但是这也可能会导致问题,因为这个函数的梯度接近1或-1时增长很小,从而导致你的权重增长巨大,以生成-1或1。一般来说,你最好的选择是在最后一层完全不使用激活函数,而不是尝试做一些可能适得其反的事情。

 

8.网络包含糟糕的梯度

1)what

使用ReLU激活函数的深层网络常常会受到所谓的“死神经元”的影响,这是由糟糕的梯度造成的。这可能会对网络的性能产生负面影响,或者在某些情况下完全不可能进行训练。

2)how

如果你发现你的训练错误没有随着时间的推移而改变,那可能是因为你所有的神经元都因使用ReLU激活函数而死亡。尝试切换到另一个激活函数,如leaky ReLUs或ELUs,看看是否会发生相同的事情。

3)why

 ReLU激活函数的梯度为正1,负0。这是因为在输入小于零的情况下,输入中很小的变化不会影响输出。因为正值的大梯度,这可能不会立即正为一个问题;但与许多层堆叠在彼此之上,和负权值能够将带有强梯度的大正值变为零梯度的负值的作用下,它可能经常会导致一些甚至是所有的网络权值在成本函数中的梯度为零,不管输入是什么。在这种情况下,我们说网络是“死的”,因为权重完全无法更新。

4)and

任何梯度为零的操作,如裁剪、舍入或取最大值/最小值,如果用于计算成本函数对权重的导数,也会产生不好的梯度。如果它们出现在符号图中的任何地方,请非常小心,因为它们常常会导致无法预见的困难,例如,如果它们用于作为成本函数的一部分提供的自定义错误度量中。 

 

9.错误地初始化网络权重

1)what

如果你没有正确初始化你的神经网络的权重,那么你的神经网络就不太可能进行训练。神经网络中的许多其他组件都假定某种形式的正确或标准化的权重初始化,并将权重设置为零,或者使用你自己的自定义随机初始化将不起作用。

2)how

“he”、“lecun”或“xavier”权重初始化都是流行的选择,在实际的任何情况下都可以很好地工作。只要选择一个(我最喜欢的是“lecun”),但是一旦你的神经网络开始工作,你就可以自由地进行实验,直到你找到最适合你任务的初始化方法。

3)why

你可能听说过可以使用“小随机数”初始化神经网络权值,但事情并没有那么简单。上述所有初始化都是使用复杂而详细的数学发现的,这些数学解释了为什么它们是最优的。更重要的是,其他神经网络组件是围绕这些初始化构建的,并使用它们进行了经验测试——使用你自己的初始化可能会使复制其他研究人员的结果变得更加困难。

4)and

其他层可能也需要小心初始化。网络偏差被初始化为零,而其他更复杂的层,如参数化激活函数可能带有它们自己的初始化,这些初始化的正确也同样很重要。

 

10.使用的网络太深

1)what

网络越深越好吗?嗯,不总是……当我们玩基准游戏并试图挤出比其他任务多1%的准确性时更深的通常是更好,但是如果你的小3,4,5层网络没有学到任何东西,那么我可以向你保证,一个100层的庞然大物的效果即使不是更糟,也会是一样糟糕。

2)how

从一个浅层的3到8层的神经网络开始。只有当你已经把事情做得很好并开始研究如何提高准确度时,才可以开始尝试更深层次的网络。

3)why

虽然看起来像这样,但是当某人决定将数百层叠加起来时,神经网络并不会突然开始获得突破性的结果。在过去的十年里,所有对神经网络的改进研究都是一些小的、根本性的变化,这些变化同样适用于小型网络和深度网络的性能。如果你的网络不工作,除了深度之外,更有可能是其他问题。

4)and

从小处着手也意味着训练你的网络会更快,推理会更快,迭代不同的设计和设置也会更快。最初,所有这些东西对你的网络的准确性的影响都比简单地叠加几层要大得多。

 

11.使用错误的隐藏单元的数目

1)what

在某些情况下,使用过多或过少的隐藏单元会使你的网络难以训练。太少的单元可能没有能力表达所需要的任务,而太多的单元可能会变得缓慢和笨拙,难以消除残留的噪声。 

2)how

从256到1024个隐藏单元开始。然后,看看其他从事类似应用的研究人员所使用的数字,并以此作为灵感。如果其他研究人员使用的数字与上面给出的数字有很大的不同,那么其中可能有一些特定的原因,这对你理解可能很重要。

3)why

在决定使用多少隐藏单元时,关键是粗略地考虑你认为表达你希望通过网络传递的信息所需的实际值最少是多少。你应该把这个数字放大一点。这将允许dropout,为网络使用一个更冗余的表示,并为你的估计留有一些余地。如果你在做分类,你可以使用5到10倍的类数作为一个好的初始猜测;而如果你在做回归,你可以使用2到3倍的输入或输出变量的数量。当然——所有这些都高度依赖于上下文,并且没有简单的自动解决方案——一个好的直觉仍然是决定隐藏单元数量的最重要因素。

4)and

在现实中,与其他因素相比,隐藏单元的数量对神经网络性能的影响往往相当小,而且在许多情况下,高估所需隐藏单元的数量除了会使训练变慢外,几乎不会产生负面影响。一旦你的网络开始工作,如果你还在担心,就试着用一大堆不同的数字来测量准确度,直到你找到最合适的。

posted @ 2019-05-20 15:14  慢行厚积  阅读(1477)  评论(0编辑  收藏  举报