转自:https://www.cnblogs.com/lifan3a/articles/4611047.html
本文由Ilya Sutskever(Google研究员、深度学习泰斗Geoffrey Hinton的学生、DNNresearch的联合创始人)受Yisong Yue之邀所写,综合讲述了有关深度学习的见解及实用建议。文章由Yisong Yue授权《程序员》电子刊翻译,并刊载于《程序员》15·2B期。
近年来IT界里掀起了一股深度学习热,有望成为下一个技术创新风口。在诸如语音识别、影像识别及其他语言相关的如机器翻译等领域里,深度学习业已取得了相当不错的成绩。
为什么呢?深度学习究竟有何神通?(接下来在论述深度神经网络时,会简写为LDNN,Large Deep Neural Networks)现在的LDNN与过去又有何异同?最后,或许你会问及如何训练一个LDNN。坊间流行的说法是“难,难,难”,同时给LDNN训练披上了一件有着“黑色魔法”的外衣——经验,经验!诚然经验不可或缺,但不应过分夸大。此外,很多开源神经网络方案已帮助不少初学者找到了入门捷径(如Caffe、cuda-convnet、Torch、Theano等)。
为什么深度学习是可行的
首先,工欲善其事,必先利其器。如果缺乏一个足够强大的模型,再好的学习算法也只能隔靴搔痒。
其次,该模型必须是可训练的。否则在瞬息万变的时代,不可训练的模型无疑是阿喀琉斯之踵。
庆幸的是,LDNN既强大又可训练。
LDNN究竟强在哪里
谈及LDNN时,我通常指的是10-20层的神经网络(这是现有算法所能驾驭的)。以下列举了几点有关LDNN的强大之处。
传统统计学模型学习的是简单的模式或群集。相反,LDNN学习的是计算,尽管进行大规模并行运算时需要适量的计算步骤。这就是LDNN与其他统计模型的重要分水岭。
更具体地说:众所周知,任何算法都可由合适的深层电路图来实现(如把算法实现中的每一时步作为一层)。而且,电路图层次越深,电路算法实现的难度越大(比方说运行时)。如果把神经网络用作电路图,越深层的神经网络越能执行更多的算法运算——深度=力度。
注意:需要明白一点的是神经网络中的单个神经元能够对输入聚集或输入分集进行计算,要做的就是对它们的连接赋上合适的值。
出人意料的是,事实上神经网络比布尔电路更加高效。进一步说,要解决某个问题,一个相当浅层DNN的层次开销比布尔电路所需的要少得多。例如,一个有着两个隐藏层和适量计算单元的DNN能够对NN位数字进行排序。当我知道这结论时是相当的惊讶,所以我尝试创建一个小型神经网络然后训练它使之对106位数字进行排序,其执行结果与结论高度一致!而如果使用布尔电路对NN位数排序,在相同条件下,这是实现不了的。
DNN比布尔电路高效的原因是神经元会执行阈值操作,而微布尔电路则做不到。
最后,尽管人类神经元速度慢,但能在短时间内完成很多复杂的任务。具体地说,有个常识是一个人类神经元每秒的运作次数少于100次。意即假若某人能在0.1秒内解决问题,我们的神经元在足够时间内只会运作10次。所以说一个10层大型神经网络能够完成任何人类需时0.1秒来做完的任务。
人的普遍认知是人类神经元要比人工神经元强大得多,但其实有可能相反。究竟孰优孰劣,暂时还言之尚早。
有趣的是,人类通常能在0.1秒左右解决极其复杂的认知问题。例如,对于眼前的事物,不论是表情,脸部还是语言交流,我们都能很快识别并作出反应。事实上,如果世上有一个人能解决最复杂的问题,即使仅有一位,也足够说服人们相信LDNN能做到相同的事情——务必确保获得正确的数据输入。
小型神经网络可行吗?也许是的。人的神经网络必定无法进行指数级生长,因为人的脑部是不可能疯长的!如果人的神经元出现杂音,意思是当一个人工神经元可以完成需要多个人类神经元合力才能完成的工作时,与人脑相匹配的DNN所需的神经元个数将明显减少。
上述的几个争论点主要阐明了在不同情况下,存在着一个能基本解决问题的LDNN连接配置。关键的,解决问题所需的单元个数要远少于指数级;因此,利用现有硬件来训练并获得一个高性能网络是可行的。最后的这点非常重要,以下继续深入说明。
我们知道机器进行算法学习是持续性的:也就是说,只要提供充足的数据,它们就能把问题解决。但持续性往往意味着指数级的大数据量。举例来说,当最近邻算法把所有可能性都考虑到了,便能解决任何问题;向量机与此类似,需要做的是提供足够的训练样本。这同样适用于一个有着单个隐藏层的神经网络:如果每个可能的训练样本都对应着一个神经元,而该神经元不关心其他事例,那么我们便可从输入和输出中学习并展示每个可能的功能。问题解决依赖于数据,但在有限的资源里不一定任何时候都能实现。
这便是LDNN与旧版的区别:使用大型而非巨大的LDNN来解决实际问题。如果人能短时间内解决问题,就足以证明即使是最小型神经网络也蕴藏着巨大的能力。
我必须承认的一点是,DNN能否把给定的问题解决好还有待时间来证明,虽然LDNN常常能在可操作的数据范围内把同一个问题处理好。
这就是我要说的。对于某个问题,例如是视觉目标识别,我们所要做的是要对一个50层巨型卷积码神经网络进行训练。显然达到如此级别的神经网络足以与人类神经网络媲美,不是吗?所以找到这样的权值是成败的关键。
学习
什么是学习?学习是为神经网络权值找到合适的设置值来使训练数据效益最大化。换言之,我们要把来自标识数据的信息作为输入参数,以供神经网络使用。
深度学习的成功取决于一个幸运的事实:精心调配并已初始化好的随机梯度下降法(SGD)能够很好地对LDNN进行训练。这是有意义的,因为一个神经网络的训练错误也是其权值的功能时,该错误是高度非凸的。当进行非凸优化时,其结果是不可预知的;只有结果为凸是好的,非凸就是不好的。但SGD看起来似乎能对此做出改善。对神经网络进行训练是个NP困难,事实上要找出有着3个隐藏单元的神经网络最佳数据集是NP困难的。而SGD能在实际中解决该问题。这是深度学习的立足之本。
可以相当自信地说,成功的LDNN训练依赖于数据的“简单”关联,从而使LDNN不断自我学习以解决数据的“复杂”关联。对此我有着一个成功的实验:训练一个神经网络来解决奇偶问题是较困难的。我成功实现了25bits、29bits的检验,但从来没有超过30bits(或许有人可以实现,但我真的还没有)。现在,我们知道奇偶问题是非常不稳定的,它缺乏任何的线性关联:每个线性输入与输出是不关联的,这对于神经网络是个问题,因为在初始化时神经网络是高度线性的(难道说我需要使用更大的初始权值?有关权值初始问题会在稍后讲述)。所以我的假设是(很多专家也分享过),当神经网络开始进行学习时就已关注到输入输出高度关联,当引入隐藏单元对此进行监测时,神经网络便可处理更复杂的关联。我设想了更多样的关联,包括简单和复杂,一个网络从一个关联跳入更复杂的关联,这不正是机会主义登山者的真实写照吗?
泛化
虽然有关神经网络优化还缺乏实质性谈资(除了又凸又无聊的局部最小值问题),相比之下泛化的讨论则可有趣且具体得多。
例如以下这件往事:Valiant在1984年发表一篇名为“可学习理论”的著名论文,他简单证明了如果给定有限的函数个数,比方说N个,一旦有着比log N更多的训练案例而该增量是个很小的常量因子时,每次训练错误将会接近每次测试错误。显然,如果所有的训练错误都接近它的测试错误,那么过度拟合基本上是不可能的(当训练错误和测试错误之间差距太大的时候才会发生拟合。我也曾在Vapnik书中看过类似结论)。这个定理很容易证明,这里就不多说了。
但这个简单的结果对任何神经网络的实现都有着非常重要的意义。假如有一个含有N个参数的神经网络,每个参数都是32位float。那么当一个神经网络被指定为32×N bits时,那么意味着不同的神经网络不会超过2³²ⁿ,甚至更少。也就是说,一旦有着超过32×N的训练样本,我们不会过度拟合多少。这样很好。理论上我们可以对参数进行计数。更重要的是,如果我们确信每个权值仅需要4个bits,而其他都是噪值,那么训练样本的数字必定是一个很小的常量因子4×N,而不是32×N。
结论
如果我们要使用一个LDNN来解决难题,就需要给予足够的参数。所以我们需要一个超高质量的标记训练集,使之确保有足够的信息来匹配所有的网络连接。一旦得到了该训练集,我们应该在这之上运行SGD直到问题解决。如果神经网络是较大而深的,这是可实现的。
80年代以来的改变
过去,人们曾认为神经网络可以解决“一切问题”。但最后为什么没有成功呢?这里面有如下几个原因。
- 过去计算机速度很慢,因此过去的神经网络是微型的,这导致性能的先天不足。换句话说,小型神经网络功能不强。
- 数据集很小。即使能奇迹般地训练LDNN,也缺乏足够的大信息数据集来约束巨量的神经网络参数。所以失败是不可避免的。
- 没有人知道如何训练深度网络。深度网络很重要。当前20-25个连续圈层是最好的对象识别网络配置。一个两层的神经网络注定在对象识别上是低效的。在过去人们认为SGD不可能用来训练深度网络,因为当时认为这是难以置信的。
科学发展是多么的有趣,特别是回首以往,会发现现在进行深度神经网络训练是小事一桩了。
实践建议
好吧,或许你已经跃跃欲试了。LDNN代表着现在也代表着未来,难道不想训练它?但传言说LDNN很高深,这是真的吗?过去或许是,但现在很多社区已经做出努力和尝试,只要把以下所述牢记于心,训练神经网络就不会太难。下面是有关社区的知识总结,这很重要请仔细阅读。
获取数据:确保要有高质量的输入/输出数据集,这个数据集要足够大、具有代表性以及拥有相对清楚的标签。缺乏数据集是很难成功的。
预处理:将数据进行集中是非常重要的,也就是要使数据均值为0,从而使每个维度的每次变动为1。有时,当输入的维度随量级排序变化时,最好使用那个维度的log(1+x)。基本上,重要的是要找到一个0值的可信编码以及自然分界的维度。这样做可使学习工作得更好。情况就是这样的,因为权值是通过公式来更新的:wij中的变化 \propto xidL/dyj(w表示从层x到层y的权值,L是损失函数)。如果x的均值很大(例如100),那么权值的更新将会非常大,并且是相互关联的,这使得学习变得低劣而缓慢。保持0均值和较小的方差是成功的关键因素。
批处理:在如今的计算机上每次只执行一个训练样本是很低效的。反之如果进行的是128个例子的批处理,效率将大幅提高,因为其输出量是非常可观的。事实上使用数量级为1的批处理效果不错,这不仅可获得性能的提升同时可降低过度拟合;不过这有可能会被大型批处理超越。但不要使用过大的批处理,因为有可能导致低效和过多过度拟合。所以我的建议是:根据硬件配置选取适合的批处理规模,量力而为会更加高效。
梯度归一化:根据批处理的大小来拆分梯度。这是一个好主意,因为如果对批处理进行倍增(或倍减),无需改变学习率(无论如何,不要太多)。
学习率计划:从一个正常大小的学习率(LR)开始,朝着终点不断缩小。
1LR的典型取值是 0.1,令人惊讶的是,对于大量的神经网络问题来说,0.1是学习率的一个很好的值。通常学习率倾向于更小而非更大。
使用一个 验证集——一个不进行训练的训练集子集,来决定何时降低学习率以及何时停止训练(例如当验证集的错误开始增多的时候)。
学习率计划的实践建议:若发现验证集遭遇瓶颈,不妨将LR除以2(或5),然后继续。最终,LR将会变得非常小,这也到了停止训练的时候了。这样做可以确保在验证性能受到损害的时候,你不会拟合(或过度拟合)训练数据。降低LR是很重要的,通过验证集来控制LR是个正确的做法。
但最重要的是要关注学习率。一些研究人员(比如Alex Krizhevsky)使用的方法是,监视更新范数和权值范数之间的比率。比率取值大约为10¯³。如果取值过小,那么学习会变得非常慢;如果取值过大,那么学习将会非常不稳定甚至失败。
权值初始化。关注权值在学习开始时的随机初始化。
如果想偷懒,不妨试试0.02*randn(num_params)。这个范围的值在许多不同的问题上工作得很好。当然,更小(或更大)的值也值得一试。
如果它工作得不好(例如是一个非常规的和/或非常深的神经网络架构),那么需要使用init_scale/sqrt(layer_width)*randn来初始化每个权值矩阵。在这种情况下,init_scale应该设置为0.1或者1,或者类似的值。
对于深度且循环的网络,随机初始化是极其重要的。如果没有处理好,那么它看起来就像没有学习到任何东西。我们知道,一旦条件都设置好了,神经网络就会学习。
一个有趣的故事:多年来,研究人员相信SGD不能训练来自随机初始化的深度神经网络。每次尝试都以失败告终。令人尴尬的是,他们没有成功是因为使用“小的随机权值”来进行初始化,虽然小数值的做法在浅度网络上工作得非常好,但在深度网络上的表现一点也不好。当网络很深时,许多权值矩阵之间会进行乘积,所以不好的结果会被放大。
但如果是浅度网络,SGD可以帮助我们解决该问题。
所以关注初始化是很有必要的。尝试多种不同的初始化,努力就会得到回报。如果网络完全不工作(即没法实施),继续改进随机初始化是正确的选择。
如果正在训练RNN或者LSTM,要对梯度(记得梯度已除以批量大小)范数使用一个硬约束。像15或者5这样的约束在我个人的实验中工作得很好。请将梯度除以批处理大小,再检查一下它的范数是否超过15(或5)。如果超过了,将它缩小到15(或5)。这个小窍门在RNN和LSTM的训练中发挥着巨大作用,不这样做的话,爆炸性的梯度将会导致学习失败,最后不得不使用像1e-6这样微小而无用的学习率。
数值梯度检查:如果没有使用过Theano或者Torch,梯度实现只能亲力亲为了。在实现梯度的时候很容易出错,所以使用数值梯度检查是至关重要的。这样做会让你对自己的代码充满信心。调整超级参数(比如学习率和初始化)是非常有价值的,因此好刀要用在刀刃上。
如果正在使用LSTM同时想在具有大范围依赖的问题上训练它们,那么应该将LSTM遗忘关口的偏差初始化为较大的值。默认状态下,遗忘关口是S型的全部输入,当权值很小时,遗忘关口会被设置为0.5,这只能对部分问题有效。这是对LSTM初始化的一个警示。
数据增加(Data augmentation):使用算法来增加训练实例数量是个有创意的做法。如果是图像,那么应该转换和旋转它们;如果是音频,应该将清晰的部分和所有类型的杂音进行混合处理。数据添加是一门艺术(除非是在处理图像),这需要一定的常识。
dropout:dropout提供了一个简单的方法来提升性能。记得要调整退出率,而在测试时不要忘记关闭dropout,然后对权值求乘积(也就是1-dropout率)。当然,要确保将网络训练得更久一点。不同于普通训练,在进入深入训练之后,验证错误通常会有所增加。dropout网络会随着时间推移而工作得越来越好,所以耐心是关键。
综合(Ensembling)。训练10个神经网络,然后对其预测数据进行平均。该做法虽然简单,但能获得更直接、更可观的性能提升。有人可能会困惑,为什么平均会这么有效?不妨用一个例子来说明:假如两个分类器的错误率为70%,如果其中一个的正确率保持较高,那么平均后的预测会更接近正确结果。这对于可信网络的效果会更加明显,当网络可信时结果是对的,不可信时结果是错的。
以上13点意见涵盖了成功训练LDNN的一切,希望我没有遗漏。
最后总结如下:
- LDNN是非常强大的;
- 如果有台高性能计算机,LDNN是可训练的;
- 如果有一个超高质量的数据集,我们可以为任务找到最好的LDNN;
- LDNN可以解决问题,或者说至少对解决问题有所帮助。
写在最后
未来会是怎样的呢?预测未来显然是困难的,但一般而言,能够执行更多计算的模型也许会非常好。神经图灵机在这个方向上迈出了非常重要的一步。其他问题,包括无监督学习,截止2015年1月8日,于我而言还仅是冰山一角。使用无监督学习来学习复杂数据是个很好的尝试。路漫漫其修远兮,我们仍需努力。