My Neural Network isn't working! What should I do?
参考文献:http://theorangeduck.com/page/neural-network-not-working
我的网络不起作用!该怎么办?
因此,你在深度学习方面正在开发下一个重大突破,但你遇到了一个不幸的挫折:你的神经网络不起作用,你不知道该怎么做。你去找你的老板/上司,但他们也不知道-他们和你一样对这一切都很陌生-那现在怎么办?
对你来说,幸运的是,我在这里列出了你可能做错了的所有事情,并根据我自己的经验编写了一份清单,用他们的项目来执行神经网络和监督其他学生:
You Forgot to Normalize Your Data
一、
我的神经网络坏了!我该怎么办?
My Neural Network isn't working! What should I do?
Created on Aug. 19, 2017, 5:56 p.m.
So you're developing the next great breakthrough in deep learning but you've hit an unfortunate setback: your neural network isn't working and you have no idea what to do. You go to your boss/supervisor but they don't know either - they are just as new to all of this as you - so what now?
Well luckily for you I'm here with a list of all the things you've probably done wrong and compiled from my own experiences implementing neural networks and supervising other students with their projects:
- You Forgot to Normalize Your Data
- You Forgot to Check your Results
- You Forgot to Preprocess Your Data
- You Forgot to use any Regularization
- You Used a too Large Batch Size
- You Used an Incorrect Learning Rate
- You Used the Wrong Activation Function on the Final Layer
- Your Network contains Bad Gradients
- You Initialized your Network Weights Incorrectly
- You Used a Network that was too Deep
- You Used the Wrong Number of Hidden Units
一、You Forgot to Normalize Your Data
What?
当使用神经网络时,必须准确地考虑如何将数据规范化。这是一个不容商量的步骤,你的网络在没有正确和谨慎的情况下工作的可能性很小。由于这一步骤是如此重要,在深度学习社区中是众所周知的,所以很少在论文中提到,因此几乎总是会让初学者摔跤
How?
一般来说,规范化是指从数据中减去平均值,然后将数据除以其标准差。通常,这是针对每个输入和输出特性单独完成的,但是您可能经常希望对特征组这样做,或者特别小心地处理某些特征的规范化。
Why?
我们需要规范化数据的主要原因是,神经网络管道的大部分假定输入和输出数据都是分布为标准差约为1,平均值约为0。这些假设在深度学习文献中随处可见,从权值初始化到激活函数,再到训练网络的优化算法。
And?
未经训练的神经网络通常会输出大约在-1到1的范围内的值。如果您期望它在其他范围内输出值(例如,存储为字节的RGB图像在0到255之间),那么您将遇到一些问题。当开始训练时,网络将非常不稳定,因为它将产生值为-1或1,当预期值为255时,这个错误被大多数用于训练神经网络的优化算法认为是巨大的。这将产生巨大的梯度,很可能你的训练错误会爆炸。如果您的训练没有爆炸,那么培训的最初几个阶段仍然是一种浪费,因为网络将学到的第一件事是缩放输出值并将其转换到所需的范围。如果您将数据规范化(在本例中,您只需除以128并减去1),那么所有这些都不会成为问题。
一般来说,神经网络中的特征的规模也将支配它们的重要性。如果输出中有一个具有较大规模的特性,那么与其他特性相比,它将产生更大的错误。类似地,输入中的大规模特性将主导网络并导致下游更大的变化。因此,利用多个神经网络库的自动归一化并不总是足够的,这些神经网络库在每个特征的基础上,盲目地减去均值,除以标准差。您可能有一个输入特性,其范围通常在0.001到0.001之间-该功能的范围是否太小是因为它是一个不重要的特性(在这种情况下,您可能不想对其进行调整),或者因为它与其他功能相比有一些小单位(在这种情况下,您这样做)?类似地,要小心那些特性,这些特性的范围很小,以至于它们的标准差接近,或者精确地接近于零-如果你将它们规范化,这些特性会产生NAN的不稳定性。仔细考虑这些问题是很重要的-考虑一下您的每个特性真正代表了什么,并将规范化视为使所有输入功能的“单元”相等的过程。这是深度学习的少数几个方面之一,我相信在这个循环中,人是真正需要的。
二、你忘了检查结果
What?
你已经训练了你的网络几个epoch,你可以看到错误下降-成功!这是否意味着你已经做到了?不幸的是并没有,几乎可以肯定,您的代码仍然有问题。它可能是数据预处理,训练代码,甚至推断中的一个错误。仅仅因为错误减少并不意味着你的网络正在学习任何有用的东西。
How?
在pipeline的每个阶段检查数据看起来都是正确的,这是非常重要的。通常,这意味着找到某种方法来可视化结果。如果你有图像数据,那么它是容易的-动画数据也可以可视化,没有太多的麻烦。如果你有更不同的东西,你必须找到一种方法来检查它,以确保它在你的预处理、训练和推理pipeline的每个阶段看起来都是正确的,并将它与ground truth进行比较。
Why?
与传统编程不同,机器学习系统几乎在所有情况下都会默默地失败。在传统的编程中,我们习惯于当事情出错时,计算机会抛出错误,并使用它作为返回和检查错误的信号。不幸的是,这个过程并不适用于机器学习应用程序,因此我们应该非常小心地用肉眼检查每个阶段的进程,以便我们知道什么时候出现了bug,什么时候我们可能需要更彻底地回过头来检查代码。
And?
有许多方法可以检查您的网络是否正常工作。部分原因是找出报告的训练错误的真正含义。可视化您的网络应用于训练集中的数据的结果-在实践中您的网络的结果如何与实际真相比较?在训练期间,您可能会看到错误从1.0到0.01,但是如果仍然存在0.01的错误,则结果仍然无法使用。在实践中一个不可接受的结果。如果它在训练集上有效,那么在验证集上检查它-它是否对以前从未见过的数据仍然有效?我的建议是,从一开始就习惯于想象一切-不要只在你的网络不起作用的时候才开始-确保在你开始尝试不同的神经网络结构之前,你已经准备好了完整的pipeline,一路走到终端用户,并进行了健康检查。这是您能够准确评估许多潜在的不同方法的唯一方法。
三、You Forgot to Preprocess Your Data
What?
大多数数据都是很棘手的-而且通常是用于某些事情的数据。我们知道是相似的,可以有很大的不同的数字表示。以角色动画为例-如果我们用角色关节相对于运动捕捉演播室中心的3D位置来表示数据,那么在一个位置或面向一个方向执行一个动作,可能有一个非常不同的数字表示,在一个不同的位置执行相同的动作,或者面对一个不同的方向。相反,我们需要做的是用不同的方式表示数据-例如,在一些局部参考框架中(例如相对于字符的质量中心),这样我们知道的两种运动都是相似的,得到了相似的数值表示。
How?
仔细想想您的特性所代表的是什么-您是否可以对它们进行一些简单的转换,以确保表示事物的数据点我们知道相似总是得到相似的数值表示吗?是否有一个本地坐标系统,您可以表示您的数据,使事物更自然-也许更好的颜色空间-一种不同的格式?
Why?
神经网络对它们接受的数据只作了几个基本假设-但其中一个基本假设是,数据所在的空间在某种程度上是连续的-对于大部分空间来说,两个数据点之间的一个点至少在某种程度上是这两个数据点的“混合体”,而附近的两个数据点在某种意义上代表着“相似”的东西。在数据空间中有很大的不连续性,或者表示相同事物的大簇分离数据,将使学习任务变得更加困难。
And?
另一种考虑数据预处理的方法是试图减少可能需要的数据变化的组合爆炸。例如,如果对字符动画数据进行训练的神经网络必须在每个位置和方向上对字符学习相同的运动集,那么网络的大量容量就会被浪费,学习过程也会重复很多。
四、You Forgot to use any Regularization
What?
正则化-通常以dropout、noise或一些注入网络的随机过程形式是现代神经网络训练的另一个不可商量的方面。即使你认为你有比参数多得多的数据,或者你有一些情况下过拟合并不重要或看起来不可能,你仍然应该经常增加dropout或其他形式的noise。
How?
使神经网络规格化的最基本的方法是在网络中的每一个线性层(卷积层或密集层)之前添加dropout。从中等到高的保留概率开始,比如0.75或0.9。根据你认为过拟合的可能性以及找到任何证据进行调整。如果你仍然认为过度拟合是不可能的,可以考虑将保留概率设置为非常高的值,比如0.99。
Why?
正则化不仅仅是控制过拟合。通过在训练过程中引入一些随机过程,你在某种意义上是在“平滑”成本景观。这可以加快训练速度,帮助处理数据中的噪声或异常值,并防止网络的极端权重配置。
And?
数据增强或其他类型的噪声也可以起到正则化的作用,就像dropout一样。虽然考虑dropout的常见方法是将许多随机子网络的预测结合起来的技术,但也有可能通过在训练期间产生许多类似的输入数据来动态地扩展训练集的大小。正如我们所知道的,避免过拟合和提高网络准确性的最好方法是拥有如此多的数据,以至于神经网络从来不会看到相同的东西两次!
三、You Used a too Large Batch Size
What?
在训练过程中,使用太大的批次大小会对网络的准确性产生负面影响,因为它降低了梯度下降的随机性。
How?
找到可以容忍训练时间的最小批次大小。对GPU并行性进行最佳使用的批处理大小在精度方面可能不是最好的,因为在某个点上,较大的批处理大小将需要对网络进行更多的时间训练,以达到相同的精度水平。不要害怕从一个很小的批次开始,比如16,8,甚至1。
Why?
使用较小的批次大小会产生更多的随机重量更新。这可以产生两个积极的影响。第一,它可以帮助训练“跳出”它以前可能陷入的局部极小值,第二,它可以使训练在“更平坦”的极小值中稳定下来,这通常表明它具有较好的泛化性能。
And?
数据中的其他一些元素有时可以有效地充当批处理大小的角色。例如,以比以前分辨率两倍的速度处理图像,其效果类似于使用批处理大小的四倍。为了获得这方面的直觉,考虑到在CNN中,每个过滤器的权重更新将平均在输入图像中的所有像素上,以及对于批处理中的每个图像。提高图像分辨率2将产生平均效果超过4倍以上的像素,以非常类似的方式,如果您增加批大小4。总的来说,重要的是要考虑最终的梯度更新将是多少。平均在每一次迭代中,确保平衡这与尽可能多地使用GPU的潜在并行性所带来的有害影响。
五、You Used an Incorrect Learning Rate
What?
学习速度可能会对训练网络的容易程度产生巨大影响,如果您是新手,那么几乎可以肯定,由于常见的深度学习框架中使用的各种默认选项,您设置得不正确。
How?
旋转渐变剪裁。找出学习率的最高值,这不会使错误在训练中爆炸。把学习速度设定得比这个低一点-这可能非常接近最优的学习率。
Why?
许多深度学习框架默认启用梯度裁剪。这个选项防止了在训练中使用的优化,通过强制每个步骤的重量可以改变的最大数量来爆炸。这是有用的-尤其是如果数据包含许多异常值,这些异常值会产生很大的错误,从而产生很大的梯度和权重更新-但是默认情况下,使用它也会使手工寻找最佳学习速度变得非常困难。我发现,大多数刚进入深度学习的人的学习速度设定得太高,因此采用梯度剪裁来解释这一点,使得整体的训练行为变慢,以及改变学习速度的效果难以预测。
And?
如果您已经正确地清理了数据,删除了大部分的异常值,并且正确地设置了学习速率,那么您就不应该需要梯度裁剪。如果没有它,你会发现你的训练错误偶尔会爆发,那就一定要打开渐变剪裁,但是请记住,看到你的训练错误爆发几乎总是表明你的一些数据有问题-裁剪只是暂时的修复。
六、You Used the Wrong Activation Function on the Final Layer
What?
在最后一层使用激活函数有时可能意味着您的网络无法生成全部所需的值。最常见的错误是在最后一层使用relu-导致网络只能产生正值作为输出。
How?
如果您正在进行回归,那么通常您不希望在最后一层使用任何类型的激活函数,除非您知道希望作为输出生成的值的具体类型。
Why?
再考虑一下数据值实际代表的是什么,以及规范化后数据值的范围是什么。最有可能的情况是,输出值是无界正数或负数-在这种情况下,不应该在最后一层使用激活函数。如果您的输出值可能仅在某个范围内有意义,例如,它包含在0-1范围内的概率,则最有可能的情况是,应该在最后一层上使用特定的激活函数,例如乙状结肠激活函数。
And?
在最后一层使用激活函数有许多微妙之处。也许你知道你的系统最终会将输出剪辑到-1,1的范围,在它们被神经网络产生之后。然后,添加这个裁剪过程作为最后一层激活似乎是有意义的,因为这将确保您的网络错误函数不会惩罚大于1或小于-1的值。但是没有错误意味着这些值也没有梯度,这些值大于或小于一个-在某些情况下,这将使您的网络无法进行训练。或者,您可能会想在最后一层使用tanh,因为知道这个激活函数在1到1的范围内输出值,但这也会引起问题,因为这个函数在1或-1附近的梯度变得非常小,这可能会导致您的体重增长巨大,从而试图产生-1或1。一般来说,你最好的选择是在最后一层不使用任何激活功能,而不是试图做一些可能适得其反的聪明的事情。
七、Your Network contains Bad Gradients
What?
使用relu激活函数的深层网络经常会受到所谓的“死神经元”的影响,这种“死神经元”是由坏的梯度引起的。这可能会对网络的性能产生负面影响,或者在某些情况下完全不可能进行培训。
How?
如果你发现你的训练错误并没有从一个epoch变化到另一个epoch,那可能是因为你所有的神经元都因为使用relu激活函数而死亡。尝试切换到另一个激活函数,比如LeakyReLU或Elus,看看是否会发生同样的事情。
Why?
对于正值和负值,relu激活函数的梯度分别为1和0。这是因为输入中非常小的变化不会影响输入小于零的输出。这似乎不是一个问题,因为正值的梯度很大,但是由于许多层相互叠在一起,负权重可以将具有强梯度的大正值转换为具有零梯度的负值,通常情况下,您的网络权重中的一些甚至所有的梯度对于成本函数都有一个梯度为零,无论输入是什么。在这种情况下,我们说网络是“死的”,因为权重是完全无法更新的。
And?
任何具有零梯度的运算,如裁剪、舍入或取最大值/最小值,如果用于计算成本函数相对于权重的导数,也会产生糟糕的梯度。如果它们出现在您的符号图中的任何地方,请非常小心,因为它们经常会造成不可预见的困难,例如,如果它们是作为成本函数的一部分提供的自定义错误度量中使用的。
八、You Initialized your Network Weights Incorrectly
What?
如果你没有正确地初始化你的神经网络权重,那么你的神经网络根本不可能训练。神经网络中的许多其他组件假设某种形式的正确或标准化的权值初始化并将权重设置为零,或者使用您自己的自定义随机初始化将无法工作。
How?
“He”、“Lecun”或“xavier”的体重缩写都是流行的选择,在任何情况下都应该能很好地发挥作用。选一个就行了(我最喜欢的是“Lecun”),但一旦你的神经网络发挥作用,你就可以自由地进行实验,直到你找到最适合你的任务为止。
Why?
你可能听说过,你可以用“小随机数”来初始化神经网络的权重,但这并不是那么简单。所有上述初始化都是用复杂而详细的数学方法发现的,这就准确地解释了它们为什么是最优的。更重要的是,其他神经网络组件已经围绕着这些初始化进行了构建,并使用它们进行了经验性测试-使用您自己的初始化可能会使复制其他研究人员的结果变得更加困难。
And?
其他层可能也需要小心初始化。网络偏差被初始化为零,而其他更复杂的层,如参数激活函数,可能伴随着它们自己的初始化,这些初始化对于得到正确的结果同样重要。
九、You Used a Network that was too Deep
What?
越深越好,对吗?嗯,并不总是…当我们玩benchmark游戏,试图从某些任务中挤出1%的精确度时,深度通常更好,但是如果你的小3,4,5层网络没有学到任何东西,那么我可以向你保证,一个100层的庞然大物如果不是更糟的话,也会失败的。
How?
从浅层开始,一个3到8层的神经网络。只有当你已经有了更好的工作,并开始研究如何提高准确性时,才开始尝试更深层次的网络。
Why?
虽然看起来可能是这样,但神经网络并没有突然开始取得突破性的结果时,有人决定堆叠数百层。在过去十年中,对神经网络的所有改进都是小的、根本性的变化,它们和深度网络一样适用于较小的网络的性能。如果您的网络不工作,它更有可能是其他的错误,而不是深度。
And?
从小的地方开始也意味着训练你的网络会更快,推理也会更快,在不同的设计和设置上迭代也会更快。最初,所有这些事情都会对你的准确性产生更大的影响,而不是简单地堆叠更多的层。
十、You Used the Wrong Number of Hidden Units
What?
在某些情况下,使用太多或太少的隐藏单位会使您的网络难以训练。单位太少,它可能没有能力表达所需的任务,而太多的和它可能会变得缓慢和笨重的训练与残差的噪音是很难消除。
How?
从256个到1024个隐藏单位开始。然后,看看从事类似应用的其他研究人员正在使用的数字,并以此作为灵感。如果其他研究人员使用的数字与上面给出的数字有很大的不同,那么可能有一些特定的原因,这对你来说可能很重要。
Why?
在决定要使用的隐藏单位的数量时,关键是大致考虑一下您认为可能是什么。所需的实际值最少若要表示希望通过网络传递的信息,请执行以下操作。然后你应该把这个数字放大一点。这将允许dropout,网络使用更多的冗余表示,并在您的估计中有一些余地。如果要进行分类,可以使用类数的五到十倍作为初始猜测,而如果要进行回归,则可能使用输入或输出变量数的两到三倍。当然-所有这些都是高度依赖于上下文的,并且没有简单的自动解决方案-良好的直觉仍然是决定隐藏单元数量的最重要的东西。
And?
实际上,与其他因素相比,隐藏单元的数量对神经网络性能的影响很小,而且在许多情况下,过高估计所需隐藏单元的数量除了使训练速度变慢外,几乎没有什么负面影响。一旦你的网络正常工作,如果你还在担心,就试着用一堆不同的数字来测量它的准确性,直到你找到最有效的一个。