[译][待续]Chap1.Using neural nets to recognize handwritten digits

时间:2023-03-09 19:28:14
[译][待续]Chap1.Using neural nets to recognize handwritten digits

Chapter1

使用神经网络辨识手写数字

人类的视觉系统是自然界的一大奇迹。试看如下的手写数列:

[译][待续]Chap1.Using neural nets to recognize handwritten digits

绝大多数人都能毫不费劲地认出这些数字是504192,而这会让人产生识别数字非常简单的错觉。人类大脑的每个半球都有初级视觉皮层,其中一个可以被记作V1,包含有1亿4千万的神经元以及它们之间数以百亿计的相互连接。何况人类的视觉系统不仅只有V1,而还包括其他所有的初级视觉皮层:V2,V3,V4和V5,逐步负责着不同复杂程度的图像处理。我们的大脑里有一台超级计算机,经过数亿年的进化,能够极好地适应理解视觉世界。辨识手写数字并不容易。相反,是我们人类对于眼睛看到的信息有惊人、令人惊奇的理解能力。何况几乎所有的工作都是在不被感知的情况下完成的。所以我们经常不能理解,我们视觉系统解决的问题究竟有多困难。

如果你尝试写一个计算机程序来识别如上的手写数列,那么视觉模式识别的难度显而易见。有些事情就是看着容易做着难。一个直觉就是,我们是如何识别形状的——“9这个数字在顶上有一个圆圈,然后在右下角有一条竖线”——这看起来并不能很好地用算法来描述。当你试图明确一些规则的时候,你很快地就会迷失在异常、意外和特殊情况的泥沼里。这看起来可让人绝望。

神经网络用一种完全不同的想法接近问题所在。就是提取大量的手写数字,作为训练样本,

[译][待续]Chap1.Using neural nets to recognize handwritten digits

然后创造一个能从这些样本中自主学习的系统。换一句话说,神经网络用样本自动生成识别手写数字所需要的规则。此外,随着样本数量的增加,神经网络能够学习有关手写字体的更多特征,从而提高它的识别精度。所以,虽然之前只展示了100个训练样本,我们也能通过使用更大的训练样本,创造一个更好的手写字体识别器。

在本章我们会写一个使用神经网络的计算机程序,用来学习并识别手写数字。这个程序的代码只有约74行长,并且没有使用特殊的神经网络库。但这个小程序能够在无人介入的前提下,以约96%的准确率识别手写数据。此外,在以后的章节我们会延伸更好的方法将准确率提高到99%+。事实上,最好的商业神经网络目前正因为其出色的表现,被银行业和邮政行业用于处理支票、辨识地址。

我们着重于手写字体识别,是因为一般地它是很棒的神经网络原型问题。作为一个原型它有着一个巨大优势:具有挑战性。识别手写数字既不容易,也不需要一个极端复杂或者计算量巨大的解决方法。此外,这也是一个发展更先进技术的好方向,比如深度学习。而且贯穿整本书之后,我们将又回到识别手写数字这个问题上来。在这本书之后的内容,我们将讨论计算机视觉里,究竟是如何将这些方法应用到不同问题上的。比如语音合成、自然语言处理及其他领域。

当然,如果本章的目的仅是写出一个识别数字的程序的话,那么它的篇幅将会短小许多。在这一路上,我们将延伸出许多关于神经网络的关键思想,包括最重要的两种人工神经元(感知机和Sigmoid神经元),还有神经网络的标准学习算法,随机梯度下降法。自始至终,我都会把精力放在解释为什么事情是这样发生的,以及打造你自己的神经网络直觉上。对比只说明基本的技巧,这需要一段冗长的讨论。但为了使自己的理解更加深刻,这是值得的。付诸努力之后,在本章节的最后我们将会理解什么是深度学习,以及它为何如此重要。

感知机

什么是神经网络?为了开篇,我会介绍一种叫作感知机的人造神经元。感知机是由科学家Frank RosenblattWarren McCullochWalter Pitts早期工作的启发下,于20世纪5060年代发明的。在今天,使用其他的人工神经元模型更为流行—在本书和多数现代的神经网络工作中,主要使用的人工神经元模型被称作Sigmoid神经元。我们很快就会讲到这个,但为了理解Sigmoid神经元的定义,以及它是如何被定义的,花一些时间来了解感知机是值得的。

所以感知机是如何工作的?一个感知机采用一组二值化数据作为输入,比如x1,x2,…,并输出一个01

[译][待续]Chap1.Using neural nets to recognize handwritten digits

例子里展示了这个感知机具有三个输入值,x1,x2,x3。一般地,感知机也可以有更多或者更少的输入值。Rosenblatt提出了一条简单的规则来产生输出。他使用权值(weights)w1,w2,…,一些实数来表示不同输入的重要性。这类神经元的输出,具体是0还是1,取决于输入值加权求和之后 ( )是大于,还是小于阈值(threshold value)。就和权值(weights)一样,阈值(threshold)也是一个实数,并是神经元的一个参数。将以上规则通过更严谨的代数形式表达出来就是:

[译][待续]Chap1.Using neural nets to recognize handwritten digits

这就是感知机工作的所有原理。

以上是最基础的数学模型。一种对感知机的理解就是,它是一种通过权衡输入进行决策的机器。让我举个例子,它可能不是一个现实的例子,但非常好理解。现在假设周末将至,而你听说在你的城市即将会举行一个奶酪节。你喜欢奶酪,并且正准备做决定去还是不去。你有可能对以下三个因素进行权衡,再做决定。

  1. 天气是否良好?

  2. 你的男/女票有打算陪你一起去吗?

  3. 这个奶酪节的公共交通方不方便?(假设你没有车)

我们用三个二值化变量x1,x2,x3代表这三个因素。令x1=1代表天气良好,x1=0代表天气很坏。相似的,x2=1代表有人陪你,x2=0代表你没人陪。再同样的,x3的值代表着交通状况是否方便。

现在,让我们假设你特别喜欢奶酪,喜欢到不管男/女票有没有兴趣陪你,如果能去奶酪节的话你都会非常开心。但你又非常、非常厌恶坏天气,而且天气一坏交通就特别不方便。你可以使用感知机来给这类决策建模。一种方法是赋予一个权值(weight)w1=6给天气,w2=2w3=2给其他的变量。w1的值越大,意味着天气对你的影响越大,远比男/女票去不去、公共交通是否邻近重要。

通过改变权值(weight)和阈值(threshold),我们能获得不同的决策模型。举个例子,假设我们将阈值(threshold)设为3。这样感知机就会作出选择,只要是好天气,或者交通良好并且男/女票愿意陪同的时候你就应该去参加奶酪节。换一句话说,这将变成一个不同的决策模型。调低阈值(threshold)意味着你更倾向于参加奶酪节。

显然地,感知机不是一个完整的人类决策模型。但这个例子揭示的是,感知机是如何通过对凭据施加权重,从而做出决策的。利用一个复杂的感知机网络作出十分精细的决策,似乎可行:

[译][待续]Chap1.Using neural nets to recognize handwritten digits

在这个网络里,第一列的感知机——我们将它们称作第一层感知机,通过对输入进行加权,做出三个非常简单的决策。那第二层感知机又是干什么的呢?这一层的每一个感知机,都把第一层感知机的输出作为自己的输入,通过进行加权做出自己的决策。这样的话,第二层的感知机就能相对第一层感知机,在更复杂和抽象的层次上进行决策。同理,第三层的感知机也能做出比上一层更复杂的决策。以此类推,一个多层感知机网络能够做出复杂而又巧妙的决策。

顺便的,我在定义感知机的时候说过它只有一个输出。然而在上图展示的网络中,感知机似乎具有很多个输出。事实上,感知机仍然只有一个输出,这些代表输出的箭头只是一种常见的表达方式,用来表示该感知机的输出被多个感知机用作输入。这比把图画成完全单输出的形式要简明一些。

让我们再简化一下感知机的描述。 ∑ j w j x j >threshold  这种表示方法繁琐而冗长,我们可以改变两种符号约定来简化它。首先我们将∑ j w j x j 写成点积的形式,令 w⋅x≡∑ j w j x j,其中w和x各自代表权值(weight)和输入(input)向量。接下来我们把阈值(threshold)移项到不等号的另一端,并且用感知机偏差 b≡−threshold  替换阈值。经过这样的处理,我们可以把感知机的逻辑用以下形式表达:

[译][待续]Chap1.Using neural nets to recognize handwritten digits

你可以把这个偏置看作是对神经元输出1难易程度的衡量。或者从生物学角度考虑,这个偏执是神经元激活的一个门槛。对于有着大偏置的神经元,激活它们使其输出1是非常容易的。但是如果这个偏置是一个很小的负数,那么激活它就是一件很苦难的事了。显然地,介绍偏置这个概念只是我们对神经元概念描述的一个小小的变动,但过一会我们会发现它能引入更简化的符号形式。正是出于这方面的考虑,在本书我们不是用阈值(threshold)这个概念,而是使用偏置(bias)。

我已经介绍了神经元是对凭据施加权重进行决策的一种方法。在另一个层面上,神经元可以用作基础逻辑运算单元。比如与逻辑 (AND)、或逻辑(OR)、与非逻辑(NAND)。举个例子,假设我们有一个二输入的神经元,且其权值均为-2,而偏置为3,则以下有这个神经元:

[译][待续]Chap1.Using neural nets to recognize handwritten digits

我们知道,此时如果输入00则能够得到输出1,因为(-2)*0+(-2)*0+3=3大于0。在这里,我用“*”号来描述显式乘法。同样的,我们输入01或者10时都能得到输出1。但是如果输入11则会得到输出0,因为(-2)*1+(-2)*1+3=-1小于0。至此我们发现,这个神经元其实就是一个与非门(NAND gate)!

这个与非门(NAND gate)的例子告诉我们,我们可以利用神经元来构造基础逻辑运算单元。事实上,我们利用神经元构造一个网络,来表示任意的逻辑运算。原因在于与非门(NAND Gate)对于逻辑运算来说具有最普遍的性质,我们可以利用与非门(NAND gate)构造任何逻辑运算。举个例子,我们可以用与非门(NAND gate)来构造一个2比特加法器(x1和x2)。这需要按位进行计算,x1⊕x2,当x1与x2均为1时,按照二进制加法,它们相加时就需要在进位位上加1。换言之进位位的值只是x1、x2按位计算的产物:

[译][待续]Chap1.Using neural nets to recognize handwritten digits

我们把所有的与非门(NAND gate)替换成二输入、权值(weight)均为-2、偏置为3的神经元,就能得到一个等效网络。以下就是等效后的网络,请注意我把等效右下角与非门的神经元稍微挪动了一下,不过仅仅是为了让图示的箭头更好画而已:

[译][待续]Chap1.Using neural nets to recognize handwritten digits

一个值得注意的地方是,最左侧神经元的输出被两次用作最下面神经元的输入。之前在定义神经元的时候,我没说过这种对单一神经元的二重输出是可以的。事实上,这不算啥事。如果我们真不允许这种情况,解决办法也很简单。我们可以把最下面那个神经元的输入权重从-2更改为-4,然后最左侧神经元的二重输出就能等效成一个单输出了。(如果这种说法你理解起来很困难,那你应该停下来好好琢磨这为什么是等效的。)作了以上改变之后,网络如下所示。未标示的权值均为-2,所有神经元的偏置都是3,其中一个神经元的输入权值是-4,具体如标记所示: