《神经网络和深度学习》系列文章三十三:一个输入和一个输出的普遍性

​出处: Michael Nielsen的《Neural Network and Deep Learning》。本节译者:朱小虎 、张广宇。


目录

1、使用神经网络识别手写数字

2、反向传播算法是如何工作的

3、改进神经网络的学习方法

4、神经网络可以计算任何函数的可视化证明

  • 两个预先声明
  • 一个输入和一个输出的普遍性
  • 多个输入变量
  • S型神经元的延伸
  • 修补阶跃函数
  • 结论

5、为什么深度神经网络的训练是困难的

6、深度学习



为了理解为何普遍性定理成立,我们先从理解如何构造这样一个神经网络开始,它能够近似一个只有一个输入和一个输出的函数:



结果表明,这其实是普遍性问题的核心。一旦我们理解了这个特例,那么实际上就会很容易扩展到那些有多个输入输出的函数上。


为了构建关于如何构造一个计算 f 的网络的理解,让我们从一个只包含一个隐藏层的网络开始,它有两个隐藏神经元,和单个输出神经元的输出层:



为了感受一下网络的组成部分工作的机制,我们专注于最顶上的那个隐藏神经元。在下图例 子中,展示了顶部隐藏神经元的权重 w,偏置 b 和输出曲线的关系。思考最上面的隐 藏神经元变化如何计算函数:



正如我们在本书前面学到的,隐藏神经元在计算的 是 ,这里 是 S 型函数。目前为止, 我们已经频繁使用了这个代数形式。但是为了证明普遍性,我们会完全忽略其代数性质,取 而代之的是在图形中调整和观察形状来获取更多的领悟。这不仅会给我们更好的感性认识, 而且它也会给我们一个可应用于除了S型函数之外其它激活函数的普遍性的证明。[1]

开始,增加偏置 b 的值。当偏置增加时,图形往左移动,但是形状不变。


接下来,减小偏置。当偏置减小时图形往右移动,但是再一次,它的形状没有变化。


继续,将权重减小到大约 2 或 3。当你减小权重时,曲线往两边拉宽了。你可以同时 改变偏置,让曲线保持在框内。


最后,把权重增加到超过 w = 100。当你这样做时,曲线变得越来越陡,直到最终看上去 就像是一个阶跃函数。试着调整偏置,使得阶跃位置靠近 x = 0.3。下面一个图示显示你 应该看到的结果。



你能给权重增加很大的值来简化我们的分析,使得输出实际上是个非常接近的阶跃函数。下 面我画出了当权重为 w = 999 时从顶部隐藏神经元的输出。



实际上处理阶跃函数比一般的 S 型函数更加容易。原因是在输出层我们把所有隐藏神经元的 贡献值加在一起。分析一串阶跃函数的和是容易的,相反,思考把一串 S 形状的曲线加起来 是什么则要更困难些。所以假设我们的隐藏神经元输出阶跃函数会使事情更容易。更具体些, 我们把权重 w 固定在一个大的值,然后通过修改偏置设置阶跃函数的位置。当然,把输出 作为一个阶跃函数处理只是一个近似,但是它是一个非常好的近似,现在我们把它看作是精 确的。稍后我会再讨论偏离这种近似的影响。


x 取何值时阶跃会发生呢?换种方式,阶跃的位置如何取决于权重和偏置?


为了回答这个问题,试着修改上面图中的权重和偏置(你可能需要向上滚动一点)。你能不 能算出阶跃的位置如何取决于 w 和 b?做点工作你应该能够说服自己,阶跃的位置 和 b 成正比,和 w 成反比。


实际上,阶跃发生在 s = -b/w 的位置,正如你能在下图中通过修改权重和偏置看到的:



这将用仅仅一个参数 s 来极大简化我们描述隐藏神经元的方式,这就是阶跃位置,s = -b/w。试着修改下图中的 s,以便习惯这个新的参数设定:



正如上面注意到的,我们隐式地设置输入上的权重 w 为一些大的值~——~大到阶跃函数能 够很好地近似。通过选择偏置 b = -ws,我们能很容易地将一个以这种方式参数化的神经 元转换回常用的模型。


目前为止我们专注于仅仅从顶部隐藏神经元输出。让我们看看整个网络的行为。尤其,我们 假设隐藏神经元在计算以阶跃点 s1 (顶部神经元)和 s2 (底部神经元)参数化的 节约函数。它们各自有输出权重 w1 和 w2。是这样的网络:



右边的绘图是隐藏层的加权输出 w1 a1 + w2 a2。这里 a1 和 a2 各 自是顶部和底部神经元的输出[2]。这些输出由 a 表示,是因为它们通常被称为神经元的激活值(activations)。


试着增加和减小顶部隐藏神经元的阶跃点 s1。感受下这如何改变隐藏层的加权输出。尤 其值得去理解当 s1 经过 s2 时发生了什么。你会看到这时图形发生了变化,因为我 们从顶部隐藏神经元先被激活的情况变成了底部隐藏神经元先被激活的情况。


类似地,试着操作底部隐藏神经元的阶跃点 s2,感受下这如何改变隐藏神经元混合后的 输出。

尝试增加和减少每一个输出权重。注意,这如何调整从各自的隐藏神经元的贡献值。当一个 权重是 0 时会发生什么?


最后,试着设置 w1 为 0.8,w2 为 -0.8。你得到一个“凸起”的函数,它从 点 s1 开始,到点 s2 结束,高为 0.8。例如,加权后的输出可能看起来像这样:



当然,我们可以调整为任意的凸起高度。让我们用一个参数,h,来表示高度。为了减少混 乱我也会移除“”和“”的标记。



试着将 h 值改大或改小,看看凸起的高度如何改变。试着把高度值改为负数,观察发生了 什么。并且试着改变阶跃点来看看如何改变凸起的形状。


顺便提一下,你会注意到,我们用神经元的方式,可以认为不只是在图形的角度,而且是更 传统的编程形式,作为 if-then-else 的一种声明,即:



对于大部分内容,我将坚持以图形的考虑角度。但在接下来的内容中,你有时可能会发现交 换考虑角度是有帮助的,并且考虑 if-then-else 的形式。


我们可以用凸起制作的技巧来得到两个凸起,通过把两对隐藏神经元一起填充进同一个网络:



这里我抑制了权重,只是简单地在每对隐藏神经元上写了 h 的值。试着增加和减少两 个 h 值,观察它如何改变图形。通过修改节点来移动凸起。


更普遍地,我们可以利用这个思想来取得我们想要的任何高度的峰值。尤其,我们可以把间 隔 [0, 1]分成大量的子区间,用 N 表示,并利用 N 对隐藏神经元来设置任意期望高 度的峰值。让我们看看 N = 5 这如何工作。那样确实有很多神经元,所以我打算弄得挤一 些。抱歉这个图示有些复杂:我能通过更进一步的抽象来隐藏其复杂性,但是我想多些复杂 是值得的,为了获得网络如何工作的更具体的感受。



你能看到有五对隐藏神经元。每对神经元对应的连接点是 0, 1/5,然后是 1/5, 2/5等 等,最后到 4/5, 5/5。这些值是固定的 -- 它们使得我们在图形上得到五个均匀分布的凸起。


每对神经元有一个值 h 和它联系。记住,神经元输出的连接有权重 h 和 -h (未标 记)。点击一个 h 值,左右拖动鼠标来改变其值。当你这么做的时候,观察函数的变化。 通过改变输出权重我们实际上在设计这个函数。


相反地,试着在图形上点击,上下拖动来改变凸起函数的高度。当你改变高度,你能看到相 应的 h 值的变化。而且,虽然没有显示,在对应的输出权重上也有一个变 化,+h 和-h。


换句话说,我们可以直接操作右边图形里的函数,然后看看反映到左边的 h 值。一个有趣 的事情是按住鼠标按键并从图形的一边拖动到另一边。这样做你拉出了一个函数,观察神经网络中为了适应这个函数调整的参数。


是时候来个挑战了。


让我们回想我在本章开始绘制出的函数:



那时我没有说,但是我绘制的其实是函数


        (113)


x 取值范围从 0 到 1,y 轴取值为 0 到 1。


它明显不是一个微不足道的函数。


你将要解出如何使用一个神经网络来计算它。


在我们上面的网络中,我们已经分析了隐藏神经元输出的加权组合。我们现在知道如何在这个量上获得大量的控制。但是,正如我前面所指 出的,这个量不是网络的输出。网络输出的是  ,其中 b 是在输出神经元的偏置。有什么办法可以实现对网络的实际输出控制吗?


解决方案是设计一个神经网络,它的隐藏层有一个加权输出 ,其中 是  函数的倒数。也就是说,我们希望从隐藏层的加权输出是:



如果你能这样做,那么整体来看网络的输出会是 f(x) 的一个很好的近似 。[3]


那么你的挑战,是在 网页上设计一个神经网络可近似上面显示的目标函数。为了尽可能多地学习,我希望你 能分两次解决这个问题。第一次,请在图形上点击,直接调整不同的凹凸函数的高度。你应 该能发现找到一个很好的匹配的目标函数是很容易的。你做的有多好通过目标函数和网络实 际计算函数的平均偏差来衡量。你的挑战是尽可能低的平均偏差。当你将平 均偏差争取到 0.40 或以下时,你完成了挑战。


一旦你完成了,点击“重置”,随机重新初始化凹凸形状。你第二次解决问题时,忍住在图 形上点击的冲动。相反,修改左边的 h 值,并再次尝试将平均偏差争取到 0.40 或以 下。点击下面的图形可链接到网页并开始你的设计。



一个完成的图形看起来像是这样:



你现在已经解决了所有网络的必要元素来近似计算函数 f(x)!这只是一个粗略的近似, 但我们可以很容易地做得更好,仅仅通过增加隐藏神经元对的数量,分配更多的凹凸形状。


特别是,将我们已经找到的所有数据转换回神经网络使用的标准参数设定是很容易的。让我 快速总结一下那是如何工作的。


第一层的权重都有一些大的,恒定的值,比如:w = 1000。


隐藏神经元上的偏置只是 b = -w s。例如,对于第二个隐藏神经元 s = 0.2 变成了 b = -1000 * 0.2 = -200。


最后一层的权重由 h 值决定。例如,我们上面已经选择的第一个 h,h = -0.5,意 味着顶部两个隐藏神经元的相应的输出权重是 -0.5 和 0.5。如此等等,确定整个层的 输出权重。


最后,输出神经元的偏置为 0。


这是所有要做的事情:现在我们有了一个可以很好计算我们原始目标函数的神经网络的完整 的描述。而且我们理解如何通过提高隐层神经元的数目来提高近似的质量。


更重要的是,关于我们的原始目标函数 ,没有什么特别的。我们可以用这个程序计算任何定义域为 [0, 1],值域为 [0, 1] 的连续函数。在本质上,我们使用我们的单层神经网络来建立一个函数的查找表。 我们将能够建立这个思想,以提供普遍性的一般性证明。


[1] 严格地说,我所采取的可视化方式传统上并不被认为是一个证明。但我相信可视化的方法比 一个传统的证明能给出更深入的了解。当然,这种了解是证明背后的真正目的。偶尔,在 我呈现的推理中会有小的差距:那些有可视化参数的地方,看上去合理,但不是很严谨。 如果这让你烦恼,那就把它视为一个挑战,来填补这些缺失的步骤。但不要忽视了真正的 目的:了解为什么普遍性定理是正确的。

[2]顺便提一下,注意整个网络的输出是,其中 b 是隐藏层的偏置。很明显,这不同于隐藏层加权后的输出, 也就是我们这里的绘图。我们现在打算专注于隐藏层的加权输出,不一会就会考虑如何把 它关联到整个网络的输出。

[3]注意我已经将输出神经元上的偏置设置为 0。


本文来源于哈工大SCIR

原文链接点击即可跳转


哈尔滨工业大学社会计算与信息检索研究中心

入门理论神经网络DNN深度学习哈工大Michael Nielsen