英文原文:http://neuralnetworksanddeeplearning.com/
对原文的表达有部分改动
人类的视觉系统可以堪称自然界的奇迹之一。我们来看一下下面的手写数字序列:
大多数人可以不费吹灰之力地将这些数字识别为 504192
。我们也许觉得这很简单,其实,这种简单在微观上却具有极大的复杂性。在我们大脑的每个半球,都有一个初级视觉皮层,也称为 V1,包含 1.4 亿个神经元,它们之间有数百亿个连接。然而,人类视觉不仅涉及 V1,还涉及整个系列的视觉皮层:V2、V3、V4 和 V5,可以进行更复杂的图像处理。我们的头脑中仿佛携带着一台超级计算机(比当前任何一台计算机都智能),经过数亿年的进化,已然变得非常适合理解视觉世界。其实,识别手写数字并不容易。相反,我们人类非常善于理解我们的眼睛向我们展示的东西。但几乎所有这些工作都是在不知不觉中完成的。所以我们通常不会意识到我们的视觉系统所解决的问题有多难。
如果您尝试编写计算机程序来识别上述数字序列,那么视觉模式识别的困难就变得显而易见了。当我们自己做时,看起来很容易的事情突然变得非常困难。关于我们如何识别形状的简单直觉:“一个 9 在顶部有一个环,在右下角有一个垂直的笔划”,明显不是那么简单的算法表达。当您试图使这些规则编写代码时,您很快就会迷失在代码异常、警告和特殊情况的迷雾中。
神经网络以不同的方式解决这个问题。具体的做法是取大量的手写数字,称为训练样本(train_set):
然后开发一个可以从这些训练示例中学习的系统。换句话说,神经网络使用训练样本自动推断出识别手写数字的规则
。此外,通过增加训练样本的数量,神经网络可以学习更多关于手写的知识,从而提高其识别的准确性。虽然在上面只展示了 100 个训练数字,但也许我们可以通过使用数千甚至数百万或数十亿的训练示例来构建更好的手写识别器。
在本章中,我们将编写一个计算机程序,实现一个学习识别手写数字的神经网络。该程序只有 74 行,并且没有使用特殊的神经网络第三方库。但是这个简短的程序可以在没有人工干预的情况下以超过 96% 的准确率识别数字。此外,在后面的章节中,我们将提出可以将准确率提高到 99% 以上的想法。事实上,现在的商业神经网络已经可以表现得很准确稳定,银行用它们来处理支票,邮局用它们来识别地址。
之所以以手写识别作为入门的例子,因为它是学习一般神经网络的一个很好的原型问题。作为原型,它达到了一个最佳点:它具有挑战性,识别手写数字并非易事,但它并没有困难到需要极其复杂的解决方案或巨大的计算能力。此外,这是开发更高级技术(例如深度学习)的前置内容。因此,在整本系列中,我们将反复回到手写识别的问题上。在系列的后续,我们将讨论如何将这些想法应用于计算机视觉以及语音、自然语言处理和其他领域的其他问题。
此过程中,我们将开发许多关于神经网络的关键思想,包括两种重要的人工神经元:感知器(perceptron)和 sigmoid 神经元(sigmoid neuron),以及神经网络的标准学习算法,称为随机梯度下降(stochastic gradient descent)。在整个过程中,我专注于解释为什么事情会以这种方式完成,以及建立你对于神经网络直觉。这可能需要更长时间的讨论,但对于您将获得的更深入的理解来说,这是值得的。在收益中,在本章结束时,我们将能够理解深度学习是什么,以及它为什么重要。
感知器(Perceptron)
什么是神经网络?首先,我们将解释一种称为感知器的人工神经元。感知器是在 1950 年代和 1960 年代由科学家 Frank Rosenblatt 开发的,其灵感来自 Warren McCulloch 和 Walter Pitts 的早期工作。如今,使用其他人工神经元模型更为常见。在本系列后续,以及在神经网络的许多现代工作中,使用的主要神经元模型是一种称为 sigmoid 神经元的模型。我们很快就会谈到 sigmoid 神经元。但是要理解为什么 sigmoid 神经元是这样定义的,首先花时间了解感知器通常是值得的。
那么感知器是如何工作的呢?感知器接受多个二进制输入 , ...,并产生单个二进制输出:
在所示示例中,感知器具有三个输入,。一般来说,它可以有更多或更少的输入。 Rosenblatt 提出了一个简单的规则来计算输出。他引入了权重 ,用来表示各个输入对输出的重要性(权重)。神经元的输出 0 或 1 取决于加权和 是小于还是大于某个阈值。就像权重一样,阈值是也是一个实数,它是神经元的参数。用更精确的代数术语来说:
这就是基本的数学模型。换句话说,它是一种通过具有权衡证据来做出决策的设备。举个例子吧。虽然这不是一个非常现实的例子,但它很容易理解,我们很快就会得到更现实的例子。假设周末快到了,您听说您所在的城市将举办奶酪节。你喜欢奶酪,并且正在决定是否去参加这个节日活动。您可能会通过权衡三个因素来做出决定:
- 天气好吗?
- 你的伴侣愿意陪你吗?
- 活动地点在公共交通附近吗?(因为你没有车)。
我们可以用对应的二元变量 来表示这三个因素。例如,如果天气好,我们会有 ,如果天气不好,我们会有 。同样,如果你的伴侣想去,,否则。对于 同样如此。
现在,假设你非常喜欢奶酪,以至于你很高兴去参加这个节日活动,即使你的伴侣不感兴趣并且活动地点附近交通不便利。但你真的很讨厌坏天气,如果天气不好,你就不可能去参加这个节日活动。您可以使用感知器对这种决策进行建模。一种方法是为天气选择权重 ,为其他条件选择 和。 的较大值表明天气对您来说很重要,远比您的伴侣是否加入您或公共交通的便利性来得更重要。最后,假设您为感知器选择了 5 的阈值。通过这些选择,感知器实现了所需的决策模型,天气好的时候输出 1,天气不好时输出 0。无论你的伴侣想去,或者附近是否有公共交通,输出都没有区别,除非是坏天气。
通过改变权重和阈值,我们可以获得不同的决策模型。例如,假设我们选择了 3 的阈值。那么感知器会决策你必须在天气好的时候去节日活动,后面两个条件只有一个为否时。换句话说,这将是一种不同的决策模型。降低阈值意味着你更愿意去参加这个节日活动。
显然,感知器并不是人类决策的完整模型!但是这个例子说明的是感知器如何权衡不同类型的证据以做出决定。一个复杂的感知器网络可以做出非常微妙的决定,这似乎是合理的:
在这个网络中,第一列的感知器我们称之为第一层感知器:通过权衡输入证据做出三个非常简单的决定。第二层的感知器中的每一个都通过权衡第一层决策的结果来做出决策。通过这种方式,第二层中的感知器可以在比第一层中的感知器更复杂和更抽象的层次上做出决策。第三层的感知器以第二层为基础。通过感知器的多层网络,系统可以进行复杂的决策。
让我们简化描述感知器的方式。条件 很麻烦,我们可以做两个符号更改来简化它。第一个变化是将 写为点积 ,其中 和 是向量,分别是权重和输入。第二个变化是将阈值移到不等式的另一侧,并用所谓的感知器偏差(bias): 替换它。重写感知器的规则:
您可以将偏差视为衡量感知器输出 1 的难易程度。或者用更生物学的术语来说,偏差衡量感知器触发(fire)的难易程度。对于一个偏差很大的感知器,感知器输出一个1是非常容易的。但是如果偏差远小于 0,那么感知器就很难输出一个1。稍后会看到引入偏差会导致进一步的符号简化。因此,在本系列的其余部分,我们不会使用阈值,我们将始终使用偏差。
我已经将感知器描述为一种权衡证据以做出决定的系统。感知器的另一种使用方式是计算我们通常认为是底层计算的基本逻辑函数,如 AND、OR 和 NAND 等函数。例如,假设我们有一个带有两个输入的感知器,每个输入的权重为 -2,总偏差为 3。这是我们的感知器:
然后我们看到输入 00 产生输出 1,因为 是正的。在这里,我引入了 ∗ 符号以使乘法更加明确。类似的计算表明,输入 01 和 10 产生输出 1。但输入 11 产生输出 0,因为 为负。所以我们的感知器实现了一个 NAND!
NAND 示例表明我们可以使用感知器来计算简单的逻辑函数。事实上,我们可以使用感知器网络来计算任何逻辑函数。我们可以在 NAND 之外构建任何计算。例如,我们可以使用 NAND 来构建一个电路,该电路将两个位 和 相加。这需要计算按位和,,以及当 和 都是 1 时设置为 1 的进位,即进位位只是按位乘积 :
为了获得等效的感知器网络,我们将所有 NAND 替换为具有两个输入的感知器,每个输入的权重为 -2,总偏差为 3。这是生成的网络:
这个感知器网络的一个值得注意的地方是最左边感知器的输出被用作最底部感知器的输入两次。我在定义感知器模型的时候并没有说是否允许这种双输出到同一个地方。其实,也没什么大不了的。如果我们不想允许这种事情发生,那么可以简单地将两条线合并为一个权重为 -4 的连接,而不是两个权重为 -2 的连接。 有了这个变化,网络看起来如下,所有未标记的权重等于 -2,所有偏差等于 3,以及一个单个权重为 -4,如下图所示:
到目前为止,我一直在绘制像 和 这样的输入作为在感知器网络左侧的变量。事实上,传统的做法是画一个额外的感知器层:输入层来对输入进行编码。输入感知器有一个输出,但没有输入:
可以将输入感知器与前面提到的感知器区分开,输入感知器向后续的感知器网络输出所需要的输入,本身并没有输入需要处理。
加法器示例演示了如何使用感知器网络来模拟包含许多 NAND 的电路。并且因为 NAND 对于计算是通用的,因此感知器对于计算也是通用的。
感知器的计算通用性使得感知器网络可以像任何其他计算设备一样强大。它也让人觉得感知器只是一种新型的 NAND。这算不上什么新鲜玩意!
事实证明,我们可以设计学习算法,该算法可以自动调整人工神经元网络的权重和偏差。这种调整是为了响应外部刺激而发生的,无需程序员的直接干预。这些学习算法使我们能够以与传统逻辑门完全不同的方式使用人工神经元。我们的神经网络无需明确地布置 NAND 和其他门电路,而是可以简单地学习解决问题。