返回介绍

1.14 我们实际上如何更新权重

发布于 2024-01-27 20:58:55 字数 14589 浏览 0 评论 0 收藏 0

我们还没有解决在神经网络更新链接权重中非常核心的问题。我们一直在努力解决这个问题,现在,我们几乎就要到达目标了。在解开这个秘密之前,我们还需要理解一个重要的思想。

到目前为止,我们已经理解了让误差反向传播到网络的每一层。为什么这样做呢?原因就是,我们使用误差来指导如何调整链接权重,从而改进神经网络输出的总体答案。这基本上就是我们使用本书先前所讨论的线性分类器所做的事情。

但是,这些节点都不是简单的线性分类器。这些稍微复杂的节点,对加权后的信号进行求和,并应用了S阈值函数,将所得到的结果输出给下一层的节点。因此,我们如何才能真正地更新连接这些相对复杂节点链接的权重呢?我们为什么不能使用一些微妙的代数来直接计算出权重的正确值呢?

数学太复杂了,因此我们不能使用微妙的代数直接计算出的权重。当我们通过网络前馈信号时,有太多的权重需要组合,太多的函数的函数的函数……需要组合。想想看,即使是一个只有3层、每层3个神经元的小小的神经网络,就像我们刚才使用的神经网络,也具有太多的权重和函数需要组合。在此情况下,你如何调整输入层第一个节点和隐藏层第二个节点之间链路的权重,以使得输出层第三个节点的输出增加0.5呢?即使我们碰运气做到了这一点,这个效果也会由于需要调整另一个权重来改进不同的输出节点而被破坏。你不能将此视为无关紧要的事情。

要意识到这件事情的重要性,请观察下面这个“面目可憎”的表达式,这是一个简单的3层、每层3个节点的神经网络,其中输入层节点的输出是输入值和链接权重的函数。在节点i处的输入是xi ,连接输入层节点i到隐藏层节点j的链接权重为wi,j ,类似地,隐藏层节点j的输出是xj ,连接隐藏层节点j和输出层节点k的链接权重是wj ,k 。那个看似有趣的符号Σb a 意味着对在a和b值之间的所有后续表达式求和。

哎呀!还是让我们不要去硬碰硬地求解这个表达式吧。

如果我们不试图耍聪明,那么我们可以只是简单地尝试随机组合权重,直到找到好的权重组合。

当我们陷入一个困难的问题而焦头烂额时,这不算是一个疯狂的想法。我们称这种方法为暴力方法。有些人使用暴力方法试图破解密码,如果密码是一个英文单词并且不算太长,那么由于没有太多的组合,一台快速的家用计算机就可以搞定,因此这种方法是行之有效的。现在,假设每个权重在-1和+1之间有1 000种可能的值,如0.501、-0.203和0.999。那么对于3层、每层3个节点的神经网络,我们可以得到18个权重,因此有18 000种可能性需要测试。如果有一个相对典型的神经网络,每层有500个节点,那么我们需要测试5亿种权重的可能性。如果每组组合需要花费1秒钟计算,那么对于一个训练样本,我们需要花费16年更新权重!对于1 000种训练样本,我们要花费16 000年!

你会发现这种暴力方法不切实际。事实上,当我们增加网络层、节点和权重的可能值时,这种方法马上就变得不可收拾了。

数学家多年来也未解决这个难题,直到20世纪60年代到70年代,这个难题才有了切实可行的求解办法。虽然对于谁最先解出了这个难题或做出了关键性的突破,大家莫衷一是,但是重要的一点是,这个迟来的发现导致了现代神经网络爆炸性的发展,因此现在的神经网络可以执行一些令人印象深刻的任务。

那么,我们如何解决这样一个明显的难题呢?信不信由你,你已经得到了工具,并且已经可以自己求解这个难题了。先前,我们已经讨论了求解这个问题的方方面面。因此,让我们开始求解这个难题吧!

我们必须做的第一件事是,拥抱悲观主义。

能够表示所有的权重如何生成神经网络输出的数学表达式过于复杂,难以求解。太多的权重组合,我们难以逐个测试,以找到一种最好的组合。

我们有更多可以悲观的理由。训练数据可能不足,不能正确地教会网络;训练数据可能有错误,因此即使我们的假设完全正确,神经网络可以学到一些东西,但却有缺陷;神经网络本身可能没有足够多的层或节点,不能正确地对问题的解进行建模。

这意味着,我们必须承认这些限制,采取实际的做法。如果我们从实际出发可以找到一种办法,虽然这种方法从数学角度而言并不完美,但是由于这种方法没有做出虚假的理想化假设,因此实际上给我们带来了更好的结果。

让我们详细解释一下这是什么意思。想象一下,一个非常复杂、有波峰波谷的地形以及连绵的群山峻岭。在黑暗中,伸手不见五指。你知道你是在一个山坡上,你需要到坡底。对于整个地形,你没有精确的地图,只有一把手电筒。你能做什么呢?你可能会使用手电筒,做近距离的观察。你不能使用手电筒看得更远,无论如何,你肯定看不到整个地形。你可以看到某一块土地看起来是下坡,于是你就小步地往这个方向走。通过这种方式,你不需要完整的地图,也不需要事先制定路线,你一步一个脚印,缓慢地前进,慢慢地下山。

在数学上,这种方法称为梯度下降(gradient descent),你可以明白这是为什么吧。在你迈出一步之后,再次观察周围的地形,看看你下一步往哪个方向走,才能更接近目标,然后,你就往那个方向走出一步。你一直保持这种方式,直到非常欣喜地到达了山底。梯度是指地面的坡度。你走的方向是最陡的坡度向下的方向。

现在,想象一下,这个复杂的地形是一个数学函数。梯度下降法给我们带来一种能力,即我们不必完全理解复杂的函数,从数学上对函数进行求解,就可以找到最小值。如果函数非常困难,我们不能用代数轻松找到最小值,我们就可以使用这个方法来代替代数方法。当然,由于我们采用步进的方式接近答案,一点一点地改进所在的位置,因此这可能无法给出精确解。但是,这比得不到答案要好。总之,我们可以使用更小的步子朝着实际的最小值方向迈进,优化答案,直到我们对于所得到的精度感到满意为止。

这种酷炫的梯度下降法与神经网络之间有什么联系呢?好吧,如果我们将复杂困难的函数当作网络误差,那么下山找到最小值就意味着最小化误差。这样我们就可以改进网络输出。这就是我们希望做到的!

为了正确理解梯度下降的思想,让我们使用一个超级简单的例子来演示一下。

下图显示了一个简单的函数y =(x -1)2 + 1。如果在这个函数中,y 表示误差,我们希望找到x ,可以最小化y 。现在,我们假装这不是一个简单的函数,而是一个复杂困难的函数。

要应用梯度下降的方法,我们必须找一个起点。上图显示了随机选择的起点。就像登山者,我们正站在这个地方,环顾四周,观察哪个方向是向下的。在图上标记了当前情况下的斜率,其斜率为负。我们希望沿着向下的方向,因此我们沿着x 轴向右。也就是说,我们稍微地增加x 的值。这是登山者的第一步。你可以观察到,我们改进了我们的位置,向实际最小值靠近了一些。

我们假设在某个地方开始,如下图所示。

这一次,我们所在之处的斜率为正,因此我们向左移动。也就是说,我们稍微减小x 值。同样,你可以观察到我们已经改善了位置,向真实的最小值靠近了一些。我们可以继续这样操作,直到几乎不能改进为止,这样我们就确信已经到达了最小值。

我们要改变步子大小,避免超调,这样就会避免在最小值的地方来回反弹,这是一个必要的优化。你可以想象,如果我们距离真正的最小值只有0.5米,但是采用2米的步长,那么由于向最小值的方向走的每一步都超过了最小值,我们就会错过最小值。如果我们调节步长,与梯度的大小成比例,那么在接近最小值时,我们就可以采用小步长。这一假设的基础是,当我们接近最小值时,斜率也变得平缓了。对于大多数光滑的连续函数,这个假设是合适的。但是对于有时突然一跃而起、有时突然急剧下降的锯齿函数而言,也就是说存在数学家所说的间断点,这不是一个合适的假设。

下面我们将详细说明,当函数梯度变得较小时调节步长的这种思想,函数梯度是在何种程度上接近最小值的良好指标。

顺便说一句,你是否注意到,我们往相反的梯度方向增加x 值?正梯度意味着减小x ,负梯度意味着增加x 。画图可以让这个现象变得很清晰,但是我们很容易忘记这一点,并经常误入歧途。

当使用梯度下降的方法时, 我们一般不使用代数计算出最小值,我们假装函数y =(x -1)2 + 1是一个非常复杂困难的函数。即使不使用数学精确计算出斜率,我们也可以估计出斜率,在我们往一般的正确方向移动时,你可以发现这种方法也非常适用。

当函数有很多参数时,这种方法才真正地显现出它的亮点。y 也许不单单取决于xy 也可能取决于a、b、c、d、e和f。记得输出函数吧,神经网络的误差函数取决于许多的权重参数,这些参数通常有数百个呢!

同样,下面我们将使用稍微复杂的、依赖2个参数的函数,详细说明梯度下降法。这可以使用三维空间来表示,同时使用高来表示函数的值。

观察这个三维曲面,你可以再次思考,梯度下降是否会终止于右侧的另一个山谷。事实上,在更一般的意义上进行思考,由于复杂的函数有众多的山谷,梯度下降有时会卡在错误的山谷中吗?这个错误的山谷是哪一个呢?答案是肯定的,这种情况可能会发生,也就是我们所到达的山谷可能不是最低的山谷。

为了避免终止于错误的山谷或错误的函数最小值,我们从山上的不同点开始,多次训练神经网络,确保并不总是终止于错误的山谷。不同的起始点意味着选择不同的起始参数,在神经网络的情况下,这意味着选择不同的起始链接权重。

下面详细说明了使用梯度下降方法的三种不同尝试,其中有一次,这种方法终止于错误的山谷中。

让我们暂停,整理一下思路。


关键点

· 梯度下降法是求解函数最小值的一种很好的办法,当函数非常复杂困难,并且不能轻易使用数学代数求解函数时,这种方法却发挥了很好的作用。

· 更重要的是,当函数有很多参数,一些其他方法不切实际,或者会得出错误答案,这种方法依然可以适用。

· 这种方法也具有弹性,可以容忍不完善的数据,如果我们不能完美地描述函数,或我们偶尔意外地走错了一步,也不会错得离谱。

神经网络的输出是一个极其复杂困难的函数,这个函数具有许多参数影响到其输出的链接权重。我们可以使用梯度下降法,计算出正确的权重吗?只要我们选择了合适的误差函数,这是完全可以的。

神经网络本身的输出函数不是一个误差函数。但我们知道,由于误差是目标训练值与实际输出值之间的差值,因此我们可以很容易地把输出函数变成误差函数。

此处,我们要注意一些事情。观察下表,这是3个输出节点的目标值和实际值以及误差函数的候选项。

网络输出

目标输出

误差
(目标值-实际值)

误差
|目标值-实际值|

误差
(目标值-实际值)2

0.4

0.5

0.1

0.1

0.01

0.8

0.7

-0.1

0.1

0.01

1.0

1.0

0

0

0

求和

0

0.2

0.02

误差函数的第一个候选项是(目标值-实际值),非常简单。这似乎足够合理了,对吧?如果你观察对所有节点的误差之和,以判断此时网络是否得到了很好的训练,你会看到总和为0!

这是如何发生的呢?很显然,由于前两个节点的输出值与目标值不同,这个网络没有得到很好的训练。但是,由于正负误差相互抵消,我们得到误差总和为0。总和为零意味着没有误差。然而即使正负误差没有完全互相抵消,这也很明显不符合实际情况,由此你也可以明白这不是一个很好的测量方法。

为了纠正这一点,我们采用差的绝对值,即将其写成|目标值-实际值|,这意味着我们可以无视符号。由于误差不能互相抵消,这可能行得通。由于斜率在最小值附近不是连续的,这使得梯度下降方法无法很好地发挥作用,由于这个误差函数,我们会在V形山谷附近来回跳动,因此这个误差函数没有得到广泛应用。在这种情况下,即使接近了最小值,斜率也不会变得更小,因此我们的步长也不会变得更小,这意味着我们有超调的风险。

第三种选择是差的平方,即(目标值-实际值)2 。我们更喜欢使用第三种误差函数,而不喜欢使用第二种误差函数,原因有以下几点:

· 使用误差的平方,我们可以很容易使用代数计算出梯度下降的斜率。

· 误差函数平滑连续,这使得梯度下降法很好地发挥作用——没有间断,也没有突然的跳跃。

· 越接近最小值,梯度越小,这意味着,如果我们使用这个函数调节步长,超调的风险就会变得较小。

是否有第四个选项呢?有,你可以构造各种各样的复杂有趣的代价函数。一些函数可能完全行不通,一些函数可能对特定类型的问题起作用,一些能够发挥作用的函数,可能由于额外的复杂度而有点不值得。

现在,我们已经跑到了最后一圈,即将到达终点了!

要使用梯度下降的方法,现在我们需要计算出误差函数相对于权重的斜率。这需要微积分的知识。你可能已经对微积分比较熟悉了,但是如果你还不熟悉微积分或者需要提示,那么附录A中包含了一个微积分的简单介绍。微积分使用精确的数学方式,计算出当一些变量改变时,其他应变量如何改变。例如,当在弹簧上施加一个伸展力时,弹簧的长度如何变化。此处,我们感兴趣的是,误差函数是如何依赖于神经网络中的链接权重的。询问这个问题的另一种方式是——“误差对链接权重的改变有多敏感?”

即然我们明白了想要的目标,而画图总是有助于让我们脚踏实地,那么我们就从图形开始吧。

此图与我们先前看到的图一样,主要是强调我们所做的事情没有什么不同。这一次,我们希望最小化的是神经网络的误差函数。我们试图优化的参数是网络链接权重。在这个简单的例子中,我们只演示了一个权重,但是我们知道神经网络有众多权重参数。

下图显示了两个链接权重,这次,误差函数是三维曲面,这个曲面随着两个链接权重的变化而变化。你可以看到,我们努力最小化误差,现在,这有点像在多山的地形中寻找一个山谷。

当函数具有多个参数时,要画出误差曲面相对较难,但是使用梯度下降寻找最小值的思想是相同的。

让我们使用数学的方式,写下想要取得的目标。

这个表达式表示了当权重wj,k 改变时,误差E是如何改变的。这是误差函数的斜率,也就是我们希望使用梯度下降的方法到达最小值的方向。

在我们求解表达式之前,让我们只关注隐藏层和最终输出层之间的链接权重。下图突出显示了我们所感兴趣的这个区域。我们将重回输入层和隐藏层之间的链接权重。

在进行微积分计算时,我们会时不时地返回来参照此图,以确保我们没有忘记每个符号的真正含义。读者请不要被吓倒而裹足不前,这个过程并不困难,我们还会进行解释,我们先前已经介绍了所有所需的概念。

首先,让我们展开误差函数,这是对目标值和实际值之差的平方进行求和,这是针对所有n个输出节点的和。

此处,我们所做的一切,就是写下实际的误差函数E。

注意,在节点n的输出on 只取决于连接到这个节点的链接,因此我们可以直接简化这个表达式。这意味着,由于这些权重是链接到节点k的权重,因此节点k的输出ok 只取决于权重wj,k

我们可以使用另一种方式来看待这个问题,节点k的输出不依赖于权重wj,b ,其中,由于b和k之间没有链接,因此b与k无关联。权重wj,b 是连接输出节点b的链接权重,而不是输出节点k的链接权重。

这意味着,除了权重wj,k 所链接的节点(也就是ok )外,我们可以从和中删除所有的on ,这就完全删除了令人厌烦的求和运算。这是一个很有用的技巧,值得保留下来收入囊中。

如果你喝了咖啡,头脑比较清醒,你可能已经意识到,这意味着误差函数根本就不需要对所有输出节点求和。原因是节点的输出只取决于所连接的链接,就是取决于链接权重。这个过程在许多教科书中一略而过,这些教科书只是简单地声明了误差函数,却没有解释原因。

无论如何,我们现在有了一个相对简单的表达式了。

现在,我们将进行一点微积分计算。记住,如果你不熟悉微积分,可以参考附录A。

t k 的部分是一个常数,因此它不会随着wj,k 的变化而变化。也就是说,tk 不是wj,k 的函数。仔细想想,如果真实示例所提供的目标值根据权重变化,就太让人匪夷所思了!由于我们使用权重前馈信号,得到输出值ok ,因此这个表达式留下了我们所知的依赖于wj,k 的ok 部分。

我们将使用链式法则,将这个微积分任务分解成更多易于管理的小块。

再次参考附录的链式法则介绍。

现在,我们可以反过来对相对简单的部分各个击破。我们对平方函数进行简单的微分,就很容易击破了第一个简单的项。这使我们得到了以下的式子:

对于第二项,我们需要仔细考虑一下,但是无需考虑过久。ok 是节点k的输出,如果你还记得,这是在连接输入信号上进行加权求和,在所得到结果上应用S函数得到的结果。让我们将这写下来,清楚地表达出来。

oj 是前一个隐藏层节点的输出,而不是最终层的输出ok

我们如何微分S函数呢?使用附录A介绍的基本思想,对S函数求微分,这对我们而言是一种非常艰辛的方法,但是,其他人已经完成了这项工作。我们可以只使用众所周知的答案,就像全世界的数学家每天都在做的事情一样。

在微分后,一些函数变成了非常可怕的表达式。S函数微分后,可以得到一个非常简单、易于使用的结果。在神经网络中,这是S函数成为大受欢迎的激活函数的一个重要原因。

因此,让我们应用这个酷炫的结果,得到以下的表达式。

这个额外的最后一项是什么呢?由于在sigmoid()函数内部的表达式也需要对wj,k 进行微分,因此我们对S函数微分项再次应用链式法则。这也非常容易,答案很简单,为oj

在写下最后的答案之前,让我们把在前面的2 去掉。我们只对误差函数的斜率方向感兴趣,这样我们就可以使用梯度下降的方法,因此可以去掉2。只要我们牢牢记住需要什么,在表达式前面的常数,无论是2、3还是100,都无关紧要。因此,去掉这个常数,让事情变得简单。

这就是我们一直在努力要得到的最后答案,这个表达式描述了误差函数的斜率,这样我们就可以调整权重w j,k 了。

嘿!我们成功做到了!

这就是我们一直在寻找的神奇表达式,也是训练神经网络的关键。

这个表达式值得再次回味,颜色标记有助于显示出表达式的各个部分。第一部分,非常简单,就是(目标值-实际值),我们对此已经很清楚了。在sigmoid中的求和表达式也很简单,就是进入最后一层节点的信号,我们可以称之为ik ,这样它看起来比较简单。这是应用激活函数之前,进入节点的信号。最后一部分是前一隐藏层节点j的输出。读者要有一种意识,明白在这个斜率的表达式中,实际涉及哪些信息并最终优化了权重,因此读者值得仔细观察这些表达式、这些项。

这是一个非常奇妙的结果,很多人难以理解这些内容。我们应该为自己感到高兴。

我们还需要做最后一件事情。我们所得到的这个表达式,是为了优化隐藏层和输出层之间的权重。现在,我们需要完成工作,为输入层和隐藏层之间的权重找到类似的误差斜率。

同样,我们可以进行大量的代数运算,但是不必这样做。我们可以很简单地使用刚才所做的解释,为感兴趣的新权重集重新构建一个表达式。

· 第一部分的(目标值-实际值)误差,现在变成了隐藏层节点中重组的向后传播误差,正如在前面所看到的那样。我们称之为ej

· sigmoid部分可以保持不变,但是内部的求和表达式指的是前一层,因此求和的范围是所有由权重调节的进入隐藏层节点j的输入。我们可以称之为ij

· 现在,最后一部分是第一层节点的输出oi ,这碰巧是输入信号。

这种巧妙的方法,简单利用问题中的对称性构建了一个新的表达式,避免了大量的工作。这种方法虽然很简单,但却是一种很强大的技术,一些天赋异禀的数学家和科学家都使用这种技术。你肯定可以使用这个技术,给你的队友留下深刻印象。

因此,我们一直在努力达成的最终答案的第二部分如下所示,这是我们所得到误差函数斜率,用于输入层和隐藏层之间权重调整。

现在,我们得到了关于斜率的所有关键的神奇表达式,可以使用这些表达式,在应用每层训练样本后,更新权重,在接下来的内容中我们将会看到这一点。

记住权重改变的方向与梯度方向相反,正如我们在先前的图中清楚看到的一样。我们使用学习因子,调节变化,我们可以根据特定的问题,调整这个学习因子。当我们建立线性分类器,作为避免被错误的训练样本拉得太远的一种方式,同时也为了保证权重不会由于持续的超调而在最小值附近来回摆动,我们都发现了这个学习因子。让我们用数学的形式来表达这个因子。

更新后的权重wj,k 是由刚刚得到误差斜率取反来调整旧的权重而得到的。正如我们先前所看到的,如果斜率为正,我们希望减小权重,如果斜率为负,我们希望增加权重,因此,我们要对斜率取反。符号α是一个因子,这个因子可以调节这些变化的强度,确保不会超调。我们通常称这个因子为学习率。

这个表达式不仅适用于隐藏层和输出层之间的权重,而且适用于输入层和隐藏层之间的权重。差值就是误差梯度,我们可以使用上述两个表达式来计算这个误差梯度。

如果我们试图按照矩阵乘法的形式进行运算,那么我们需要看看计算的过程。为了有助于理解,我们将按照以前那样写出权重变化矩阵的每个元素。

由于学习率只是一个常数,并没有真正改变如何组织矩阵乘法,因此我们省略了学习率α。

权重改变矩阵中包含的值,这些值可以调整链接权重wj,k ,这个权重链接了当前层节点j与下一层节点k。你可以发现,表达式中的第一项使用下一层(节点k)的值,最后一项使用前一层(节点j)的值。

仔细观察上图,你就会发现,表达式的最后一部分,也就是单行的水平矩阵,是前一层oj 的输出的转置。颜色标记显示点乘是正确的方式。如果你不能确定,请尝试使用另一种方式的点乘,你会发现这是行不通的。

因此,权重更新矩阵有如下的矩阵形式,这种形式可以让我们通过计算机编程语言高效地实现矩阵运算。

实际上,这不是什么复杂的表达式。由于我们简化了节点输出ok ,那些sigmoids已经消失了。

好了!任务完成。


关键点

· 神经网络的误差是内部链接权重的函数。

· 改进神经网络,意味着通过改变权重减少这种误差。

· 直接选择合适的权重太难了。另一种方法是,通过误差函数的梯度下降,采取小步长,迭代地改进权重。所迈出的每一步的方向都是在当前位置向下斜率最大的方向,这就是所谓的梯度下降。

· 使用微积分可以很容易地计算出误差斜率。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文